[PATCH v2 2/8] qedit: Implement IMediaDet::EnterBitmapGrabMode.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Fri Oct 23 10:18:52 CDT 2020
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/qedit/mediadet.c | 165 ++++++++++++++++++++++++++++++++++--
dlls/qedit/tests/mediadet.c | 40 +++++----
2 files changed, 178 insertions(+), 27 deletions(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c
index bacf520..5eb6aef 100644
--- a/dlls/qedit/mediadet.c
+++ b/dlls/qedit/mediadet.c
@@ -40,6 +40,7 @@ typedef struct MediaDetImpl {
IGraphBuilder *graph;
IBaseFilter *source;
IBaseFilter *splitter;
+ ISampleGrabber *grabber;
WCHAR *filename;
LONG num_streams;
LONG cur_stream;
@@ -64,6 +65,8 @@ static void MD_cleanup(MediaDetImpl *This)
This->source = NULL;
if (This->splitter) IBaseFilter_Release(This->splitter);
This->splitter = NULL;
+ if (This->grabber) ISampleGrabber_Release(This->grabber);
+ This->grabber = NULL;
if (This->graph) IGraphBuilder_Release(This->graph);
This->graph = NULL;
free(This->filename);
@@ -224,6 +227,71 @@ next:
return hr;
}
+static HRESULT seek_graph(MediaDetImpl *detector, double seek_time)
+{
+ FILTER_STATE state;
+ LONGLONG pos, stop;
+ IMediaControl *mc;
+ IMediaSeeking *ms;
+ IMediaFilter *mf;
+ GUID format;
+ HRESULT hr;
+
+ if (FAILED(hr = IPin_QueryInterface(detector->cur_pin, &IID_IMediaSeeking, (void**)&ms)))
+ return hr;
+
+ if (IMediaSeeking_IsUsingTimeFormat(ms, &TIME_FORMAT_MEDIA_TIME) != S_OK &&
+ (FAILED(IMediaSeeking_GetTimeFormat(ms, &format)) ||
+ !IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME)))
+ {
+ /* Windows doesn't implement it */
+ hr = E_NOTIMPL;
+ }
+ IMediaSeeking_Release(ms);
+ if (FAILED(hr))
+ return hr;
+
+ if (FAILED(hr = IGraphBuilder_QueryInterface(detector->graph, &IID_IMediaControl, (void**)&mc)))
+ return hr;
+
+ if (FAILED(hr = IMediaControl_Stop(mc)))
+ goto done;
+
+ if (seek_time >= 0.0)
+ {
+ if (FAILED(hr = IGraphBuilder_QueryInterface(detector->graph, &IID_IMediaSeeking, (void**)&ms)))
+ goto done;
+
+ stop = pos = seek_time * 10000000.0;
+ hr = IMediaSeeking_SetPositions(ms, &pos, AM_SEEKING_AbsolutePositioning,
+ &stop, AM_SEEKING_AbsolutePositioning);
+ IMediaSeeking_Release(ms);
+ if (FAILED(hr))
+ goto done;
+ }
+
+ if (FAILED(hr = IGraphBuilder_QueryInterface(detector->graph, &IID_IMediaFilter, (void**)&mf)))
+ goto done;
+ hr = IMediaFilter_SetSyncSource(mf, NULL);
+ IMediaFilter_Release(mf);
+ if (FAILED(hr)) goto done;
+
+ if (FAILED(hr = IMediaControl_Pause(mc)))
+ goto done;
+
+ /* Testing on Windows shows it waits up to 37500 ms */
+ if (FAILED(hr = IMediaControl_GetState(mc, 37500, (OAFilterState*)&state)))
+ {
+ if (hr == VFW_S_STATE_INTERMEDIATE) hr = VFW_E_TIME_EXPIRED;
+ goto done;
+ }
+
+ hr = S_OK;
+done:
+ IMediaControl_Release(mc);
+ return hr;
+}
+
/* MediaDet inner IUnknown */
static HRESULT WINAPI MediaDet_inner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
@@ -371,7 +439,7 @@ static HRESULT WINAPI MediaDet_get_OutputStreams(IMediaDet* iface, LONG *pVal)
TRACE("(%p)\n", This);
- if (!This->splitter)
+ if (This->grabber || !This->splitter)
return E_INVALIDARG;
if (This->num_streams != -1)
@@ -466,6 +534,9 @@ static HRESULT WINAPI MediaDet_put_CurrentStream(IMediaDet* iface, LONG newVal)
TRACE("(%p)->(%d)\n", This, newVal);
+ if (This->grabber)
+ return E_INVALIDARG;
+
if (This->num_streams == -1)
{
LONG n;
@@ -495,6 +566,8 @@ static HRESULT WINAPI MediaDet_get_StreamType(IMediaDet *iface, GUID *majortype)
if (!majortype)
return E_POINTER;
+ if (detector->grabber)
+ return E_INVALIDARG;
if (SUCCEEDED(hr = IMediaDet_get_StreamMediaType(iface, &mt)))
{
@@ -533,7 +606,7 @@ static HRESULT WINAPI MediaDet_get_StreamLength(IMediaDet *iface, double *length
if (!length)
return E_POINTER;
- if (!detector->cur_pin)
+ if (detector->grabber || !detector->cur_pin)
return E_INVALIDARG;
if (SUCCEEDED(hr = IPin_QueryInterface(detector->cur_pin,
@@ -647,7 +720,7 @@ static HRESULT WINAPI MediaDet_get_StreamMediaType(IMediaDet* iface,
if (!pVal)
return E_POINTER;
- if (!This->cur_pin)
+ if (This->grabber || !This->cur_pin)
return E_INVALIDARG;
return get_pin_media_type(This->cur_pin, pVal);
@@ -672,6 +745,8 @@ static HRESULT WINAPI MediaDet_get_FrameRate(IMediaDet* iface, double *pVal)
if (!pVal)
return E_POINTER;
+ if (This->grabber)
+ return E_INVALIDARG;
hr = MediaDet_get_StreamMediaType(iface, &mt);
if (FAILED(hr))
@@ -693,9 +768,87 @@ static HRESULT WINAPI MediaDet_get_FrameRate(IMediaDet* iface, double *pVal)
static HRESULT WINAPI MediaDet_EnterBitmapGrabMode(IMediaDet* iface,
double SeekTime)
{
- MediaDetImpl *This = impl_from_IMediaDet(iface);
- FIXME("(%p)->(%f): not implemented!\n", This, SeekTime);
- return E_NOTIMPL;
+ MediaDetImpl *detector = impl_from_IMediaDet(iface);
+ IPin *sg_inpin, *sg_outpin, *null_pin;
+ IBaseFilter *sg_filter, *null_filter;
+ ISampleGrabber *sg;
+ AM_MEDIA_TYPE mt;
+ GUID major_type;
+ IUnknown *unk;
+ HRESULT hr;
+
+ TRACE("(%p)->(%.16e)\n", detector, SeekTime);
+
+ if (detector->grabber)
+ return S_OK;
+ if (!detector->cur_pin)
+ return E_INVALIDARG;
+ if (FAILED(hr = get_pin_media_type(detector->cur_pin, &mt)))
+ return hr;
+ major_type = mt.majortype;
+ FreeMediaType(&mt);
+ if (!IsEqualGUID(&major_type, &MEDIATYPE_Video))
+ return VFW_E_INVALIDMEDIATYPE;
+
+ hr = sample_grabber_create(NULL, &unk);
+ if (FAILED(hr)) return hr;
+ IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void**)&sg_filter);
+ IUnknown_Release(unk);
+
+ hr = null_renderer_create(NULL, &unk);
+ if (FAILED(hr))
+ {
+ IBaseFilter_Release(sg_filter);
+ return hr;
+ }
+ IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void**)&null_filter);
+ IUnknown_Release(unk);
+
+ memset(&mt, 0, sizeof(mt));
+ mt.majortype = MEDIATYPE_Video;
+ mt.subtype = MEDIASUBTYPE_RGB24;
+ mt.formattype = FORMAT_VideoInfo;
+
+ IBaseFilter_QueryInterface(sg_filter, &IID_ISampleGrabber, (void**)&sg);
+ ISampleGrabber_SetMediaType(sg, &mt);
+ ISampleGrabber_SetBufferSamples(sg, TRUE);
+
+ IBaseFilter_FindPin(sg_filter, L"In", &sg_inpin);
+ IBaseFilter_FindPin(sg_filter, L"Out", &sg_outpin);
+ IBaseFilter_FindPin(null_filter, L"In", &null_pin);
+
+ if (FAILED(hr = IGraphBuilder_AddFilter(detector->graph, sg_filter, L"BitBucket")))
+ {
+ ISampleGrabber_Release(sg);
+ goto done;
+ }
+
+ if (FAILED(hr = IGraphBuilder_AddFilter(detector->graph, null_filter, L"NullRenderer")))
+ {
+ IGraphBuilder_RemoveFilter(detector->graph, sg_filter);
+ ISampleGrabber_Release(sg);
+ goto done;
+ }
+
+ if (FAILED(hr = IGraphBuilder_Connect(detector->graph, detector->cur_pin, sg_inpin)) ||
+ FAILED(hr = IGraphBuilder_ConnectDirect(detector->graph, sg_outpin, null_pin, NULL)) ||
+ FAILED(hr = seek_graph(detector, SeekTime)))
+ {
+ IGraphBuilder_RemoveFilter(detector->graph, null_filter);
+ IGraphBuilder_RemoveFilter(detector->graph, sg_filter);
+ ISampleGrabber_Release(sg);
+ goto done;
+ }
+
+ detector->grabber = sg;
+
+done:
+ IPin_Release(null_pin);
+ IPin_Release(sg_outpin);
+ IPin_Release(sg_inpin);
+ IBaseFilter_Release(null_filter);
+ IBaseFilter_Release(sg_filter);
+ return hr;
}
static const IMediaDetVtbl IMediaDet_VTable =
diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c
index 0a05a65..71d4a4b 100644
--- a/dlls/qedit/tests/mediadet.c
+++ b/dlls/qedit/tests/mediadet.c
@@ -1326,7 +1326,7 @@ static void test_bitmap_grab_mode(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IMediaDet_EnterBitmapGrabMode(detector, 0.0);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_GetSampleGrabber(detector, &sg);
todo_wine ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
@@ -1337,7 +1337,7 @@ static void test_bitmap_grab_mode(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IMediaDet_EnterBitmapGrabMode(detector, 0.0);
- todo_wine ok(hr == VFW_E_INVALIDMEDIATYPE, "Got hr %#x.\n", hr);
+ ok(hr == VFW_E_INVALIDMEDIATYPE, "Got hr %#x.\n", hr);
ref = IMediaDet_Release(detector);
ok(!ref, "Got outstanding refcount %d.\n", ref);
@@ -1355,10 +1355,10 @@ static void test_bitmap_grab_mode(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IMediaDet_EnterBitmapGrabMode(detector, -1.0);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(testfilter.cur_pos == 0xdeadbeef, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
hr = IMediaDet_EnterBitmapGrabMode(detector, 1.0);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(testfilter.cur_pos == 0xdeadbeef, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
ref = IMediaDet_Release(detector);
@@ -1382,11 +1382,11 @@ static void test_bitmap_grab_mode(void)
hr = IMediaDet_EnterBitmapGrabMode(detector, 1337.0);
if (time_formats[i] == &TIME_FORMAT_MEDIA_TIME)
{
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(testfilter.cur_pos == 13370000000LL, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(testfilter.cur_pos == 13370000000LL, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
hr = IMediaDet_EnterBitmapGrabMode(detector, 1.0);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(testfilter.cur_pos == 13370000000LL, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(testfilter.cur_pos == 13370000000LL, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
}
else
ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
@@ -1407,11 +1407,11 @@ static void test_bitmap_grab_mode(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IMediaDet_EnterBitmapGrabMode(detector, 0.0);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(testfilter.cur_pos == 0, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(testfilter.cur_pos == 0, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
hr = IMediaDet_EnterBitmapGrabMode(detector, 1.0);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(testfilter.cur_pos == 0, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(testfilter.cur_pos == 0, "Current position was set to 0x%s.\n", wine_dbgstr_longlong(testfilter.cur_pos));
/* These still work */
hr = IMediaDet_get_Filter(detector, &unk);
@@ -1426,21 +1426,19 @@ static void test_bitmap_grab_mode(void)
/* These don't work anymore */
hr = IMediaDet_get_OutputStreams(detector, &count);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_get_FrameRate(detector, &duration);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_get_StreamLength(detector, &duration);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_get_StreamMediaType(detector, &mt);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
- if (SUCCEEDED(hr)) FreeMediaType(&mt);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_get_StreamType(detector, &guid);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_get_StreamTypeB(detector, &str);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
- if (SUCCEEDED(hr)) SysFreeString(str);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = IMediaDet_put_CurrentStream(detector, 0);
- todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
/* Check the SampleGrabber */
hr = IMediaDet_GetSampleGrabber(detector, &sg);
--
2.21.0
More information about the wine-devel
mailing list