The splitter may return S_FALSE (no pins) and this caused a crash when it somehow matched with the File Source (Async).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/qedit/mediadet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c index eb7a519..c3891c5 100644 --- a/dlls/qedit/mediadet.c +++ b/dlls/qedit/mediadet.c @@ -197,7 +197,7 @@ static HRESULT find_splitter(MediaDetImpl *detector)
hr = IEnumPins_Next(enum_pins, 1, &splitter_pin, NULL); IEnumPins_Release(enum_pins); - if (FAILED(hr)) + if (hr != S_OK) goto next;
hr = IPin_Connect(source_pin, splitter_pin, NULL);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/qedit/mediadet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c index c3891c5..3923205 100644 --- a/dlls/qedit/mediadet.c +++ b/dlls/qedit/mediadet.c @@ -145,7 +145,7 @@ static HRESULT find_splitter(MediaDetImpl *detector) } hr = IEnumPins_Next(enum_pins, 1, &source_pin, NULL); IEnumPins_Release(enum_pins); - if (FAILED(hr)) + if (hr != S_OK) { ERR("Failed to get source pin, hr %#x.\n", hr); return hr;
Signed-off-by: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/qedit/mediadet.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c index 3923205..ac382ff 100644 --- a/dlls/qedit/mediadet.c +++ b/dlls/qedit/mediadet.c @@ -103,6 +103,28 @@ static HRESULT get_filter_info(IMoniker *moniker, GUID *clsid, VARIANT *var) return hr; }
+static HRESULT get_pin_media_type(IPin *pin, AM_MEDIA_TYPE *out) +{ + IEnumMediaTypes *types; + AM_MEDIA_TYPE *pmt; + HRESULT hr; + + hr = IPin_EnumMediaTypes(pin, &types); + if (SUCCEEDED(hr)) + { + hr = IEnumMediaTypes_Next(types, 1, &pmt, NULL) == S_OK ? S_OK : E_NOINTERFACE; + IEnumMediaTypes_Release(types); + } + + if (SUCCEEDED(hr)) + { + *out = *pmt; + CoTaskMemFree(pmt); + } + + return hr; +} + static HRESULT find_splitter(MediaDetImpl *detector) { IPin *source_pin, *splitter_pin; @@ -611,9 +633,6 @@ static HRESULT WINAPI MediaDet_get_StreamMediaType(IMediaDet* iface, AM_MEDIA_TYPE *pVal) { MediaDetImpl *This = impl_from_IMediaDet(iface); - IEnumMediaTypes *types; - AM_MEDIA_TYPE *pmt; - HRESULT hr;
TRACE("(%p)\n", This);
@@ -623,22 +642,7 @@ static HRESULT WINAPI MediaDet_get_StreamMediaType(IMediaDet* iface, if (!This->cur_pin) return E_INVALIDARG;
- hr = IPin_EnumMediaTypes(This->cur_pin, &types); - if (SUCCEEDED(hr)) - { - hr = (IEnumMediaTypes_Next(types, 1, &pmt, NULL) == S_OK - ? S_OK - : E_NOINTERFACE); - IEnumMediaTypes_Release(types); - } - - if (SUCCEEDED(hr)) - { - *pVal = *pmt; - CoTaskMemFree(pmt); - } - - return hr; + return get_pin_media_type(This->cur_pin, pVal); }
static HRESULT WINAPI MediaDet_GetSampleGrabber(IMediaDet* iface,
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/qedit/mediadet.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c index ac382ff..ff7f0f9 100644 --- a/dlls/qedit/mediadet.c +++ b/dlls/qedit/mediadet.c @@ -128,12 +128,10 @@ static HRESULT get_pin_media_type(IPin *pin, AM_MEDIA_TYPE *out) static HRESULT find_splitter(MediaDetImpl *detector) { IPin *source_pin, *splitter_pin; - IFileSourceFilter *file_source; IEnumMoniker *enum_moniker; IFilterMapper2 *mapper; IBaseFilter *splitter; IEnumPins *enum_pins; - LPOLESTR filename; AM_MEDIA_TYPE mt; IMoniker *mon; GUID type[2]; @@ -141,25 +139,6 @@ static HRESULT find_splitter(MediaDetImpl *detector) HRESULT hr; GUID clsid;
- if (FAILED(hr = IBaseFilter_QueryInterface(detector->source, - &IID_IFileSourceFilter, (void **)&file_source))) - { - ERR("Failed to get file source interface.\n"); - return hr; - } - - hr = IFileSourceFilter_GetCurFile(file_source, &filename, &mt); - IFileSourceFilter_Release(file_source); - CoTaskMemFree(filename); - if (FAILED(hr)) - { - ERR("Failed to get current file, hr %#x.\n", hr); - return hr; - } - type[0] = mt.majortype; - type[1] = mt.subtype; - FreeMediaType(&mt); - if (FAILED(hr = IBaseFilter_EnumPins(detector->source, &enum_pins))) { ERR("Failed to enumerate source pins, hr %#x.\n", hr); @@ -173,6 +152,17 @@ static HRESULT find_splitter(MediaDetImpl *detector) return hr; }
+ if (FAILED(hr = get_pin_media_type(source_pin, &mt))) + { + ERR("Failed to get media type, hr %#x.\n", hr); + IPin_Release(source_pin); + return hr; + } + + type[0] = mt.majortype; + type[1] = mt.subtype; + FreeMediaType(&mt); + if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (void **)&mapper))) {
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Comparing directly to 4.2 works, I guess it was just a display issue since it can't be represented exactly in base 2.
dlls/qedit/mediadet.c | 32 ++++++- dlls/qedit/tests/mediadet.c | 185 ++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 3 deletions(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c index ff7f0f9..6abf19a 100644 --- a/dlls/qedit/mediadet.c +++ b/dlls/qedit/mediadet.c @@ -528,11 +528,37 @@ static HRESULT WINAPI MediaDet_get_StreamTypeB(IMediaDet *iface, BSTR *bstr) return hr; }
-static HRESULT WINAPI MediaDet_get_StreamLength(IMediaDet* iface, double *pVal) +static HRESULT WINAPI MediaDet_get_StreamLength(IMediaDet* iface, double *length) { MediaDetImpl *This = impl_from_IMediaDet(iface); - FIXME("(%p): stub!\n", This); - return VFW_E_INVALIDMEDIATYPE; + IMediaSeeking *seeking; + HRESULT hr; + + TRACE("detector %p, output length %p.\n", This, length); + + if (!length) + return E_POINTER; + + if (!This->cur_pin) + return E_INVALIDARG; + + hr = IPin_QueryInterface(This->cur_pin, &IID_IMediaSeeking, (void **) &seeking); + if (SUCCEEDED(hr)) + { + LONGLONG duration; + + hr = IMediaSeeking_GetDuration(seeking, &duration); + if (SUCCEEDED(hr)) + { + /* Windows assumes the time format is TIME_FORMAT_MEDIA_TIME + and does not check it nor convert it, as tests show. */ + *length = (REFTIME)duration / 10000000; + } + IMediaSeeking_Release(seeking); + return hr; + } + + return hr; }
static HRESULT WINAPI MediaDet_get_Filename(IMediaDet* iface, BSTR *pVal) diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c index 3286147..70fb250 100644 --- a/dlls/qedit/tests/mediadet.c +++ b/dlls/qedit/tests/mediadet.c @@ -135,6 +135,7 @@ struct testfilter { struct strmbase_filter filter; struct strmbase_source source; + IMediaSeeking IMediaSeeking_iface; };
static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface) @@ -163,6 +164,11 @@ static const struct strmbase_filter_ops testfilter_ops = .filter_destroy = testfilter_destroy, };
+static inline struct testfilter *impl_from_strmbase_pin(struct strmbase_pin *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, source.pin); +} + static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt) { static const VIDEOINFOHEADER source_format = @@ -192,6 +198,19 @@ static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned in return S_OK; }
+static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_strmbase_pin(iface); + + if (IsEqualGUID(iid, &IID_IMediaSeeking)) + *out = &filter->IMediaSeeking_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown*)*out); + return S_OK; +} + static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, IMemInputPin *peer, IMemAllocator **allocator) { @@ -201,10 +220,164 @@ static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, static const struct strmbase_source_ops testsource_ops = { .base.pin_get_media_type = testsource_get_media_type, + .base.pin_query_interface = testsource_query_interface, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = testsource_DecideAllocator, };
+static inline struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface); +} + +static HRESULT WINAPI testseek_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out); +} + +static ULONG WINAPI testseek_AddRef(IMediaSeeking *iface) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IPin_AddRef(&filter->source.pin.IPin_iface); +} + +static ULONG WINAPI testseek_Release(IMediaSeeking *iface) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IPin_Release(&filter->source.pin.IPin_iface); +} + +static HRESULT WINAPI testseek_GetCapabilities(IMediaSeeking *iface, DWORD *caps) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_CheckCapabilities(IMediaSeeking *iface, DWORD *caps) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_IsFormatSupported(IMediaSeeking *iface, const GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_QueryPreferredFormat(IMediaSeeking *iface, GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetTimeFormat(IMediaSeeking *iface, GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_SetTimeFormat(IMediaSeeking *iface, const GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *duration) +{ + if (winetest_debug > 1) trace("IMediaSeeking_GetDuration()\n"); + + *duration = 42000000; + return S_OK; +} + +static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target, + const GUID *target_format, LONGLONG source, const GUID *source_format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_SetPositions(IMediaSeeking *iface, LONGLONG *current, + DWORD current_flags, LONGLONG *stop, DWORD stop_flags) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_SetRate(IMediaSeeking *iface, double rate) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetRate(IMediaSeeking *iface, double *rate) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static const IMediaSeekingVtbl testseek_vtbl = +{ + testseek_QueryInterface, + testseek_AddRef, + testseek_Release, + testseek_GetCapabilities, + testseek_CheckCapabilities, + testseek_IsFormatSupported, + testseek_QueryPreferredFormat, + testseek_GetTimeFormat, + testseek_IsUsingTimeFormat, + testseek_SetTimeFormat, + testseek_GetDuration, + testseek_GetStopPosition, + testseek_GetCurrentPosition, + testseek_ConvertTimeFormat, + testseek_SetPositions, + testseek_GetPositions, + testseek_GetAvailable, + testseek_SetRate, + testseek_GetRate, + testseek_GetPreroll +}; + static void testfilter_init(struct testfilter *filter) { static const GUID clsid = {0xabacab}; @@ -212,6 +385,7 @@ static void testfilter_init(struct testfilter *filter) memset(filter, 0, sizeof(*filter)); strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops); strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops); + filter->IMediaSeeking_iface.lpVtbl = &testseek_vtbl; }
static WCHAR test_avi_filename[MAX_PATH]; @@ -571,6 +745,7 @@ static void test_put_filter(void) IMediaDet *detector; LONG index, count; AM_MEDIA_TYPE mt; + double duration; IUnknown *unk; BSTR filename; HRESULT hr; @@ -586,6 +761,12 @@ static void test_put_filter(void) hr = IMediaDet_get_Filter(detector, NULL); ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IMediaDet_get_StreamLength(detector, NULL); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + hr = IMediaDet_get_StreamLength(detector, &duration); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + testfilter_init(&testfilter); hr = IMediaDet_put_Filter(detector, &testfilter.filter.IUnknown_inner); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -639,6 +820,10 @@ static void test_put_filter(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(!filename, "Got filename %s.\n", debugstr_w(filename));
+ hr = IMediaDet_get_StreamLength(detector, &duration); + ok(hr == S_OK, "IMediaDet_get_StreamLength failed: %08x\n", hr); + ok(duration == 4.2, "Got duration %.16e\n", duration); + ref = IMediaDet_Release(detector); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IBaseFilter_Release(&testfilter2.filter.IBaseFilter_iface);
On 4/27/20 8:07 AM, Gabriel Ivăncescu wrote:
The splitter may return S_FALSE (no pins) and this caused a crash when it somehow matched with the File Source (Async).
Yes, we should probably be passing TRUE as the "need input" parameter.