Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2021
- 83 participants
- 2620 messages
[PATCH v2 4/5] strmbase: Send EC_COMPLETE in IBaseFilter::Run() for unconnected renderers.
by Zebediah Figura
From: Andrew Eikum <aeikum(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/evr/tests/evr.c | 6 +++---
dlls/qedit/tests/nullrenderer.c | 6 +++---
dlls/quartz/tests/videorenderer.c | 6 +++---
dlls/quartz/tests/vmr7.c | 6 +++---
dlls/quartz/tests/vmr9.c | 6 +++---
dlls/strmbase/renderer.c | 2 +-
6 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index 8bfeb987352..48115388993 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -508,7 +508,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Pause(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -520,7 +520,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -532,7 +532,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
IMediaControl_Release(control);
IMediaEvent_Release(eventsrc);
diff --git a/dlls/qedit/tests/nullrenderer.c b/dlls/qedit/tests/nullrenderer.c
index b4003f43cf4..cfbf1d37c2f 100644
--- a/dlls/qedit/tests/nullrenderer.c
+++ b/dlls/qedit/tests/nullrenderer.c
@@ -969,7 +969,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Pause(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -981,7 +981,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -993,7 +993,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
IMediaControl_Release(control);
IMediaEvent_Release(eventsrc);
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index 0ce24884200..5625971426b 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -2897,7 +2897,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Pause(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -2909,7 +2909,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -2921,7 +2921,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
IMediaControl_Release(control);
IMediaEvent_Release(eventsrc);
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index 1214d5dcbb7..efc876a845c 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -3101,7 +3101,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Pause(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -3113,7 +3113,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -3125,7 +3125,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
IMediaControl_Release(control);
IMediaEvent_Release(eventsrc);
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 618669595cb..a0ccb4898a9 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -4202,7 +4202,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Pause(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -4214,7 +4214,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -4226,7 +4226,7 @@ static void test_unconnected_eos(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = check_ec_complete(eventsrc, 0);
- todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+ ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
IMediaControl_Release(control);
IMediaEvent_Release(eventsrc);
diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c
index a879917b169..da257555a19 100644
--- a/dlls/strmbase/renderer.c
+++ b/dlls/strmbase/renderer.c
@@ -252,7 +252,7 @@ static HRESULT renderer_start_stream(struct strmbase_filter *iface, REFERENCE_TI
if (filter->sink.pin.peer && filter->ops->renderer_start_stream)
filter->ops->renderer_start_stream(filter);
- if (filter->eos && graph
+ if ((filter->eos || !filter->sink.pin.peer) && graph
&& SUCCEEDED(IFilterGraph_QueryInterface(graph,
&IID_IMediaEventSink, (void **)&event_sink)))
{
--
2.33.0
Nov. 1, 2021
[PATCH v2 3/5] qedit/tests: Test receiving EC_COMPLETE when not connected.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/qedit/tests/nullrenderer.c | 104 ++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/dlls/qedit/tests/nullrenderer.c b/dlls/qedit/tests/nullrenderer.c
index 1800f4dad4c..b4003f43cf4 100644
--- a/dlls/qedit/tests/nullrenderer.c
+++ b/dlls/qedit/tests/nullrenderer.c
@@ -32,6 +32,15 @@ static IBaseFilter *create_null_renderer(void)
return filter;
}
+static IFilterGraph2 *create_graph(void)
+{
+ IFilterGraph2 *ret;
+ HRESULT hr;
+ hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (void **)&ret);
+ ok(hr == S_OK, "Failed to create FilterGraph: %#x\n", hr);
+ return ret;
+}
+
static ULONG get_refcount(void *iface)
{
IUnknown *unknown = iface;
@@ -791,6 +800,34 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph)
IMediaControl_Release(control);
}
+static unsigned int check_event_code(IMediaEvent *eventsrc, DWORD timeout, LONG expected_code, LONG_PTR expected1, LONG_PTR expected2)
+{
+ LONG_PTR param1, param2;
+ unsigned int ret = 0;
+ HRESULT hr;
+ LONG code;
+
+ while ((hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, timeout)) == S_OK)
+ {
+ if (code == expected_code)
+ {
+ ok(param1 == expected1, "Got param1 %#lx.\n", param1);
+ ok(param2 == expected2, "Got param2 %#lx.\n", param2);
+ ret++;
+ }
+ IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ timeout = 0;
+ }
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ return ret;
+}
+
+static unsigned int check_ec_complete(IMediaEvent *eventsrc, DWORD timeout)
+{
+ return check_event_code(eventsrc, timeout, EC_COMPLETE, S_OK, 0);
+}
+
static void test_connect_pin(void)
{
static const AM_MEDIA_TYPE req_mt =
@@ -900,6 +937,72 @@ static void test_connect_pin(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_unconnected_eos(void)
+{
+ IBaseFilter *filter = create_null_renderer();
+ IFilterGraph2 *graph = create_graph();
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ unsigned int ret;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = IFilterGraph2_AddFilter(graph, filter, L"renderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
START_TEST(nullrenderer)
{
IBaseFilter *filter;
@@ -924,6 +1027,7 @@ START_TEST(nullrenderer)
test_media_types();
test_enum_media_types();
test_connect_pin();
+ test_unconnected_eos();
CoUninitialize();
}
--
2.33.0
Nov. 1, 2021
[PATCH v2 2/5] quartz/tests: Test receiving EC_COMPLETE when not connected.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/quartz/tests/dsoundrender.c | 76 +++++++++++++++++++++++++
dlls/quartz/tests/videorenderer.c | 67 ++++++++++++++++++++++
dlls/quartz/tests/vmr7.c | 95 +++++++++++++++++++++++++++++++
dlls/quartz/tests/vmr9.c | 67 ++++++++++++++++++++++
4 files changed, 305 insertions(+)
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c
index fdc23d2b48c..9107828b9df 100644
--- a/dlls/quartz/tests/dsoundrender.c
+++ b/dlls/quartz/tests/dsoundrender.c
@@ -40,6 +40,15 @@ static IBaseFilter *create_dsound_render(void)
return filter;
}
+static IFilterGraph2 *create_graph(void)
+{
+ IFilterGraph2 *ret;
+ HRESULT hr;
+ hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (void **)&ret);
+ ok(hr == S_OK, "Failed to create FilterGraph: %#x\n", hr);
+ return ret;
+}
+
static inline BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b)
{
return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat))
@@ -1314,6 +1323,72 @@ static void test_media_types(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_unconnected_eos(void)
+{
+ IBaseFilter *filter = create_dsound_render();
+ IFilterGraph2 *graph = create_graph();
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ unsigned int ret;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = IFilterGraph2_AddFilter(graph, filter, L"renderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
START_TEST(dsoundrender)
{
IBaseFilter *filter;
@@ -1343,6 +1418,7 @@ START_TEST(dsoundrender)
test_unconnected_filter_state();
test_media_types();
test_connect_pin();
+ test_unconnected_eos();
CoUninitialize();
}
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index 8d0003cf12e..0ce24884200 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -2865,6 +2865,72 @@ static void test_basic_video(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_unconnected_eos(void)
+{
+ IBaseFilter *filter = create_video_renderer();
+ IFilterGraph2 *graph = create_graph();
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ unsigned int ret;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = IFilterGraph2_AddFilter(graph, filter, L"renderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
START_TEST(videorenderer)
{
CoInitialize(NULL);
@@ -2881,6 +2947,7 @@ START_TEST(videorenderer)
test_overlay();
test_video_window();
test_basic_video();
+ test_unconnected_eos();
CoUninitialize();
}
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index 688770a8501..1214d5dcbb7 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1236,6 +1236,34 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control
ok(hr == S_OK, "Got hr %#x.\n", hr);
}
+static unsigned int check_event_code(IMediaEvent *eventsrc, DWORD timeout, LONG expected_code, LONG_PTR expected1, LONG_PTR expected2)
+{
+ LONG_PTR param1, param2;
+ unsigned int ret = 0;
+ HRESULT hr;
+ LONG code;
+
+ while ((hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, timeout)) == S_OK)
+ {
+ if (code == expected_code)
+ {
+ ok(param1 == expected1, "Got param1 %#lx.\n", param1);
+ ok(param2 == expected2, "Got param2 %#lx.\n", param2);
+ ret++;
+ }
+ IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ timeout = 0;
+ }
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ return ret;
+}
+
+static unsigned int check_ec_complete(IMediaEvent *eventsrc, DWORD timeout)
+{
+ return check_event_code(eventsrc, timeout, EC_COMPLETE, S_OK, 0);
+}
+
static void test_current_image(IBaseFilter *filter, IMemInputPin *input,
IMediaControl *control, const BITMAPINFOHEADER *req_bih)
{
@@ -3041,6 +3069,72 @@ out:
DestroyWindow(window);
}
+static void test_unconnected_eos(void)
+{
+ IFilterGraph2 *graph = create_graph();
+ IBaseFilter *filter = create_vmr7(0);
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ unsigned int ret;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = IFilterGraph2_AddFilter(graph, filter, L"renderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
START_TEST(vmr7)
{
CoInitialize(NULL);
@@ -3059,6 +3153,7 @@ START_TEST(vmr7)
test_video_window();
test_basic_video();
test_windowless_size();
+ test_unconnected_eos();
CoUninitialize();
}
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 154b6a6b99e..618669595cb 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -4170,6 +4170,72 @@ static void test_mixing_prefs(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_unconnected_eos(void)
+{
+ IFilterGraph2 *graph = create_graph();
+ IBaseFilter *filter = create_vmr9(0);
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ unsigned int ret;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = IFilterGraph2_AddFilter(graph, filter, L"renderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
START_TEST(vmr9)
{
IBaseFilter *filter;
@@ -4205,6 +4271,7 @@ START_TEST(vmr9)
test_basic_video();
test_windowless_size();
test_mixing_prefs();
+ test_unconnected_eos();
CoUninitialize();
}
--
2.33.0
Nov. 1, 2021
[PATCH v2 1/5] evr/tests: Test receiving EC_COMPLETE when not connected.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/evr/tests/evr.c | 106 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index 6a711e30581..8bfeb987352 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -84,6 +84,16 @@ static IBaseFilter *create_evr(void)
return filter;
}
+static IFilterGraph2 *create_graph(void)
+{
+ IFilterGraph2 *ret;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (void **)&ret);
+ ok(hr == S_OK, "Failed to create FilterGraph: %#x\n", hr);
+ return ret;
+}
+
static ULONG get_refcount(void *iface)
{
IUnknown *unknown = iface;
@@ -438,6 +448,100 @@ static void test_pin_info(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static unsigned int check_event_code(IMediaEvent *eventsrc, DWORD timeout, LONG expected_code, LONG_PTR expected1, LONG_PTR expected2)
+{
+ LONG_PTR param1, param2;
+ unsigned int ret = 0;
+ HRESULT hr;
+ LONG code;
+
+ while ((hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, timeout)) == S_OK)
+ {
+ if (code == expected_code)
+ {
+ ok(param1 == expected1, "Got param1 %#lx.\n", param1);
+ ok(param2 == expected2, "Got param2 %#lx.\n", param2);
+ ret++;
+ }
+ IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ timeout = 0;
+ }
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ return ret;
+}
+
+static unsigned int check_ec_complete(IMediaEvent *eventsrc, DWORD timeout)
+{
+ return check_event_code(eventsrc, timeout, EC_COMPLETE, S_OK, 0);
+}
+
+static void test_unconnected_eos(void)
+{
+ IBaseFilter *filter = create_evr();
+ IFilterGraph2 *graph = create_graph();
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ unsigned int ret;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = IFilterGraph2_AddFilter(graph, filter, L"renderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got %u EC_COMPLETE events.\n", ret);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Got %u EC_COMPLETE events.\n", ret);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
static IMFMediaType * create_video_type(const GUID *subtype)
{
IMFMediaType *video_type;
@@ -2952,6 +3056,8 @@ START_TEST(evr)
test_enum_pins();
test_find_pin();
test_pin_info();
+ test_unconnected_eos();
+
test_default_mixer();
test_default_mixer_type_negotiation();
test_surface_sample();
--
2.33.0
Nov. 1, 2021
[PATCH 6/6] winegstreamer: Seek to the beginning of the range in wm_reader_set_output_props().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 2 ++
dlls/winegstreamer/wm_reader.c | 18 ++++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index d330716b8f9..109ce6ab28f 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -136,6 +136,8 @@ struct wm_reader
LONG refcount;
CRITICAL_SECTION cs;
+ QWORD start_time;
+
IStream *source_stream;
HANDLE read_thread;
bool read_thread_shutdown;
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 24fd11f652d..82f74318062 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1543,6 +1543,22 @@ HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
stream->format = format;
wg_parser_stream_enable(stream->wg_stream, &format);
+ /* Re-decode any buffers that might have been generated with the old format.
+ *
+ * FIXME: Seeking in-place will cause some buffers to be dropped.
+ * Unfortunately, we can't really store the last received PTS and seek there
+ * either: since seeks are inexact and we aren't guaranteed to receive
+ * samples in order, some buffers might be duplicated or dropped anyway.
+ * In order to really seamlessly allow for format changes, we need
+ * cooperation from each individual GStreamer stream, to be able to tell
+ * upstream exactly which buffers they need resent...
+ *
+ * In all likelihood this function is being called not mid-stream but rather
+ * while setting the stream up, before consuming any events. Accordingly
+ * let's just seek back to the beginning. */
+ wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, reader->start_time, 0,
+ AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
+
LeaveCriticalSection(&reader->cs);
return S_OK;
}
@@ -1643,6 +1659,8 @@ void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration)
EnterCriticalSection(&reader->cs);
+ reader->start_time = start;
+
wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, start, start + duration,
AM_SEEKING_AbsolutePositioning, duration ? AM_SEEKING_AbsolutePositioning : AM_SEEKING_NoPositioning);
--
2.33.0
Nov. 1, 2021
[PATCH 5/6] winegstreamer: Implement IWMSyncReader::SetRange().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/wm_reader.c | 15 +++++++++++++++
dlls/winegstreamer/wm_syncreader.c | 9 ++++++---
dlls/wmvcore/tests/wmvcore.c | 17 +++++++----------
4 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index a9c361366b3..d330716b8f9 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -166,6 +166,7 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
INSSBuffer **sample, QWORD *pts, QWORD *duration, DWORD *flags);
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops);
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
+void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration);
HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
IWMOutputMediaProps *props);
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index e708ed4bfa6..24fd11f652d 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1637,6 +1637,21 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
}
}
+void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration)
+{
+ WORD i;
+
+ EnterCriticalSection(&reader->cs);
+
+ wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, start, start + duration,
+ AM_SEEKING_AbsolutePositioning, duration ? AM_SEEKING_AbsolutePositioning : AM_SEEKING_NoPositioning);
+
+ for (i = 0; i < reader->stream_count; ++i)
+ reader->streams[i].eos = false;
+
+ LeaveCriticalSection(&reader->cs);
+}
+
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
{
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;
diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c
index 063be2a94ab..1f5827cf244 100644
--- a/dlls/winegstreamer/wm_syncreader.c
+++ b/dlls/winegstreamer/wm_syncreader.c
@@ -259,9 +259,12 @@ static HRESULT WINAPI WMSyncReader_SetOutputSetting(IWMSyncReader2 *iface, DWORD
static HRESULT WINAPI WMSyncReader_SetRange(IWMSyncReader2 *iface, QWORD start, LONGLONG duration)
{
- struct sync_reader *This = impl_from_IWMSyncReader2(iface);
- FIXME("(%p)->(%s %s): stub!\n", This, wine_dbgstr_longlong(start), wine_dbgstr_longlong(duration));
- return E_NOTIMPL;
+ struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
+
+ TRACE("reader %p, start %I64u, duration %I64d.\n", reader, start, duration);
+
+ wm_reader_seek(&reader->reader, start, duration);
+ return S_OK;
}
static HRESULT WINAPI WMSyncReader_SetRangeByFrame(IWMSyncReader2 *iface, WORD stream_num, QWORD frame_num,
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 48d585e73c0..6e196234208 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -542,25 +542,22 @@ static void test_sync_reader_streaming(void)
ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
hr = IWMSyncReader_SetRange(reader, 0, 0);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample, &pts, &duration, &flags, NULL, NULL);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (hr == S_OK)
- INSSBuffer_Release(sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ INSSBuffer_Release(sample);
hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, NULL);
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, &output_number, NULL);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (hr == S_OK)
- INSSBuffer_Release(sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ INSSBuffer_Release(sample);
hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, &stream_number);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (hr == S_OK)
- INSSBuffer_Release(sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ INSSBuffer_Release(sample);
for (;;)
{
--
2.33.0
Nov. 1, 2021
[PATCH 4/6] winegstreamer: Implement reading from all streams in IWMSyncReader::GetNextSample().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/wm_syncreader.c | 29 +++++++++++++++++++++++++++--
dlls/wmvcore/tests/wmvcore.c | 6 +++---
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c
index a2cc747e9bf..063be2a94ab 100644
--- a/dlls/winegstreamer/wm_syncreader.c
+++ b/dlls/winegstreamer/wm_syncreader.c
@@ -25,6 +25,8 @@ struct sync_reader
struct wm_reader reader;
IWMSyncReader2 IWMSyncReader2_iface;
+
+ WORD last_read_stream;
};
static struct sync_reader *impl_from_IWMSyncReader2(IWMSyncReader2 *iface)
@@ -83,6 +85,7 @@ static HRESULT WINAPI WMSyncReader_GetNextSample(IWMSyncReader2 *iface,
struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
struct wm_stream *stream;
HRESULT hr;
+ WORD i;
TRACE("reader %p, stream_number %u, sample %p, pts %p, duration %p,"
" flags %p, output_number %p, ret_stream_number %p.\n",
@@ -92,8 +95,30 @@ static HRESULT WINAPI WMSyncReader_GetNextSample(IWMSyncReader2 *iface,
if (!stream_number)
{
- FIXME("Reading from all streams is not implemented yet.\n");
- hr = E_NOTIMPL;
+ if (!output_number && !ret_stream_number)
+ {
+ LeaveCriticalSection(&reader->reader.cs);
+ return E_INVALIDARG;
+ }
+
+ for (i = 0; i < reader->reader.stream_count; ++i)
+ {
+ WORD index = (i + reader->last_read_stream + 1) % reader->reader.stream_count;
+
+ hr = wm_reader_get_stream_sample(&reader->reader.streams[index], sample, pts, duration, flags);
+ if (hr == S_OK)
+ {
+ if (output_number)
+ *output_number = index;
+ if (ret_stream_number)
+ *ret_stream_number = index + 1;
+ }
+ if (hr != NS_E_NO_MORE_SAMPLES)
+ {
+ reader->last_read_stream = index;
+ break;
+ }
+ }
}
else
{
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 419dea2f68d..48d585e73c0 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -550,7 +550,7 @@ static void test_sync_reader_streaming(void)
INSSBuffer_Release(sample);
hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, NULL);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, &output_number, NULL);
todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -567,7 +567,7 @@ static void test_sync_reader_streaming(void)
stream_number = pts = duration = flags = output_number = 0xdeadbeef;
hr = IWMSyncReader_GetNextSample(reader, 0, &sample,
&pts, &duration, &flags, &output_number, &stream_number);
- todo_wine ok(hr == S_OK || hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ ok(hr == S_OK || hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
if (hr == S_OK)
{
@@ -589,7 +589,7 @@ static void test_sync_reader_streaming(void)
hr = IWMSyncReader_GetNextSample(reader, 0, &sample,
&pts, &duration, &flags, NULL, &stream_number);
- todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
&pts, &duration, &flags, NULL, NULL);
--
2.33.0
Nov. 1, 2021
[PATCH 3/6] winegstreamer: Implement INSSBuffer::GetBufferAndLength().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/wm_reader.c | 22 +++++++++++++++++++---
dlls/wmvcore/tests/wmvcore.c | 2 +-
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 71adfac5a42..e708ed4bfa6 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -171,6 +171,9 @@ struct buffer
{
INSSBuffer INSSBuffer_iface;
LONG refcount;
+
+ DWORD size;
+ BYTE data[1];
};
static struct buffer *impl_from_INSSBuffer(INSSBuffer *iface)
@@ -246,8 +249,13 @@ static HRESULT WINAPI buffer_GetBuffer(INSSBuffer *iface, BYTE **data)
static HRESULT WINAPI buffer_GetBufferAndLength(INSSBuffer *iface, BYTE **data, DWORD *size)
{
- FIXME("iface %p, data %p, size %p, stub!\n", iface, data, size);
- return E_NOTIMPL;
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ TRACE("buffer %p, data %p, size %p.\n", buffer, data, size);
+
+ *size = buffer->size;
+ *data = buffer->data;
+ return S_OK;
}
static const INSSBufferVtbl buffer_vtbl =
@@ -1579,7 +1587,7 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
{
case WG_PARSER_EVENT_BUFFER:
/* FIXME: Should these be pooled? */
- if (!(object = calloc(1, sizeof(*object))))
+ if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size]))))
{
wg_parser_stream_release_buffer(wg_stream);
return E_OUTOFMEMORY;
@@ -1587,6 +1595,14 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
object->refcount = 1;
+ object->size = event.u.buffer.size;
+
+ if (!wg_parser_stream_copy_buffer(wg_stream, object->data, 0, object->size))
+ {
+ /* The GStreamer pin has been flushed. */
+ free(object);
+ break;
+ }
wg_parser_stream_release_buffer(wg_stream);
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index dabeb054530..419dea2f68d 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -509,7 +509,7 @@ static void test_sync_reader_streaming(void)
if (hr == S_OK)
{
hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
ref = INSSBuffer_Release(sample);
ok(!ref, "Got outstanding refcount %d.\n", ref);
--
2.33.0
Nov. 1, 2021
[PATCH 2/6] winegstreamer: Implement IWMSyncReader::GetNextSample().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 5 +
dlls/winegstreamer/wm_reader.c | 192 +++++++++++++++++++++++++++++
dlls/winegstreamer/wm_syncreader.c | 41 +++++-
dlls/wmvcore/tests/wmvcore.c | 12 +-
include/wmsdkidl.idl | 7 ++
5 files changed, 245 insertions(+), 12 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 278fc132ccf..a9c361366b3 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -121,6 +121,7 @@ struct wm_stream
struct wm_reader *reader;
struct wg_parser_stream *wg_stream;
WORD index;
+ bool eos;
struct wg_format format;
};
@@ -159,6 +160,10 @@ HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output, DWORD *count);
HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output,
IWMOutputMediaProps **props);
+struct wm_stream *wm_reader_get_stream_by_stream_number(struct wm_reader *reader,
+ WORD stream_number);
+HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
+ INSSBuffer **sample, QWORD *pts, QWORD *duration, DWORD *flags);
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops);
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 21e08b5834f..71adfac5a42 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -167,6 +167,101 @@ static IWMOutputMediaProps *output_props_create(const struct wg_format *format)
return &object->IWMOutputMediaProps_iface;
}
+struct buffer
+{
+ INSSBuffer INSSBuffer_iface;
+ LONG refcount;
+};
+
+static struct buffer *impl_from_INSSBuffer(INSSBuffer *iface)
+{
+ return CONTAINING_RECORD(iface, struct buffer, INSSBuffer_iface);
+}
+
+static HRESULT WINAPI buffer_QueryInterface(INSSBuffer *iface, REFIID iid, void **out)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ TRACE("buffer %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_INSSBuffer))
+ *out = &buffer->INSSBuffer_iface;
+ else
+ {
+ *out = NULL;
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
+static ULONG WINAPI buffer_AddRef(INSSBuffer *iface)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+ ULONG refcount = InterlockedIncrement(&buffer->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", buffer, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI buffer_Release(INSSBuffer *iface)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+ ULONG refcount = InterlockedDecrement(&buffer->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", buffer, refcount);
+
+ if (!refcount)
+ free(buffer);
+
+ return refcount;
+}
+
+static HRESULT WINAPI buffer_GetLength(INSSBuffer *iface, DWORD *size)
+{
+ FIXME("iface %p, size %p, stub!\n", iface, size);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI buffer_SetLength(INSSBuffer *iface, DWORD size)
+{
+ FIXME("iface %p, size %u, stub!\n", iface, size);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI buffer_GetMaxLength(INSSBuffer *iface, DWORD *size)
+{
+ FIXME("iface %p, size %p, stub!\n", iface, size);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI buffer_GetBuffer(INSSBuffer *iface, BYTE **data)
+{
+ FIXME("iface %p, data %p, stub!\n", iface, data);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI buffer_GetBufferAndLength(INSSBuffer *iface, BYTE **data, DWORD *size)
+{
+ FIXME("iface %p, data %p, size %p, stub!\n", iface, data, size);
+ return E_NOTIMPL;
+}
+
+static const INSSBufferVtbl buffer_vtbl =
+{
+ buffer_QueryInterface,
+ buffer_AddRef,
+ buffer_Release,
+ buffer_GetLength,
+ buffer_SetLength,
+ buffer_GetMaxLength,
+ buffer_GetBuffer,
+ buffer_GetBufferAndLength,
+};
+
struct stream_config
{
IWMStreamConfig IWMStreamConfig_iface;
@@ -1231,8 +1326,15 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
if (stream->format.u.video.format == WG_VIDEO_FORMAT_I420)
stream->format.u.video.format = WG_VIDEO_FORMAT_YV12;
}
+ wg_parser_stream_enable(stream->wg_stream, &stream->format);
}
+ wg_parser_end_flush(reader->wg_parser);
+ /* We probably discarded events because streams weren't enabled yet.
+ * Now that they're all enabled seek back to the start again. */
+ wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, 0, 0,
+ AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
+
LeaveCriticalSection(&reader->cs);
return S_OK;
@@ -1281,6 +1383,14 @@ HRESULT wm_reader_close(struct wm_reader *reader)
return S_OK;
}
+struct wm_stream *wm_reader_get_stream_by_stream_number(struct wm_reader *reader, WORD stream_number)
+{
+ if (stream_number && stream_number <= reader->stream_count)
+ return &reader->streams[stream_number - 1];
+ WARN("Invalid stream number %u.\n", stream_number);
+ return NULL;
+}
+
HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOutputMediaProps **props)
{
struct wm_stream *stream;
@@ -1429,6 +1539,88 @@ HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
return S_OK;
}
+static const char *get_major_type_string(enum wg_major_type type)
+{
+ switch (type)
+ {
+ case WG_MAJOR_TYPE_AUDIO:
+ return "audio";
+ case WG_MAJOR_TYPE_VIDEO:
+ return "video";
+ case WG_MAJOR_TYPE_UNKNOWN:
+ return "unknown";
+ }
+ assert(0);
+ return NULL;
+}
+
+HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
+ INSSBuffer **ret_sample, QWORD *pts, QWORD *duration, DWORD *flags)
+{
+ struct wg_parser_stream *wg_stream = stream->wg_stream;
+ struct wg_parser_event event;
+ struct buffer *object;
+
+ if (stream->eos)
+ return NS_E_NO_MORE_SAMPLES;
+
+ for (;;)
+ {
+ if (!wg_parser_stream_get_event(wg_stream, &event))
+ {
+ FIXME("Stream is flushing.\n");
+ return E_NOTIMPL;
+ }
+
+ TRACE("Got event of type %#x for %s stream %p.\n", event.type,
+ get_major_type_string(stream->format.major_type), stream);
+
+ switch (event.type)
+ {
+ case WG_PARSER_EVENT_BUFFER:
+ /* FIXME: Should these be pooled? */
+ if (!(object = calloc(1, sizeof(*object))))
+ {
+ wg_parser_stream_release_buffer(wg_stream);
+ return E_OUTOFMEMORY;
+ }
+
+ object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
+ object->refcount = 1;
+
+ wg_parser_stream_release_buffer(wg_stream);
+
+ if (!event.u.buffer.has_pts)
+ FIXME("Missing PTS.\n");
+ if (!event.u.buffer.has_duration)
+ FIXME("Missing duration.\n");
+
+ *pts = event.u.buffer.pts;
+ *duration = event.u.buffer.duration;
+ *flags = 0;
+ if (event.u.buffer.discontinuity)
+ *flags |= WM_SF_DISCONTINUITY;
+ if (!event.u.buffer.delta)
+ *flags |= WM_SF_CLEANPOINT;
+
+ TRACE("Created buffer %p.\n", object);
+ *ret_sample = &object->INSSBuffer_iface;
+ return S_OK;
+
+ case WG_PARSER_EVENT_EOS:
+ stream->eos = true;
+ TRACE("End of stream.\n");
+ return NS_E_NO_MORE_SAMPLES;
+
+ case WG_PARSER_EVENT_SEGMENT:
+ break;
+
+ case WG_PARSER_EVENT_NONE:
+ assert(0);
+ }
+ }
+}
+
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
{
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;
diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c
index f9728211661..a2cc747e9bf 100644
--- a/dlls/winegstreamer/wm_syncreader.c
+++ b/dlls/winegstreamer/wm_syncreader.c
@@ -76,13 +76,42 @@ static HRESULT WINAPI WMSyncReader_GetMaxStreamSampleSize(IWMSyncReader2 *iface,
return E_NOTIMPL;
}
-static HRESULT WINAPI WMSyncReader_GetNextSample(IWMSyncReader2 *iface, WORD stream, INSSBuffer **sample,
- QWORD *sample_time, QWORD *sample_duration, DWORD *flags, DWORD *output_num, WORD *stream_num)
+static HRESULT WINAPI WMSyncReader_GetNextSample(IWMSyncReader2 *iface,
+ WORD stream_number, INSSBuffer **sample, QWORD *pts, QWORD *duration,
+ DWORD *flags, DWORD *output_number, WORD *ret_stream_number)
{
- struct sync_reader *This = impl_from_IWMSyncReader2(iface);
- FIXME("(%p)->(%d %p %p %p %p %p %p): stub!\n", This, stream, sample, sample_time,
- sample_duration, flags, output_num, stream_num);
- return E_NOTIMPL;
+ struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
+ struct wm_stream *stream;
+ HRESULT hr;
+
+ TRACE("reader %p, stream_number %u, sample %p, pts %p, duration %p,"
+ " flags %p, output_number %p, ret_stream_number %p.\n",
+ reader, stream_number, sample, pts, duration, flags, output_number, ret_stream_number);
+
+ EnterCriticalSection(&reader->reader.cs);
+
+ if (!stream_number)
+ {
+ FIXME("Reading from all streams is not implemented yet.\n");
+ hr = E_NOTIMPL;
+ }
+ else
+ {
+ if (!(stream = wm_reader_get_stream_by_stream_number(&reader->reader, stream_number)))
+ {
+ LeaveCriticalSection(&reader->reader.cs);
+ return E_INVALIDARG;
+ }
+
+ hr = wm_reader_get_stream_sample(stream, sample, pts, duration, flags);
+ if (hr == S_OK && output_number)
+ *output_number = stream->index;
+ if (ret_stream_number)
+ *ret_stream_number = stream->index + 1;
+ }
+
+ LeaveCriticalSection(&reader->reader.cs);
+ return hr;
}
static HRESULT WINAPI WMSyncReader_GetOutputCount(IWMSyncReader2 *iface, DWORD *count)
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index e07e6241a4c..dabeb054530 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -500,7 +500,7 @@ static void test_sync_reader_streaming(void)
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[j], &sample,
&pts, &duration, &flags, &output_number, &stream_number);
if (first)
- todo_wine ok(hr == S_OK, "Expected at least one valid sample; got hr %#x.\n", hr);
+ ok(hr == S_OK, "Expected at least one valid sample; got hr %#x.\n", hr);
else if (eos[j])
ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
else
@@ -527,7 +527,7 @@ static void test_sync_reader_streaming(void)
eos[j] = true;
}
- todo_wine ok(stream_number == stream_numbers[j], "Expected stream number %u, got %u.\n",
+ ok(stream_number == stream_numbers[j], "Expected stream number %u, got %u.\n",
stream_numbers[j], stream_number);
}
first = false;
@@ -535,11 +535,11 @@ static void test_sync_reader_streaming(void)
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
&pts, &duration, &flags, NULL, NULL);
- todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[1], &sample,
&pts, &duration, &flags, NULL, NULL);
- todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
hr = IWMSyncReader_SetRange(reader, 0, 0);
todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -593,11 +593,11 @@ static void test_sync_reader_streaming(void)
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
&pts, &duration, &flags, NULL, NULL);
- todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetNextSample(reader, stream_numbers[1], &sample,
&pts, &duration, &flags, NULL, NULL);
- todo_wine ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
hr = IWMSyncReader_Close(reader);
ok(hr == S_OK, "Got hr %#x.\n", hr);
diff --git a/include/wmsdkidl.idl b/include/wmsdkidl.idl
index f276d642a03..55142f47e93 100644
--- a/include/wmsdkidl.idl
+++ b/include/wmsdkidl.idl
@@ -81,6 +81,13 @@ typedef struct _WMReaderClientInfo
WCHAR *wszPlayerUserAgent;
} WM_READER_CLIENTINFO;
+enum
+{
+ WM_SF_CLEANPOINT = 0x1,
+ WM_SF_DISCONTINUITY = 0x2,
+ WM_SF_DATALOSS = 0x4,
+};
+
typedef enum WMT_ATTR_DATATYPE
{
WMT_TYPE_DWORD = 0,
--
2.33.0
Nov. 1, 2021
[PATCH 1/6] winegstreamer: Implement IWMSyncReader::SetOutputProps().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 3 ++
dlls/winegstreamer/quartz_parser.c | 2 +-
dlls/winegstreamer/wm_reader.c | 47 ++++++++++++++++++++++++++++++
dlls/winegstreamer/wm_syncreader.c | 10 ++++---
dlls/wmvcore/tests/wmvcore.c | 9 +-----
5 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 9219a86c094..278fc132ccf 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -102,6 +102,7 @@ HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
HRESULT wave_parser_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format);
+bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format);
BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
@@ -160,5 +161,7 @@ HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output,
IWMOutputMediaProps **props);
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops);
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
+HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
+ IWMOutputMediaProps *props);
#endif /* __GST_PRIVATE_INCLUDED__ */
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 0862a75b7ef..4e7e22a64ea 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -540,7 +540,7 @@ static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *fo
return false;
}
-static bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
+bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
memset(format, 0, sizeof(*format));
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 79a89c9a332..21e08b5834f 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -140,6 +140,14 @@ static const struct IWMOutputMediaPropsVtbl output_props_vtbl =
output_props_GetConnectionName,
};
+static struct output_props *unsafe_impl_from_IWMOutputMediaProps(IWMOutputMediaProps *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &output_props_vtbl);
+ return impl_from_IWMOutputMediaProps(iface);
+}
+
static IWMOutputMediaProps *output_props_create(const struct wg_format *format)
{
struct output_props *object;
@@ -1382,6 +1390,45 @@ HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
return *props ? S_OK : E_OUTOFMEMORY;
}
+HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
+ IWMOutputMediaProps *props_iface)
+{
+ struct output_props *props = unsafe_impl_from_IWMOutputMediaProps(props_iface);
+ struct wg_format format, pref_format;
+ struct wm_stream *stream;
+
+ strmbase_dump_media_type(&props->mt);
+
+ if (!amt_to_wg_format(&props->mt, &format))
+ {
+ ERR("Failed to convert media type to winegstreamer format.\n");
+ return E_FAIL;
+ }
+
+ EnterCriticalSection(&reader->cs);
+
+ if (!(stream = get_stream_by_output_number(reader, output)))
+ {
+ LeaveCriticalSection(&reader->cs);
+ return E_INVALIDARG;
+ }
+
+ wg_parser_stream_get_preferred_format(stream->wg_stream, &pref_format);
+ if (pref_format.major_type != format.major_type)
+ {
+ /* R.U.S.E sets the type of the wrong stream, apparently by accident. */
+ LeaveCriticalSection(&reader->cs);
+ WARN("Major types don't match; returning NS_E_INCOMPATIBLE_FORMAT.\n");
+ return NS_E_INCOMPATIBLE_FORMAT;
+ }
+
+ stream->format = format;
+ wg_parser_stream_enable(stream->wg_stream, &format);
+
+ LeaveCriticalSection(&reader->cs);
+ return S_OK;
+}
+
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
{
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;
diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c
index 54c53dee3bd..f9728211661 100644
--- a/dlls/winegstreamer/wm_syncreader.c
+++ b/dlls/winegstreamer/wm_syncreader.c
@@ -186,11 +186,13 @@ static HRESULT WINAPI WMSyncReader_OpenStream(IWMSyncReader2 *iface, IStream *st
return wm_reader_open_stream(&reader->reader, stream);
}
-static HRESULT WINAPI WMSyncReader_SetOutputProps(IWMSyncReader2 *iface, DWORD output_num, IWMOutputMediaProps *output)
+static HRESULT WINAPI WMSyncReader_SetOutputProps(IWMSyncReader2 *iface, DWORD output, IWMOutputMediaProps *props)
{
- struct sync_reader *This = impl_from_IWMSyncReader2(iface);
- FIXME("(%p)->(%u %p): stub!\n", This, output_num, output);
- return E_NOTIMPL;
+ struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
+
+ TRACE("reader %p, output %u, props %p.\n", reader, output, props);
+
+ return wm_reader_set_output_props(&reader->reader, output, props);
}
static HRESULT WINAPI WMSyncReader_SetOutputSetting(IWMSyncReader2 *iface, DWORD output_num, const WCHAR *name,
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index ebfdfdf0107..e07e6241a4c 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -789,14 +789,7 @@ static void test_sync_reader_types(void)
check_video_type(mt);
hr = IWMSyncReader_SetOutputProps(reader, output_number, output_props);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (hr != S_OK)
- {
- ref = IWMOutputMediaProps_Release(output_props);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- winetest_pop_context();
- continue;
- }
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IWMSyncReader_SetOutputProps(reader, 1 - output_number, output_props);
if (!i)
todo_wine ok(hr == ASF_E_BADMEDIATYPE, "Got hr %#x.\n", hr);
--
2.33.0
Nov. 1, 2021