Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: give w10pro64 more time
dlls/quartz/tests/dsoundrender.c | 142 +++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+)
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c index 558e6989c98..c33c074d93d 100644 --- a/dlls/quartz/tests/dsoundrender.c +++ b/dlls/quartz/tests/dsoundrender.c @@ -877,6 +877,147 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control ok(hr == S_OK, "Got hr %#x.\n", hr); }
+static unsigned int check_ec_complete(IMediaEvent *eventsrc, DWORD timeout) +{ + 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 == EC_COMPLETE) + { + ok(param1 == S_OK, "Got param1 %#lx.\n", param1); + ok(!param2, "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 void test_eos(IPin *pin, IMemInputPin *input, IMediaControl *control) +{ + IMediaEvent *eventsrc; + OAFilterState state; + HRESULT hr; + BOOL ret; + + IMediaControl_QueryInterface(control, &IID_IMediaEvent, (void **)&eventsrc); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = send_frame(input); + todo_wine ok(hr == VFW_E_SAMPLE_REJECTED_EOS, "Got hr %#x.\n", hr); + + hr = IMediaControl_Run(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + /* We do not receive an EC_COMPLETE notification until the last sample is + * done rendering. */ + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = send_frame(input); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Run(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + ret = check_ec_complete(eventsrc, 2000); + todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + /* Test sending EOS while flushing. */ + + hr = IMediaControl_Run(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = send_frame(input); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_EndOfStream(pin); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + /* Test sending EOS and then flushing or stopping. */ + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = send_frame(input); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Run(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = send_frame(input); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + IMediaEvent_Release(eventsrc); +} + static void test_connect_pin(void) { ALLOCATOR_PROPERTIES req_props = {1, 4 * 44100, 1, 0}, ret_props; @@ -971,6 +1112,7 @@ static void test_connect_pin(void)
test_filter_state(input, control); test_flushing(pin, input, control); + test_eos(pin, input, control);
hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/avisplit.c | 207 ++++++++++++++++++++++++++++++++ dlls/quartz/tests/mpegsplit.c | 193 ++++++++++++++++++++++++++++++ dlls/quartz/tests/rsrc.rc | 2 +- dlls/quartz/tests/test.avi | Bin 6938 -> 11642 bytes dlls/quartz/tests/waveparser.c | 210 +++++++++++++++++++++++++++++++++ 5 files changed, 611 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/tests/avisplit.c b/dlls/quartz/tests/avisplit.c index c5af19b5aff..ec7345ad8a5 100644 --- a/dlls/quartz/tests/avisplit.c +++ b/dlls/quartz/tests/avisplit.c @@ -25,6 +25,8 @@ #include "wine/strmbase.h" #include "wine/test.h"
+static const GUID testguid = {0xfacade}; + static IBaseFilter *create_avi_splitter(void) { IBaseFilter *filter = NULL; @@ -1373,6 +1375,210 @@ static void test_unconnected_filter_state(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static void test_seeking(void) +{ + LONGLONG time, current, stop, prev_stop, earliest, latest, duration; + const WCHAR *filename = load_resource(L"test.avi"); + IBaseFilter *filter = create_avi_splitter(); + IFilterGraph2 *graph = connect_input(filter, filename); + IMediaSeeking *seeking; + unsigned int i; + double rate; + GUID format; + HRESULT hr; + DWORD caps; + ULONG ref; + IPin *pin; + BOOL ret; + + static const struct + { + const GUID *guid; + HRESULT hr; + } + format_tests[] = + { + {&TIME_FORMAT_MEDIA_TIME, S_OK}, + {&TIME_FORMAT_FRAME, S_OK}, + + {&TIME_FORMAT_BYTE, S_FALSE}, + {&TIME_FORMAT_NONE, S_FALSE}, + {&TIME_FORMAT_SAMPLE, S_FALSE}, + {&TIME_FORMAT_FIELD, S_FALSE}, + {&testguid, S_FALSE}, + }; + + IBaseFilter_FindPin(filter, L"Stream 00", &pin); + IPin_QueryInterface(pin, &IID_IMediaSeeking, (void **)&seeking); + + hr = IMediaSeeking_GetCapabilities(seeking, &caps); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(caps == (AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards + | AM_SEEKING_CanSeekBackwards | AM_SEEKING_CanGetStopPos + | AM_SEEKING_CanGetDuration), "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(caps == (AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards), "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanGetCurrentPos; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(caps == AM_SEEKING_CanSeekAbsolute, "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanGetCurrentPos; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + ok(!caps, "Got caps %#x.\n", caps); + + caps = 0; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + ok(!caps, "Got caps %#x.\n", caps); + + for (i = 0; i < ARRAY_SIZE(format_tests); ++i) + { + hr = IMediaSeeking_IsFormatSupported(seeking, format_tests[i].guid); + todo_wine_if(i == 1) ok(hr == format_tests[i].hr, "Got hr %#x for format %s.\n", + hr, wine_dbgstr_guid(format_tests[i].guid)); + } + + hr = IMediaSeeking_QueryPreferredFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_GetTimeFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_FRAME); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_SAMPLE); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_FRAME); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_GetTimeFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(IsEqualGUID(&format, &TIME_FORMAT_FRAME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_FRAME); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + duration = 0; + hr = IMediaSeeking_GetDuration(seeking, &duration); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(duration > 0, "Got duration %s.\n", wine_dbgstr_longlong(duration)); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetStopPosition(seeking, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stop == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(stop)); + hr = IMediaSeeking_GetCurrentPosition(seeking, ¤t); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(stop)); + + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, &TIME_FORMAT_MEDIA_TIME, 0x123456789a, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time)); + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, NULL, 0x123456789a, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time)); + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, NULL, 123, &TIME_FORMAT_FRAME); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(time == 123 * 10000000, "Got time %s.\n", wine_dbgstr_longlong(time)); + + earliest = latest = 0xdeadbeef; + hr = IMediaSeeking_GetAvailable(seeking, &earliest, &latest); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!earliest, "Got time %s.\n", wine_dbgstr_longlong(earliest)); + ok(latest == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(latest)); + + rate = 0; + hr = IMediaSeeking_GetRate(seeking, &rate); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(rate == 1.0, "Got rate %.16e.\n", rate); + + hr = IMediaSeeking_SetRate(seeking, 200.0); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + rate = 0; + hr = IMediaSeeking_GetRate(seeking, &rate); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(rate == 200.0, "Got rate %.16e.\n", rate); + + hr = IMediaSeeking_SetRate(seeking, -1.0); + todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_GetPreroll(seeking, &time); + todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + + current = 1500 * 10000; + stop = 3500 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + &stop, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 1500 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 3500 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + /* Native snaps to the nearest frame. */ + ok(current > 0 && current < duration, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop > 0 && stop < duration && stop > current, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 1500 * 10000; + stop = 3500 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime, + &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current > 0 && current < duration, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop > 0 && stop < duration && stop > current, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + hr = IMediaSeeking_GetStopPosition(seeking, &prev_stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + current = 0; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + NULL, AM_SEEKING_NoPositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == prev_stop, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(prev_stop), wine_dbgstr_longlong(stop)); + + IMediaSeeking_Release(seeking); + IPin_Release(pin); + IFilterGraph2_Release(graph); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); +} + START_TEST(avisplit) { IBaseFilter *filter; @@ -1396,6 +1602,7 @@ START_TEST(avisplit) test_enum_media_types(); test_unconnected_filter_state(); test_connect_pin(); + test_seeking();
CoUninitialize(); } diff --git a/dlls/quartz/tests/mpegsplit.c b/dlls/quartz/tests/mpegsplit.c index 26e2d06314c..d159fe49832 100644 --- a/dlls/quartz/tests/mpegsplit.c +++ b/dlls/quartz/tests/mpegsplit.c @@ -24,6 +24,7 @@ #include "wine/strmbase.h" #include "wine/test.h"
+static const GUID testguid = {0xfacade}; static const GUID MEDIASUBTYPE_mp3 = {0x00000055,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
static IBaseFilter *create_mpeg_splitter(void) @@ -1554,6 +1555,197 @@ static void test_connect_pin(void) ok(ret, "Failed to delete file, error %u.\n", GetLastError()); }
+static void test_seeking(void) +{ + LONGLONG time, current, stop, earliest, latest, duration; + const WCHAR *filename = load_resource(L"test.mp3"); + IBaseFilter *filter = create_mpeg_splitter(); + IFilterGraph2 *graph = connect_input(filter, filename); + IMediaSeeking *seeking; + unsigned int i; + double rate; + GUID format; + HRESULT hr; + DWORD caps; + ULONG ref; + IPin *pin; + BOOL ret; + + static const struct + { + const GUID *guid; + HRESULT hr; + } + format_tests[] = + { + {&TIME_FORMAT_MEDIA_TIME, S_OK}, + + {&TIME_FORMAT_SAMPLE, S_FALSE}, + {&TIME_FORMAT_BYTE, S_FALSE}, + {&TIME_FORMAT_NONE, S_FALSE}, + {&TIME_FORMAT_FRAME, S_FALSE}, + {&TIME_FORMAT_FIELD, S_FALSE}, + {&testguid, S_FALSE}, + }; + + IBaseFilter_FindPin(filter, L"Audio", &pin); + IPin_QueryInterface(pin, &IID_IMediaSeeking, (void **)&seeking); + + hr = IMediaSeeking_GetCapabilities(seeking, &caps); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(caps == (AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards + | AM_SEEKING_CanSeekBackwards | AM_SEEKING_CanGetStopPos + | AM_SEEKING_CanGetDuration), "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(caps == (AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards), "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanGetCurrentPos; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(caps == AM_SEEKING_CanSeekAbsolute, "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanGetCurrentPos; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + ok(!caps, "Got caps %#x.\n", caps); + + caps = 0; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + ok(!caps, "Got caps %#x.\n", caps); + + for (i = 0; i < ARRAY_SIZE(format_tests); ++i) + { + hr = IMediaSeeking_IsFormatSupported(seeking, format_tests[i].guid); + ok(hr == format_tests[i].hr, "Got hr %#x for format %s.\n", + hr, wine_dbgstr_guid(format_tests[i].guid)); + } + + hr = IMediaSeeking_QueryPreferredFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_GetTimeFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_SAMPLE); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_FRAME); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + duration = 0; + hr = IMediaSeeking_GetDuration(seeking, &duration); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(duration > 0, "Got duration %s.\n", wine_dbgstr_longlong(duration)); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetStopPosition(seeking, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stop == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(stop)); + hr = IMediaSeeking_GetCurrentPosition(seeking, ¤t); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(stop)); + + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, &TIME_FORMAT_MEDIA_TIME, 0x123456789a, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time)); + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, NULL, 0x123456789a, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time)); + + earliest = latest = 0xdeadbeef; + hr = IMediaSeeking_GetAvailable(seeking, &earliest, &latest); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!earliest, "Got time %s.\n", wine_dbgstr_longlong(earliest)); + ok(latest == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(latest)); + + rate = 0; + hr = IMediaSeeking_GetRate(seeking, &rate); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(rate == 1.0, "Got rate %.16e.\n", rate); + + hr = IMediaSeeking_SetRate(seeking, 200.0); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + rate = 0; + hr = IMediaSeeking_GetRate(seeking, &rate); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(rate == 200.0, "Got rate %.16e.\n", rate); + + hr = IMediaSeeking_SetRate(seeking, -1.0); + todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_GetPreroll(seeking, &time); + todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + + current = 200 * 10000; + stop = 400 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + &stop, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 400 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 400 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 200 * 10000; + stop = 400 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime, + &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 400 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 100 * 10000; + stop = 200 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime, + &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 100 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 50 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + NULL, AM_SEEKING_NoPositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 50 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + IMediaSeeking_Release(seeking); + IPin_Release(pin); + IFilterGraph2_Release(graph); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); +} + START_TEST(mpegsplit) { IBaseFilter *filter; @@ -1577,6 +1769,7 @@ START_TEST(mpegsplit) test_enum_media_types(); test_unconnected_filter_state(); test_connect_pin(); + test_seeking();
CoUninitialize(); } diff --git a/dlls/quartz/tests/rsrc.rc b/dlls/quartz/tests/rsrc.rc index d28c2bd6edc..2cc0d789ff0 100644 --- a/dlls/quartz/tests/rsrc.rc +++ b/dlls/quartz/tests/rsrc.rc @@ -20,7 +20,7 @@
#include "windef.h"
-/* ffmpeg -f lavfi -i smptebars -t 1 -r 1 -f avi -vcodec rawvideo -pix_fmt yuv420p -vf scale=32x24 test.avi */ +/* ffmpeg -f lavfi -i smptebars -t 5 -r 1 -f avi -vcodec rawvideo -pix_fmt yuv420p -vf scale=32x24 test.avi */ /* @makedep: test.avi */ test.avi RCDATA "test.avi"
diff --git a/dlls/quartz/tests/test.avi b/dlls/quartz/tests/test.avi index bec304de1d89a5353af4949270ca47a38d636290..3c927999fbf9f0b6625cb0ba9ac20c07aec19ea3 100644 GIT binary patch literal 11642 zcmWIYbaN}xWngd&^HlKh3=XjnVqnNfDauJK%gnG~U|?`?;%8`J0WyF<fRllN6~bg- zgorRG0BH%R7%~Mi>wy3RLvcw_4iJOQD$7hM_B1gvKvoAb2Vxe)Y>-|5fdHmP0cbi< zf0_nR0E88Q7-SzK0}lhpESTGXLU7;}>gO#1v>WPd1_OhXWVqxgV>ARtLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(M1(+DK~aGVl21Y74+=mG8dqQjjvBz&AaRfw zj1QvG0cfm&1*kATB{v6%GJc>d7(sl{n2!|Dzn*?>{+_{ZA$&l#Phwe`sfC`2sh**M z0Rt$selU-qAQ|=QXb6mk06YXhCBzyr28P`HvP{sZENJw0D-f(*w0QC2uI853hQh+a zqJ-ek&|qgLCucJy6%`e*{6e6DuBMij`htSOqWIttpuD4_lc|!jvho%nShH}^qQ#v} z%^>-L!uX(&&>$y}yyB=l&BJFq5UgLkWXV!+`~ah`I6g2qBnTWo@(KzHD}i9)v}x0) zx70N>RAppjX2petM}*ni+S-}x>Op|IjI^|rM|fDYm!zbmXhd6MbEUkf7=O^FHEY%= zDJdz-h$$&51|~%YItvR6^9D3j*Az<%2yy#wShZ@EIS?2|-MMw^-iw*)dYYQrQX)V@ zBsjPQM5Secz!C_I6F<Ix_x9TYC2buYJ!xJ(K0aPHE&(x7ULddl0^|6%uV26ZGGAFo zM@LthPe4F`pB*SK24n~jk_Vfg@b(Q*|2&9(eyDzNagcsO@{KL-Dp5-&db=+;*dJSa z?P^1_8<0Q2%Wc7dzSx?pAii?s;(jl;`TP4~YOY=(m0#cFq7<>X-_v#e0igct*V?;$ zwBnXc^7Wd(uP?s#{JE2-Cl^oHwx*$W>b%~XhW7S_i)J=9^{!bpr=h8_v9Z2>_M91w zb)Bo%&9AF(017nDnG5Exombxg291qfQ!+I4Ev;6ZI(Kt_QE@{<*OYX1Jxj|Kr_SEk zUs%-8&^Z~%x3E}#^6ZU$<nX(uq^anbo3A_rG{3N@zP@u(wuzOU-Ml@AFYPKSE-b9B zpSp8hZMBbOa(8QeeNs|-U31UO$-R|j)%Ep_jR^^<_4O^2r}hHf4)Q=Ekl)ZUc}g$T z{iEg3@F*uo%OPMnH(CyjmP4cMp#g0Vj+R5C<<Mw*XtZB8(EZZUa%i+18ZC!L%c0S7 zXmorC-}uq!_z?c_q0E#D!vNq2HfWp(xTqMssu(nG4deF!*~okm;3{ck{v2LZz6x-K HHAo%+W5c>j
literal 6938 zcmWIYbaNAuW?*m(^HlKh3=XjnVqnNfDauJK%gnG~U|?`?;%8Wq2xI_(04D<jBZLX1 z1sD{7d<m!+G6gd0fdB(TaY<1Q5QEJs%S<WuG%+$jRtGW<*~|tO28RDY08^s?G##iv zO#>(Z!U{kPvX7C0hXG_3NIg363ib1r0NM?cGB8L<MprY+9}R)g5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c-XTy{P*mW8<VDc<g8~qP#ub=>qXsZGNE{>v<AZ2) z02*sx0V>Q-$;|<xj34L<Mi3t~<|764ucx1zzh|&p2p^E`lUSB!YNlsmpl4`c$N&nh zAIu{tNJhOn8Umvs01p9B3DE-_md(vC%LI+ef<|w*0>Rpaixw^FYHn$5C@d^2P6!SO z33hgJayC;`R#pbfFIc#6VP{iIOMO8>VNrZga7d7oqocE_f|8Qb79dyyk#7dc7l7o0 zLGn(c@^lEF?Le?@(c;C6LGf2#SXfjX9~cxA2#OyQIeB^cl|Zm?>eOk|TI%W>sxmS% zv*N<S!b9zCZSBl;bRj@pMp{bBBP=w^OHxu&G@`AssZw54j6Z18>eZ_i6&00a#FP{j z0}~?xoP~vjc>@}%Yl<ZWgt+}TtXj3o90&{}@7%g|@5M}YJxxt*DG{I{5**wDqSCTJ zU<m}qi67s;d;4vHlD3YHo-{8XA0ICpmw=ckFA!J&fpPrX*RNlHnXjy)qoXU$Cm<le z&kmFq12O~%$%D;Lc>4yZe;!0XKUBZCI7mMs`NkG^m8c~Xz1<fa=!>bncD13|4alG1 z<u-qRZ%oZq5MMcRaX*OP6J2xl3aR}1CKsiM#r>YHVExyxwRibw#VwoU>otFGZ(Qy9 zb0<$vE}pP;O+)R}dA&6a?d=N}&1`J!U9)OVLsMg8V}1SXIWrpTI#;io4~#ybK;xXb zVE)>9^$lRq*w{5WT|>{(V#TR*H}@A6H#BrkO4HD@uvmWT?2Y|}MPR<VuDSX0lV@-2 zBafe|s%>Vr;tbII!lL^6jtSYOmbSL@_8h*ntEjlJu)2Qg&ULlb-j>PTt@ZUuN$GXX zJu@fwR+d%Q*EcpMB&62Yw@jYe3v@fk1BpO>L(AkTy-@dOrc@XLCyN+B<q?Pm%^HEq FB>*m=8Sel9
diff --git a/dlls/quartz/tests/waveparser.c b/dlls/quartz/tests/waveparser.c index 37f924b716f..18541012ccf 100644 --- a/dlls/quartz/tests/waveparser.c +++ b/dlls/quartz/tests/waveparser.c @@ -23,6 +23,8 @@ #include "mmreg.h" #include "wine/test.h"
+static const GUID testguid = {0xfacade}; + static IBaseFilter *create_wave_parser(void) { IBaseFilter *filter = NULL; @@ -825,6 +827,213 @@ static void test_unconnected_filter_state(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static void test_seeking(void) +{ + LONGLONG time, current, stop, earliest, latest, duration; + const WCHAR *filename = load_resource(L"test.wav"); + IBaseFilter *filter = create_wave_parser(); + IFilterGraph2 *graph = connect_input(filter, filename); + IMediaSeeking *seeking; + unsigned int i; + double rate; + GUID format; + HRESULT hr; + DWORD caps; + ULONG ref; + IPin *pin; + BOOL ret; + + static const struct + { + const GUID *guid; + HRESULT hr; + } + format_tests[] = + { + {&TIME_FORMAT_MEDIA_TIME, S_OK}, + {&TIME_FORMAT_SAMPLE, S_OK}, + + {&TIME_FORMAT_BYTE, S_FALSE}, + {&TIME_FORMAT_NONE, S_FALSE}, + {&TIME_FORMAT_FRAME, S_FALSE}, + {&TIME_FORMAT_FIELD, S_FALSE}, + {&testguid, S_FALSE}, + }; + + IBaseFilter_FindPin(filter, L"output", &pin); + IPin_QueryInterface(pin, &IID_IMediaSeeking, (void **)&seeking); + + hr = IMediaSeeking_GetCapabilities(seeking, &caps); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(caps == (AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards + | AM_SEEKING_CanSeekBackwards | AM_SEEKING_CanGetStopPos + | AM_SEEKING_CanGetDuration | AM_SEEKING_CanDoSegments), "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(caps == (AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards), "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanGetCurrentPos; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(caps == AM_SEEKING_CanSeekAbsolute, "Got caps %#x.\n", caps); + + caps = AM_SEEKING_CanGetCurrentPos; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + ok(!caps, "Got caps %#x.\n", caps); + + caps = 0; + hr = IMediaSeeking_CheckCapabilities(seeking, &caps); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + ok(!caps, "Got caps %#x.\n", caps); + + for (i = 0; i < ARRAY_SIZE(format_tests); ++i) + { + hr = IMediaSeeking_IsFormatSupported(seeking, format_tests[i].guid); + todo_wine_if(i == 1) ok(hr == format_tests[i].hr, "Got hr %#x for format %s.\n", + hr, wine_dbgstr_guid(format_tests[i].guid)); + } + + hr = IMediaSeeking_QueryPreferredFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_GetTimeFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_SAMPLE); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_FRAME); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_SAMPLE); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_GetTimeFormat(seeking, &format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(IsEqualGUID(&format, &TIME_FORMAT_SAMPLE), "Got format %s.\n", wine_dbgstr_guid(&format)); + + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = IMediaSeeking_IsUsingTimeFormat(seeking, &TIME_FORMAT_SAMPLE); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_SetTimeFormat(seeking, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + duration = 0xdeadbeef; + hr = IMediaSeeking_GetDuration(seeking, &duration); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(duration > 0, "Got duration %s.\n", wine_dbgstr_longlong(time)); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetStopPosition(seeking, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stop == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(stop)); + hr = IMediaSeeking_GetCurrentPosition(seeking, ¤t); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(stop)); + + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, &TIME_FORMAT_MEDIA_TIME, 0x123456789a, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time)); + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, NULL, 0x123456789a, &TIME_FORMAT_MEDIA_TIME); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time)); + time = 0xdeadbeef; + hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, NULL, 441, &TIME_FORMAT_SAMPLE); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(time == 100000, "Got time %s.\n", wine_dbgstr_longlong(time)); + + earliest = latest = 0xdeadbeef; + hr = IMediaSeeking_GetAvailable(seeking, &earliest, &latest); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!earliest, "Got time %s.\n", wine_dbgstr_longlong(earliest)); + ok(latest == duration, "Expected time %s, got %s.\n", + wine_dbgstr_longlong(duration), wine_dbgstr_longlong(latest)); + + rate = 0; + hr = IMediaSeeking_GetRate(seeking, &rate); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(rate == 1.0, "Got rate %.16e.\n", rate); + + hr = IMediaSeeking_SetRate(seeking, 200.0); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + rate = 0; + hr = IMediaSeeking_GetRate(seeking, &rate); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(rate == 200.0, "Got rate %.16e.\n", rate); + + hr = IMediaSeeking_SetRate(seeking, -1.0); + todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IMediaSeeking_GetPreroll(seeking, &time); + todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + + current = 200 * 10000; + stop = 400 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + &stop, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 400 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 400 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 200 * 10000; + stop = 400 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime, + &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 400 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 100 * 10000; + stop = 200 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime, + &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 100 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + current = 50 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + NULL, AM_SEEKING_NoPositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + stop = current = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(current == 50 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current)); + ok(stop == 200 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop)); + + IMediaSeeking_Release(seeking); + IPin_Release(pin); + IFilterGraph2_Release(graph); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); +} + START_TEST(waveparser) { IBaseFilter *filter; @@ -847,6 +1056,7 @@ START_TEST(waveparser) test_media_types(); test_enum_media_types(); test_unconnected_filter_state(); + test_seeking();
CoUninitialize(); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/avisplit.c | 150 ++++++++++++++++++++++++++++++++++ dlls/quartz/tests/mpegsplit.c | 150 ++++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+)
diff --git a/dlls/quartz/tests/avisplit.c b/dlls/quartz/tests/avisplit.c index ec7345ad8a5..4ebc3d5df9a 100644 --- a/dlls/quartz/tests/avisplit.c +++ b/dlls/quartz/tests/avisplit.c @@ -807,6 +807,9 @@ struct testfilter struct strmbase_sink sink; IAsyncReader IAsyncReader_iface, *reader; const AM_MEDIA_TYPE *mt; + HANDLE eos_event; + unsigned int sample_count, eos_count, new_segment_count; + REFERENCE_TIME seek_start, seek_end; };
static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface) @@ -827,6 +830,7 @@ static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, un static void testfilter_destroy(struct strmbase_filter *iface) { struct testfilter *filter = impl_from_strmbase_filter(iface); + CloseHandle(filter->eos_event); strmbase_source_cleanup(&filter->source); strmbase_sink_cleanup(&filter->sink); strmbase_filter_cleanup(&filter->filter); @@ -911,6 +915,60 @@ static HRESULT testsink_get_media_type(struct strmbase_pin *iface, unsigned int
static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample *sample) { + struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter); + REFERENCE_TIME start, end; + IMediaSeeking *seeking; + HRESULT hr; + + hr = IMediaSample_GetTime(sample, &start, &end); + todo_wine_if (hr == VFW_S_NO_STOP_TIME) ok(hr == S_OK, "Got hr %#x.\n", hr); + + if (winetest_debug > 1) + trace("%04x: Got sample with timestamps %I64d-%I64d.\n", GetCurrentThreadId(), start, end); + + ok(filter->new_segment_count, "Expected NewSegment() before Receive().\n"); + + IPin_QueryInterface(iface->pin.peer, &IID_IMediaSeeking, (void **)&seeking); + hr = IMediaSeeking_GetPositions(seeking, &start, &end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine_if (start != filter->seek_start) + ok(start == filter->seek_start, "Expected start position %I64u, got %I64u.\n", filter->seek_start, start); + ok(end == filter->seek_end, "Expected end position %I64u, got %I64u.\n", filter->seek_end, end); + IMediaSeeking_Release(seeking); + + ok(!filter->eos_count, "Got a sample after EOS.\n"); + ++filter->sample_count; + return S_OK; +} + +static HRESULT testsink_eos(struct strmbase_sink *iface) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter); + + if (winetest_debug > 1) + trace("%04x: Got EOS.\n", GetCurrentThreadId()); + + ok(!filter->eos_count, "Got %u EOS events.\n", filter->eos_count + 1); + ++filter->eos_count; + SetEvent(filter->eos_event); + return S_OK; +} + +static HRESULT testsink_new_segment(struct strmbase_sink *iface, + REFERENCE_TIME start, REFERENCE_TIME end, double rate) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter); + IMediaSeeking *seeking; + HRESULT hr; + + ++filter->new_segment_count; + + IPin_QueryInterface(iface->pin.peer, &IID_IMediaSeeking, (void **)&seeking); + hr = IMediaSeeking_GetPositions(seeking, &filter->seek_start, &filter->seek_end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(rate == 1.0, "Got rate %.16e.\n", rate); + IMediaSeeking_Release(seeking); + return S_OK; }
@@ -920,6 +978,8 @@ static const struct strmbase_sink_ops testsink_ops = .base.pin_query_accept = testsink_query_accept, .base.pin_get_media_type = testsink_get_media_type, .pfnReceive = testsink_Receive, + .sink_eos = testsink_eos, + .sink_new_segment = testsink_new_segment, };
static struct testfilter *impl_from_IAsyncReader(IAsyncReader *iface) @@ -1007,6 +1067,7 @@ static void testfilter_init(struct testfilter *filter) strmbase_source_init(&filter->source, &filter->filter, L"source", &testsource_ops); strmbase_sink_init(&filter->sink, &filter->filter, L"sink", &testsink_ops, NULL); filter->IAsyncReader_iface.lpVtbl = &async_reader_vtbl; + filter->eos_event = CreateEventW(NULL, FALSE, FALSE, NULL); }
static void test_filter_state(IMediaControl *control) @@ -1579,6 +1640,94 @@ static void test_seeking(void) ok(ret, "Failed to delete file, error %u.\n", GetLastError()); }
+static void test_streaming(void) +{ + const WCHAR *filename = load_resource(L"test.avi"); + IBaseFilter *filter = create_avi_splitter(); + IFilterGraph2 *graph = connect_input(filter, filename); + struct testfilter testsink; + REFERENCE_TIME start, end; + IMediaSeeking *seeking; + IMediaControl *control; + IPin *source; + HRESULT hr; + ULONG ref; + DWORD ret; + + testfilter_init(&testsink); + IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink"); + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + IBaseFilter_FindPin(filter, L"Stream 00", &source); + IPin_QueryInterface(source, &IID_IMediaSeeking, (void **)&seeking); + + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Expected timeout.\n"); + + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + testsink.sample_count = testsink.eos_count = 0; + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + testsink.sample_count = testsink.eos_count = 0; + start = 1500 * 10000; + end = 3500 * 10000; + hr = IMediaSeeking_SetPositions(seeking, &start, AM_SEEKING_AbsolutePositioning, + &end, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + start = end = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, &start, &end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end); + + testsink.sample_count = testsink.eos_count = 0; + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + start = end = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, &start, &end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end); + + IMediaSeeking_Release(seeking); + IPin_Release(source); + IMediaControl_Release(control); + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&testsink.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); +} + START_TEST(avisplit) { IBaseFilter *filter; @@ -1603,6 +1752,7 @@ START_TEST(avisplit) test_unconnected_filter_state(); test_connect_pin(); test_seeking(); + test_streaming();
CoUninitialize(); } diff --git a/dlls/quartz/tests/mpegsplit.c b/dlls/quartz/tests/mpegsplit.c index d159fe49832..a334467ad70 100644 --- a/dlls/quartz/tests/mpegsplit.c +++ b/dlls/quartz/tests/mpegsplit.c @@ -1096,6 +1096,9 @@ struct testfilter struct strmbase_sink sink; IAsyncReader IAsyncReader_iface, *reader; const AM_MEDIA_TYPE *mt; + HANDLE eos_event; + unsigned int sample_count, eos_count, new_segment_count; + REFERENCE_TIME seek_start, seek_end; };
static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface) @@ -1119,6 +1122,7 @@ static void testfilter_destroy(struct strmbase_filter *iface) strmbase_source_cleanup(&filter->source); strmbase_sink_cleanup(&filter->sink); strmbase_filter_cleanup(&filter->filter); + CloseHandle(filter->eos_event); }
static const struct strmbase_filter_ops testfilter_ops = @@ -1200,6 +1204,60 @@ static HRESULT testsink_get_media_type(struct strmbase_pin *iface, unsigned int
static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample *sample) { + struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter); + REFERENCE_TIME start, end; + IMediaSeeking *seeking; + HRESULT hr; + + hr = IMediaSample_GetTime(sample, &start, &end); + todo_wine_if (hr == VFW_S_NO_STOP_TIME) ok(hr == S_OK, "Got hr %#x.\n", hr); + + if (winetest_debug > 1) + trace("%04x: Got sample with timestamps %I64d-%I64d.\n", GetCurrentThreadId(), start, end); + + ok(filter->new_segment_count, "Expected NewSegment() before Receive().\n"); + + IPin_QueryInterface(iface->pin.peer, &IID_IMediaSeeking, (void **)&seeking); + hr = IMediaSeeking_GetPositions(seeking, &start, &end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine_if (start != filter->seek_start) + ok(start == filter->seek_start, "Expected start position %I64u, got %I64u.\n", filter->seek_start, start); + ok(end == filter->seek_end, "Expected end position %I64u, got %I64u.\n", filter->seek_end, end); + IMediaSeeking_Release(seeking); + + ok(!filter->eos_count, "Got a sample after EOS.\n"); + ++filter->sample_count; + return S_OK; +} + +static HRESULT testsink_eos(struct strmbase_sink *iface) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter); + + if (winetest_debug > 1) + trace("%04x: Got EOS.\n", GetCurrentThreadId()); + + ok(!filter->eos_count, "Got %u EOS events.\n", filter->eos_count + 1); + ++filter->eos_count; + SetEvent(filter->eos_event); + return S_OK; +} + +static HRESULT testsink_new_segment(struct strmbase_sink *iface, + REFERENCE_TIME start, REFERENCE_TIME end, double rate) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter); + IMediaSeeking *seeking; + HRESULT hr; + + ++filter->new_segment_count; + + IPin_QueryInterface(iface->pin.peer, &IID_IMediaSeeking, (void **)&seeking); + hr = IMediaSeeking_GetPositions(seeking, &filter->seek_start, &filter->seek_end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(rate == 1.0, "Got rate %.16e.\n", rate); + IMediaSeeking_Release(seeking); + return S_OK; }
@@ -1209,6 +1267,8 @@ static const struct strmbase_sink_ops testsink_ops = .base.pin_query_accept = testsink_query_accept, .base.pin_get_media_type = testsink_get_media_type, .pfnReceive = testsink_Receive, + .sink_eos = testsink_eos, + .sink_new_segment = testsink_new_segment, };
static struct testfilter *impl_from_IAsyncReader(IAsyncReader *iface) @@ -1296,6 +1356,7 @@ static void testfilter_init(struct testfilter *filter) strmbase_source_init(&filter->source, &filter->filter, L"source", &testsource_ops); strmbase_sink_init(&filter->sink, &filter->filter, L"sink", &testsink_ops, NULL); filter->IAsyncReader_iface.lpVtbl = &async_reader_vtbl; + filter->eos_event = CreateEventW(NULL, FALSE, FALSE, NULL); }
static void test_connect_pin(void) @@ -1746,6 +1807,94 @@ static void test_seeking(void) ok(ret, "Failed to delete file, error %u.\n", GetLastError()); }
+static void test_streaming(void) +{ + const WCHAR *filename = load_resource(L"test.mp3"); + IBaseFilter *filter = create_mpeg_splitter(); + IFilterGraph2 *graph = connect_input(filter, filename); + struct testfilter testsink; + REFERENCE_TIME start, end; + IMediaSeeking *seeking; + IMediaControl *control; + IPin *source; + HRESULT hr; + ULONG ref; + DWORD ret; + + testfilter_init(&testsink); + IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink"); + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + IBaseFilter_FindPin(filter, L"Audio", &source); + IPin_QueryInterface(source, &IID_IMediaSeeking, (void **)&seeking); + + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Expected timeout.\n"); + + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + testsink.sample_count = testsink.eos_count = 0; + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + testsink.sample_count = testsink.eos_count = 0; + start = 100 * 10000; + end = 300 * 10000; + hr = IMediaSeeking_SetPositions(seeking, &start, AM_SEEKING_AbsolutePositioning, + &end, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + start = end = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, &start, &end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end); + + testsink.sample_count = testsink.eos_count = 0; + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(testsink.eos_event, 1000), "Did not receive EOS.\n"); + ok(WaitForSingleObject(testsink.eos_event, 100) == WAIT_TIMEOUT, "Got more than one EOS.\n"); + ok(testsink.sample_count, "Expected at least one sample.\n"); + + start = end = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, &start, &end); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end); + + IMediaSeeking_Release(seeking); + IPin_Release(source); + IMediaControl_Release(control); + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&testsink.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); +} + START_TEST(mpegsplit) { IBaseFilter *filter; @@ -1770,6 +1919,7 @@ START_TEST(mpegsplit) test_unconnected_filter_state(); test_connect_pin(); test_seeking(); + test_streaming();
CoUninitialize(); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/avisplit.c | 7 +++---- dlls/quartz/tests/mpegsplit.c | 7 +++---- dlls/winegstreamer/gstdemux.c | 29 +---------------------------- 3 files changed, 7 insertions(+), 36 deletions(-)
diff --git a/dlls/quartz/tests/avisplit.c b/dlls/quartz/tests/avisplit.c index 4ebc3d5df9a..7ded1773637 100644 --- a/dlls/quartz/tests/avisplit.c +++ b/dlls/quartz/tests/avisplit.c @@ -931,8 +931,7 @@ static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample IPin_QueryInterface(iface->pin.peer, &IID_IMediaSeeking, (void **)&seeking); hr = IMediaSeeking_GetPositions(seeking, &start, &end); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine_if (start != filter->seek_start) - ok(start == filter->seek_start, "Expected start position %I64u, got %I64u.\n", filter->seek_start, start); + ok(start == filter->seek_start, "Expected start position %I64u, got %I64u.\n", filter->seek_start, start); ok(end == filter->seek_end, "Expected end position %I64u, got %I64u.\n", filter->seek_end, end); IMediaSeeking_Release(seeking);
@@ -1696,7 +1695,7 @@ static void test_streaming(void) start = end = 0xdeadbeef; hr = IMediaSeeking_GetPositions(seeking, &start, &end); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end);
testsink.sample_count = testsink.eos_count = 0; @@ -1712,7 +1711,7 @@ static void test_streaming(void) start = end = 0xdeadbeef; hr = IMediaSeeking_GetPositions(seeking, &start, &end); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end);
IMediaSeeking_Release(seeking); diff --git a/dlls/quartz/tests/mpegsplit.c b/dlls/quartz/tests/mpegsplit.c index a334467ad70..be971897f99 100644 --- a/dlls/quartz/tests/mpegsplit.c +++ b/dlls/quartz/tests/mpegsplit.c @@ -1220,8 +1220,7 @@ static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample IPin_QueryInterface(iface->pin.peer, &IID_IMediaSeeking, (void **)&seeking); hr = IMediaSeeking_GetPositions(seeking, &start, &end); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine_if (start != filter->seek_start) - ok(start == filter->seek_start, "Expected start position %I64u, got %I64u.\n", filter->seek_start, start); + ok(start == filter->seek_start, "Expected start position %I64u, got %I64u.\n", filter->seek_start, start); ok(end == filter->seek_end, "Expected end position %I64u, got %I64u.\n", filter->seek_end, end); IMediaSeeking_Release(seeking);
@@ -1863,7 +1862,7 @@ static void test_streaming(void) start = end = 0xdeadbeef; hr = IMediaSeeking_GetPositions(seeking, &start, &end); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end);
testsink.sample_count = testsink.eos_count = 0; @@ -1879,7 +1878,7 @@ static void test_streaming(void) start = end = 0xdeadbeef; hr = IMediaSeeking_GetPositions(seeking, &start, &end); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); + ok(start == testsink.seek_start, "Expected start position %I64u, got %I64u.\n", testsink.seek_start, start); ok(end == testsink.seek_end, "Expected end position %I64u, got %I64u.\n", testsink.seek_end, end);
IMediaSeeking_Release(seeking); diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 215e2704a27..6d66ddcb167 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1897,33 +1897,6 @@ static ULONG WINAPI GST_Seeking_Release(IMediaSeeking *iface) return IPin_Release(&This->pin.pin.IPin_iface); }
-static HRESULT WINAPI GST_Seeking_GetCurrentPosition(IMediaSeeking *iface, REFERENCE_TIME *pos) -{ - struct gstdemux_source *This = impl_from_IMediaSeeking(iface); - - TRACE("(%p)->(%p)\n", This, pos); - - if (!pos) - return E_POINTER; - - mark_wine_thread(); - - if (This->pin.pin.filter->state == State_Stopped) - { - *pos = This->seek.llCurrent; - TRACE("Cached value\n"); - return S_OK; - } - - if (!gst_pad_query_position(This->their_src, GST_FORMAT_TIME, pos)) { - WARN("Could not query position\n"); - return E_NOTIMPL; - } - *pos /= 100; - This->seek.llCurrent = *pos; - return S_OK; -} - static GstSeekType type_from_flags(DWORD flags) { switch (flags & AM_SEEKING_PositioningBitsMask) { @@ -1997,7 +1970,7 @@ static const IMediaSeekingVtbl GST_Seeking_Vtbl = SourceSeekingImpl_SetTimeFormat, SourceSeekingImpl_GetDuration, SourceSeekingImpl_GetStopPosition, - GST_Seeking_GetCurrentPosition, + SourceSeekingImpl_GetCurrentPosition, SourceSeekingImpl_ConvertTimeFormat, GST_Seeking_SetPositions, SourceSeekingImpl_GetPositions,
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 80 +++++++++++++---------------------- 1 file changed, 30 insertions(+), 50 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 6d66ddcb167..e227ed9331d 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1897,63 +1897,43 @@ static ULONG WINAPI GST_Seeking_Release(IMediaSeeking *iface) return IPin_Release(&This->pin.pin.IPin_iface); }
-static GstSeekType type_from_flags(DWORD flags) -{ - switch (flags & AM_SEEKING_PositioningBitsMask) { - case AM_SEEKING_NoPositioning: - return GST_SEEK_TYPE_NONE; - case AM_SEEKING_AbsolutePositioning: - case AM_SEEKING_RelativePositioning: - return GST_SEEK_TYPE_SET; - case AM_SEEKING_IncrementalPositioning: - return GST_SEEK_TYPE_END; - } - return GST_SEEK_TYPE_NONE; -} - static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface, - REFERENCE_TIME *pCur, DWORD curflags, REFERENCE_TIME *pStop, - DWORD stopflags) + LONGLONG *current, DWORD current_flags, LONGLONG *stop, DWORD stop_flags) { - HRESULT hr; - struct gstdemux_source *This = impl_from_IMediaSeeking(iface); - GstSeekFlags f = 0; - GstSeekType curtype, stoptype; - GstEvent *e; - gint64 stop_pos = 0, curr_pos = 0; + GstSeekType current_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET; + struct gstdemux_source *pin = impl_from_IMediaSeeking(iface); + GstSeekFlags flags = 0;
- TRACE("(%p)->(%p, 0x%x, %p, 0x%x)\n", This, pCur, curflags, pStop, stopflags); + TRACE("pin %p, current %s, current_flags %#x, stop %s, stop_flags %#x.\n", + pin, current ? debugstr_time(*current) : "<null>", current_flags, + stop ? debugstr_time(*stop) : "<null>", stop_flags);
mark_wine_thread();
- hr = SourceSeekingImpl_SetPositions(iface, pCur, curflags, pStop, stopflags); - if (This->pin.pin.filter->state == State_Stopped) - return hr; - - curtype = type_from_flags(curflags); - stoptype = type_from_flags(stopflags); - if (curflags & AM_SEEKING_SeekToKeyFrame) - f |= GST_SEEK_FLAG_KEY_UNIT; - if (curflags & AM_SEEKING_Segment) - f |= GST_SEEK_FLAG_SEGMENT; - if (!(curflags & AM_SEEKING_NoFlush)) - f |= GST_SEEK_FLAG_FLUSH; - - if (((curflags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_RelativePositioning) || - ((stopflags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_RelativePositioning)) { - gint64 tmp_pos; - gst_pad_query_position (This->my_sink, GST_FORMAT_TIME, &tmp_pos); - if ((curflags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_RelativePositioning) - curr_pos = tmp_pos; - if ((stopflags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_RelativePositioning) - stop_pos = tmp_pos; - } - - e = gst_event_new_seek(This->seek.dRate, GST_FORMAT_TIME, f, curtype, pCur ? curr_pos + *pCur * 100 : -1, stoptype, pStop ? stop_pos + *pStop * 100 : -1); - if (gst_pad_push_event(This->my_sink, e)) + SourceSeekingImpl_SetPositions(iface, current, current_flags, stop, stop_flags); + if (pin->pin.pin.filter->state == State_Stopped) return S_OK; - else - return E_NOTIMPL; + + if (current_flags & AM_SEEKING_SeekToKeyFrame) + flags |= GST_SEEK_FLAG_KEY_UNIT; + if (current_flags & AM_SEEKING_Segment) + flags |= GST_SEEK_FLAG_SEGMENT; + if (!(current_flags & AM_SEEKING_NoFlush)) + flags |= GST_SEEK_FLAG_FLUSH; + + if ((current_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) + current_type = GST_SEEK_TYPE_NONE; + if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) + stop_type = GST_SEEK_TYPE_NONE; + + if (!gst_pad_push_event(pin->my_sink, gst_event_new_seek(pin->seek.dRate, GST_FORMAT_TIME, flags, + current_type, pin->seek.llCurrent * 100, stop_type, pin->seek.llStop * 100))) + { + ERR("Failed to seek (current %s, stop %s).\n", + debugstr_time(pin->seek.llCurrent), debugstr_time(pin->seek.llStop)); + return E_FAIL; + } + return S_OK; }
static const IMediaSeekingVtbl GST_Seeking_Vtbl =
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtergraph.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index e7ee4e5c446..853155ab100 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -1623,7 +1623,7 @@ static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *durat struct testfilter *filter = impl_from_IMediaSeeking(iface); if (winetest_debug > 1) trace("%p->GetDuration()\n", iface); *duration = filter->seek_duration; - return S_OK; + return filter->seek_hr; }
static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop) @@ -4399,6 +4399,26 @@ static void test_graph_seeking(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(time == 0x23456, "Got time %s.\n", wine_dbgstr_longlong(time));
+ filter1.seek_hr = filter2.seek_hr = 0xbeef; + hr = IMediaSeeking_GetDuration(seeking, &time); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x23456, "Got time %s.\n", wine_dbgstr_longlong(time)); + + filter1.seek_hr = E_NOTIMPL; + filter2.seek_hr = S_OK; + hr = IMediaSeeking_GetDuration(seeking, &time); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 0x12345, "Got time %s.\n", wine_dbgstr_longlong(time)); + + filter1.seek_hr = 0xdeadbeef; + hr = IMediaSeeking_GetDuration(seeking, &time); + ok(hr == 0xdeadbeef, "Got hr %#x.\n", hr); + + filter1.seek_hr = filter2.seek_hr = E_NOTIMPL; + hr = IMediaSeeking_GetDuration(seeking, &time); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + filter1.seek_hr = filter2.seek_hr = S_OK; + flush_cached_seeking(graph, &filter1); flush_cached_seeking(graph, &filter2);
@@ -4420,6 +4440,7 @@ static void test_graph_seeking(void) ok(time == 0x65432, "Got time %s.\n", wine_dbgstr_longlong(time));
filter1.seek_hr = E_NOTIMPL; + filter2.seek_hr = S_OK; hr = IMediaSeeking_GetStopPosition(seeking, &time); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(time == 0x54321, "Got time %s.\n", wine_dbgstr_longlong(time)); @@ -4470,6 +4491,7 @@ static void test_graph_seeking(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
filter1.seek_hr = E_NOTIMPL; + filter2.seek_hr = S_OK; hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, &stop, AM_SEEKING_AbsolutePositioning); ok(hr == S_OK, "Got hr %#x.\n", hr);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 53 +++++++++++++++++++-------------- dlls/quartz/tests/filtergraph.c | 4 +-- 2 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index b3aebabbdad..fb0890fda1f 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -2237,36 +2237,45 @@ static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUI return S_OK; }
-static HRESULT WINAPI FoundDuration(struct filter_graph *This, IMediaSeeking *seek, DWORD_PTR pduration) +static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *duration) { - HRESULT hr; - LONGLONG duration = 0, *pdur = (LONGLONG*)pduration; + struct filter_graph *graph = impl_from_IMediaSeeking(iface); + HRESULT hr = E_NOTIMPL, filter_hr; + LONGLONG filter_duration; + struct filter *filter;
- hr = IMediaSeeking_GetDuration(seek, &duration); - if (FAILED(hr)) - return hr; + TRACE("graph %p, duration %p.\n", graph, duration);
- if (*pdur < duration) - *pdur = duration; - return hr; -} + if (!duration) + return E_POINTER;
-static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration) -{ - struct filter_graph *This = impl_from_IMediaSeeking(iface); - HRESULT hr; + *duration = 0;
- TRACE("(%p/%p)->(%p)\n", This, iface, pDuration); + EnterCriticalSection(&graph->cs);
- if (!pDuration) - return E_POINTER; + LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry) + { + update_seeking(filter); + if (!filter->seeking) + continue;
- EnterCriticalSection(&This->cs); - *pDuration = 0; - hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration); - LeaveCriticalSection(&This->cs); + filter_hr = IMediaSeeking_GetDuration(filter->seeking, &filter_duration); + if (SUCCEEDED(filter_hr)) + { + hr = S_OK; + *duration = max(*duration, filter_duration); + } + else if (filter_hr != E_NOTIMPL) + { + LeaveCriticalSection(&graph->cs); + return filter_hr; + } + } + + LeaveCriticalSection(&graph->cs);
- TRACE("--->%08x\n", hr); + TRACE("Returning hr %#x, duration %s (%s seconds).\n", hr, + wine_dbgstr_longlong(*duration), debugstr_time(*duration)); return hr; }
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 853155ab100..b6e68f3f6b9 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -4401,13 +4401,13 @@ static void test_graph_seeking(void)
filter1.seek_hr = filter2.seek_hr = 0xbeef; hr = IMediaSeeking_GetDuration(seeking, &time); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(time == 0x23456, "Got time %s.\n", wine_dbgstr_longlong(time));
filter1.seek_hr = E_NOTIMPL; filter2.seek_hr = S_OK; hr = IMediaSeeking_GetDuration(seeking, &time); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(time == 0x12345, "Got time %s.\n", wine_dbgstr_longlong(time));
filter1.seek_hr = 0xdeadbeef;