[PATCH 3/5] amstream: Implement MediaStreamFilter::SupportSeeking.

Zebediah Figura zfigura at codeweavers.com
Wed Jun 3 11:31:43 CDT 2020


On 6/3/20 11:36 AM, Anton Baskanov wrote:
> On Tuesday, 2 June 2020 23:04:00 +07 you wrote:
>> On 6/2/20 10:54 AM, Zebediah Figura wrote:
>>> On 6/1/20 11:13 PM, Anton Baskanov wrote:
>>>> Signed-off-by: Anton Baskanov <baskanov at gmail.com>
>>>> ---
>>>>
>>>>   dlls/amstream/filter.c         | 249 ++++++++++++++++++++++++-
>>>>   dlls/amstream/tests/amstream.c | 323 +++++++++++++++++++++++++++++++++
>>>>   2 files changed, 568 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/dlls/amstream/filter.c b/dlls/amstream/filter.c
>>>> index 4b5e184f04..643cfcdbe4 100644
>>>> --- a/dlls/amstream/filter.c
>>>> +++ b/dlls/amstream/filter.c
>>>> @@ -163,6 +163,7 @@ static const IEnumPinsVtbl enum_pins_vtbl =
>>>>
>>>>   struct filter
>>>>   {
>>>>   
>>>>       IMediaStreamFilter IMediaStreamFilter_iface;
>>>>
>>>> +    IMediaSeeking IMediaSeeking_iface;
>>>>
>>>>       LONG refcount;
>>>>       CRITICAL_SECTION cs;
>>>>
>>>> @@ -171,6 +172,7 @@ struct filter
>>>>
>>>>       IFilterGraph *graph;
>>>>       ULONG nb_streams;
>>>>       IAMMediaStream **streams;
>>>>
>>>> +    IAMMediaStream *seekable_stream;
>>>>
>>>>       FILTER_STATE state;
>>>>   
>>>>   };
>>>>
>>>> @@ -181,6 +183,8 @@ static inline struct filter
>>>> *impl_from_IMediaStreamFilter(IMediaStreamFilter *if>>
>>>>   static HRESULT WINAPI filter_QueryInterface(IMediaStreamFilter *iface,
>>>>   REFIID riid, void **ret_iface) {
>>>>
>>>> +    struct filter *filter = impl_from_IMediaStreamFilter(iface);
>>>> +
>>>>
>>>>       TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
>>>>       
>>>>       *ret_iface = NULL;
>>>>
>>>> @@ -191,10 +195,12 @@ static HRESULT WINAPI
>>>> filter_QueryInterface(IMediaStreamFilter *iface, REFIID ri>>
>>>>           IsEqualIID(riid, &IID_IBaseFilter) ||
>>>>           IsEqualIID(riid, &IID_IMediaStreamFilter))
>>>>           *ret_iface = iface;
>>>>
>>>> +    else if (IsEqualIID(riid, &IID_IMediaSeeking) &&
>>>> filter->seekable_stream) +        *ret_iface =
>>>> &filter->IMediaSeeking_iface;
>>>>
>>>>       if (*ret_iface)
>>>>       {
>>>>
>>>> -        IMediaStreamFilter_AddRef(*ret_iface);
>>>> +        IUnknown_AddRef((IUnknown *)*ret_iface);
>>>>
>>>>           return S_OK;
>>>>       
>>>>       }
>>>>
>>>> @@ -544,11 +550,74 @@ static HRESULT WINAPI
>>>> filter_EnumMediaStreams(IMediaStreamFilter *iface, LONG in>>
>>>>       return S_OK;
>>>>   
>>>>   }
>>>>
>>>> -static HRESULT WINAPI filter_SupportSeeking(IMediaStreamFilter *iface,
>>>> BOOL bRenderer) +static IMediaSeeking *get_seeking(IAMMediaStream
>>>> *stream)
>>>>
>>>>   {
>>>>
>>>> -    FIXME("(%p)->(%d): Stub!\n", iface, bRenderer);
>>>> +    IPin *pin;
>>>> +    IPin *peer;
>>>> +    IMediaSeeking *seeking;
>>>>
>>>> -    return E_NOTIMPL;
>>>> +    if (FAILED(IAMMediaStream_QueryInterface(stream, &IID_IPin, (void
>>>> **)&pin))) +    {
>>>> +        WARN("Stream %p does not support IPin.\n", stream);
>>>> +        return NULL;
>>>> +    }
>>>> +
>>>> +    if (FAILED(IPin_ConnectedTo(pin, &peer)))
>>>> +    {
>>>> +        IPin_Release(pin);
>>>> +        return NULL;
>>>> +    }
>>>> +
>>>> +    if (FAILED(IPin_QueryInterface(peer, &IID_IMediaSeeking, (void
>>>> **)&seeking))) +    {
>>>> +        IPin_Release(peer);
>>>> +        IPin_Release(pin);
>>>> +        return NULL;
>>>> +    }
>>>> +
>>>> +    IPin_Release(peer);
>>>> +    IPin_Release(pin);
>>>> +
>>>> +    return seeking;
>>>> +}
>>>> +
>>>> +static HRESULT WINAPI filter_SupportSeeking(IMediaStreamFilter *iface,
>>>> BOOL renderer) +{
>>>> +    struct filter *filter = impl_from_IMediaStreamFilter(iface);
>>>> +    unsigned int i;
>>>> +    HRESULT hr = E_NOINTERFACE;
>>>> +
>>>> +    TRACE("filter %p, renderer %d\n", iface, renderer);
>>>
>>> Without tests to show whether/how the "renderer" value makes a
>>> difference, I think we should print a FIXME if it's FALSE.
>>>
>>>> +
>>>> +    EnterCriticalSection(&filter->cs);
>>>> +
>>>> +    if (filter->seekable_stream)
>>>> +        return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
>>>
>>> Missing LeaveCriticalSection().
>>>
>>>> +
>>>> +    for (i = 0; i < filter->nb_streams; ++i)
>>>> +    {
>>>> +        IMediaSeeking *seeking = get_seeking(filter->streams[i]);
>>>> +        LONGLONG duration;
>>>> +
>>>> +        if (!seeking)
>>>> +            continue;
>>>> +
>>>> +        if (FAILED(IMediaSeeking_GetDuration(seeking, &duration)))
>>>> +        {
>>>> +            IMediaSeeking_Release(seeking);
>>>> +            continue;
>>>> +        }
>>>> +
>>>> +        filter->seekable_stream = filter->streams[i];
>>>> +        hr = S_OK;
>>>> +        IMediaSeeking_Release(seeking);
>>>
>>> Is it correct that only one stream is chosen for seeking, even if there
>>> are multiple available? Consider e.g. the quartz filter graph, which
>>> seeks all available streams.
>>>
>>> For that matter, should we be delegating to the filter graph instead of
>>> seeking the pins directly?
>>>
>>> One thing in particular to test is whether filters are paused when
>>> seeked. Even if we don't delegate to the filter graph, we likely want to
>>> do this anyway.
>>>
>>> Another thing to test is whether GetCurrentPosition() returns something
>>> reflecting the reference clock time, or the last sample time, or whether
>>> it fails if no exposed streams support GetCurrentPosition().
>>
>> Sorry, on reflection, I realize this doesn't make sense, because we
>> *are* the sink filter. multimedia stream ≠ stream filter...
>>
>> I think the question about seeking multiple streams still stands, though.
> 
> ::SetPosition tests show that only one stream is used for seeking and that
> ::SupportSeeking determines which one will be used. Probably it's assumed that
> all the streams come from the same splitter filter.
> 
> 

Ah yes, I see you're right; I clearly didn't read closely enough.

I guess it makes sense anyway, after all, in the case of amstream 
everything's expected to go through OpenFile anyway.



More information about the wine-devel mailing list