[PATCH 2/7] quartz/tests: Add some tests for IMediaSeeking on parser filters.

Zebediah Figura z.figura12 at gmail.com
Sat Nov 21 15:24:57 CST 2020


Signed-off-by: Zebediah Figura <z.figura12 at 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, &current);
+    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, &current, &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, &current, 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, &current, &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, &current, 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, &current, AM_SEEKING_AbsolutePositioning,
+            NULL, AM_SEEKING_NoPositioning);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    stop = current = 0xdeadbeef;
+    hr = IMediaSeeking_GetPositions(seeking, &current, &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, &current);
+    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, &current, &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, &current, 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, &current, &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, &current, 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, &current, 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, &current, AM_SEEKING_AbsolutePositioning,
+            NULL, AM_SEEKING_NoPositioning);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    stop = current = 0xdeadbeef;
+    hr = IMediaSeeking_GetPositions(seeking, &current, &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 at EIS?2|-MMw^-iw*)dYYQrQX)V@
zBsjPQM5Secz!C_I6F<Ix_x9TYC2buYJ!xJ(K0aPHE&(x7ULddl0^|6%uV26ZGGAFo
zM at LthPe4F`pB*SK24n~jk_Vfg at 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 at zP@u(wuzOU-Ml at AFYPKSE-b9B
zpSp8hZMBbOa(8QeeNs|-U31UO$-R|j)%Ep_jR^^<_4O^2r}hHf4)Q=Ekl)ZUc}g$T
z{iEg3 at 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 at 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 at 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 at uvmWT?2Y|}MPR<VuDSX0lV at -2
zBafe|s%>Vr;tbII!lL^6jtSYOmbSL at _8h*ntEjlJu)2Qg&ULlb-j>PTt at ZUuN$GXX
zJu at fwR+d%Q*EcpMB&62Yw at jYe3v@fk1BpO>L(AkTy- at 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, &current);
+    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, &current, &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, &current, 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, &current, &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, &current, 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, &current, 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, &current, AM_SEEKING_AbsolutePositioning,
+            NULL, AM_SEEKING_NoPositioning);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    stop = current = 0xdeadbeef;
+    hr = IMediaSeeking_GetPositions(seeking, &current, &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();
 }
-- 
2.29.2




More information about the wine-devel mailing list