[PATCH 3/5] amstream: Implement MediaStreamFilter::SupportSeeking.
Zebediah Figura
zfigura at codeweavers.com
Tue Jun 2 11:04:00 CDT 2020
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.
More information about the wine-devel
mailing list