[PATCH 1/5] amstream: Implement MediaStreamFilter::IsFormatSupported.

Zebediah Figura (she/her) zfigura at codeweavers.com
Mon Nov 16 10:49:43 CST 2020


On 11/16/20 9:31 AM, Anton Baskanov wrote:
> Signed-off-by: Anton Baskanov <baskanov at gmail.com>
> ---
>  dlls/amstream/filter.c         |  20 ++++-
>  dlls/amstream/tests/amstream.c | 136 ++++++++++++++++++++++++++++++++-
>  2 files changed, 152 insertions(+), 4 deletions(-)
> 
> diff --git a/dlls/amstream/filter.c b/dlls/amstream/filter.c
> index 5fd5b2afdbc..3c0436a294f 100644
> --- a/dlls/amstream/filter.c
> +++ b/dlls/amstream/filter.c
> @@ -848,9 +848,25 @@ static HRESULT WINAPI filter_seeking_CheckCapabilities(IMediaSeeking *iface, DWO
>  
>  static HRESULT WINAPI filter_seeking_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
>  {
> -    FIXME("iface %p, format %s, stub!\n", iface, debugstr_guid(format));
> +    struct filter *filter = impl_from_IMediaSeeking(iface);
> +    IMediaSeeking *seeking;
> +    HRESULT hr;
>  
> -    return E_NOTIMPL;
> +    TRACE("filter %p, format %s.\n", filter, debugstr_guid(format));
> +
> +    EnterCriticalSection(&filter->cs);
> +
> +    seeking = get_seeking(filter->seekable_stream);
> +
> +    LeaveCriticalSection(&filter->cs);
> +
> +    if (!seeking)
> +        return E_NOTIMPL;
> +
> +    hr = IMediaSeeking_IsFormatSupported(seeking, format);
> +    IMediaSeeking_Release(seeking);
> +
> +    return hr;
>  }
>  
>  static HRESULT WINAPI filter_seeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
> diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
> index f5014395832..2e5d6bc92be 100644
> --- a/dlls/amstream/tests/amstream.c
> +++ b/dlls/amstream/tests/amstream.c
> @@ -975,12 +975,14 @@ struct testfilter
>      LONGLONG stop_position;
>      const AM_MEDIA_TYPE *preferred_mt;
>      HANDLE wait_state_event;
> +    GUID is_format_supported_format;
>      HRESULT get_duration_hr;
>      HRESULT get_stop_position_hr;
>      HRESULT set_positions_hr;
>      HRESULT init_stream_hr;
>      HRESULT cleanup_stream_hr;
>      HRESULT wait_state_hr;
> +    HRESULT is_format_supported_hr;
>  };
>  
>  static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface)
> @@ -1168,8 +1170,11 @@ static HRESULT WINAPI testsource_seeking_CheckCapabilities(IMediaSeeking *iface,
>  
>  static HRESULT WINAPI testsource_seeking_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
>  {
> -    ok(0, "Unexpected call.\n");
> -    return E_NOTIMPL;
> +    struct testfilter *filter = impl_from_IMediaSeeking(iface);
> +
> +    filter->is_format_supported_format = *format;

I do appreciate the attention to detail, but maybe this is a little
redundant. The difference in HRESULT already proves that this function
is being called. [Plus, you only call this with TIME_FORMAT_MEDIA_TIME
anyway, so you could just hard-code it here with an ok() message instead.]

> +
> +    return filter->is_format_supported_hr;
>  }
>  
>  static HRESULT WINAPI testsource_seeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
> @@ -6926,6 +6931,132 @@ static void test_mediastreamfilter_wait_until(void)
>      ok(!ref, "Got outstanding refcount %d.\n", ref);
>  }
>  
> +static void test_mediastreamfilter_is_format_supported(void)
> +{
> +    IAMMultiMediaStream *mmstream = create_ammultimediastream();
> +    static const MSPID mspid1 = {0x88888888, 1};
> +    static const MSPID mspid2 = {0x88888888, 2};
> +    static const MSPID mspid3 = {0x88888888, 3};
> +    struct testfilter source1, source2, source3;
> +    IAMMediaStream *stream1, *stream2, *stream3;
> +    IMediaStreamFilter *filter;
> +    IPin *pin1, *pin2, *pin3;
> +    IMediaSeeking *seeking;
> +    IGraphBuilder *graph;
> +    HRESULT hr;
> +    ULONG ref;
> +
> +    hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream1);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream3);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMediaStream_Initialize(stream1, NULL, 0, &mspid1, STREAMTYPE_READ);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid2, STREAMTYPE_READ);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMediaStream_Initialize(stream3, NULL, 0, &mspid3, STREAMTYPE_READ);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream1, &mspid1, 0, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid2, 0, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream3, &mspid3, 0, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMediaStream_QueryInterface(stream3, &IID_IPin, (void **)&pin3);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    ok(graph != NULL, "Expected non-NULL graph.\n");
> +    testfilter_init(&source1);
> +    testfilter_init(&source2);
> +    testfilter_init(&source3);
> +    source1.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
> +    source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
> +    source3.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
> +    hr = IGraphBuilder_AddFilter(graph, &source1.filter.IBaseFilter_iface, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IGraphBuilder_AddFilter(graph, &source2.filter.IBaseFilter_iface, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IGraphBuilder_AddFilter(graph, &source3.filter.IBaseFilter_iface, NULL);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +
> +    hr = IGraphBuilder_ConnectDirect(graph, &source2.source.pin.IPin_iface, pin2, &audio_mt);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    hr = IGraphBuilder_ConnectDirect(graph, &source3.source.pin.IPin_iface, pin3, &audio_mt);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +
> +    hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +
> +    hr = IGraphBuilder_ConnectDirect(graph, &source1.source.pin.IPin_iface, pin1, &audio_mt);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +
> +    hr = IMediaStreamFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +
> +    source2.is_format_supported_format = GUID_NULL;
> +    hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
> +    ok(hr == S_OK, "Got hr %#x.\n", hr);
> +    ok(IsEqualGUID(&source2.is_format_supported_format, &TIME_FORMAT_MEDIA_TIME),
> +            "Got format %s.\n", wine_dbgstr_guid(&source2.is_format_supported_format));
> +
> +    source2.is_format_supported_hr = E_FAIL;
> +    source2.is_format_supported_format = GUID_NULL;
> +    hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
> +    ok(hr == E_FAIL, "Got hr %#x.\n", hr);
> +    ok(IsEqualGUID(&source2.is_format_supported_format, &TIME_FORMAT_MEDIA_TIME),
> +            "Got format %s.\n", wine_dbgstr_guid(&source2.is_format_supported_format));
> +
> +    source2.is_format_supported_hr = E_NOTIMPL;
> +    source2.is_format_supported_format = GUID_NULL;
> +    hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
> +    ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
> +    ok(IsEqualGUID(&source2.is_format_supported_format, &TIME_FORMAT_MEDIA_TIME),
> +            "Got format %s.\n", wine_dbgstr_guid(&source2.is_format_supported_format));
> +
> +    source2.IMediaSeeking_iface.lpVtbl = NULL;
> +    hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
> +    ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
> +
> +    IGraphBuilder_Disconnect(graph, pin2);
> +    IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
> +
> +    hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
> +    ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
> +
> +    IGraphBuilder_Disconnect(graph, pin1);
> +    IGraphBuilder_Disconnect(graph, &source1.source.pin.IPin_iface);
> +    IGraphBuilder_Disconnect(graph, pin3);
> +    IGraphBuilder_Disconnect(graph, &source3.source.pin.IPin_iface);
> +
> +    ref = IAMMultiMediaStream_Release(mmstream);
> +    ok(!ref, "Got outstanding refcount %d.\n", ref);
> +    ref = IGraphBuilder_Release(graph);
> +    ok(!ref, "Got outstanding refcount %d.\n", ref);
> +    IMediaSeeking_Release(seeking);
> +    ref = IMediaStreamFilter_Release(filter);
> +    ok(!ref, "Got outstanding refcount %d.\n", ref);
> +    IPin_Release(pin1);
> +    ref = IAMMediaStream_Release(stream1);
> +    ok(!ref, "Got outstanding refcount %d.\n", ref);
> +    IPin_Release(pin2);
> +    ref = IAMMediaStream_Release(stream2);
> +    ok(!ref, "Got outstanding refcount %d.\n", ref);
> +    IPin_Release(pin3);
> +    ref = IAMMediaStream_Release(stream3);
> +    ok(!ref, "Got outstanding refcount %d.\n", ref);
> +}
> +

Self-contained tests are nice, but there's an awful lot of boilerplate
here, and I think it wouldn't lose that much to merge this with the
GetStopPosition() and GetDuration() tests [and probably also
SetPositions()].

>  static void test_ddrawstream_getsetdirectdraw(void)
>  {
>      IAMMultiMediaStream *mmstream = create_ammultimediastream();
> @@ -8834,6 +8965,7 @@ START_TEST(amstream)
>      test_mediastreamfilter_get_current_stream_time();
>      test_mediastreamfilter_reference_time_to_stream_time();
>      test_mediastreamfilter_wait_until();
> +    test_mediastreamfilter_is_format_supported();
>  
>      CoUninitialize();
>  }
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20201116/777a60ca/attachment.sig>


More information about the wine-devel mailing list