From: Ziqing Hui zhui@codeweavers.com
--- dlls/qasf/dmowrapper.c | 61 ++++++++++++++++++++++++------------ dlls/qasf/tests/dmowrapper.c | 3 -- 2 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/dlls/qasf/dmowrapper.c b/dlls/qasf/dmowrapper.c index 95e12e860ae..97cf43cbeff 100644 --- a/dlls/qasf/dmowrapper.c +++ b/dlls/qasf/dmowrapper.c @@ -202,12 +202,24 @@ static void dmo_wrapper_sink_disconnect(struct strmbase_sink *iface) IMediaObject_Release(dmo); }
-static HRESULT process_output(struct dmo_wrapper *filter, IMediaObject *dmo) +static void release_output_samples(struct dmo_wrapper *filter) +{ + DWORD i; + + for (i = 0; i < filter->source_count; ++i) + { + if (filter->sources[i].buffer.sample) + { + IMediaSample_Release(filter->sources[i].buffer.sample); + filter->sources[i].buffer.sample = NULL; + } + } +} + +static HRESULT get_output_samples(struct dmo_wrapper *filter) { - DMO_OUTPUT_DATA_BUFFER *buffers = filter->buffers; - DWORD status, i; - BOOL more_data; HRESULT hr; + DWORD i;
for (i = 0; i < filter->source_count; ++i) { @@ -216,16 +228,27 @@ static HRESULT process_output(struct dmo_wrapper *filter, IMediaObject *dmo) if (FAILED(hr = IMemAllocator_GetBuffer(filter->sources[i].pin.pAllocator, &filter->sources[i].buffer.sample, NULL, NULL, 0))) { - ERR("Failed to get sample, hr %#lx.\n", hr); - goto out; + ERR("Failed to get sample for source %lu, hr %#lx.\n", i, hr); + release_output_samples(filter); + return hr; } - buffers[i].pBuffer = &filter->sources[i].buffer.IMediaBuffer_iface; + filter->buffers[i].pBuffer = &filter->sources[i].buffer.IMediaBuffer_iface; IMediaSample_SetActualDataLength(filter->sources[i].buffer.sample, 0); } else - buffers[i].pBuffer = NULL; + filter->buffers[i].pBuffer = NULL; }
+ return S_OK; +} + +static HRESULT process_output(struct dmo_wrapper *filter, IMediaObject *dmo) +{ + DMO_OUTPUT_DATA_BUFFER *buffers = filter->buffers; + DWORD status, i; + BOOL more_data; + HRESULT hr; + do { more_data = FALSE; @@ -264,7 +287,8 @@ static HRESULT process_output(struct dmo_wrapper *filter, IMediaObject *dmo) if (FAILED(hr = IMemInputPin_Receive(filter->sources[i].pin.pMemInputPin, sample))) { WARN("Downstream sink returned %#lx.\n", hr); - goto out; + release_output_samples(filter); + return hr; } IMediaSample_SetActualDataLength(sample, 0); } @@ -272,16 +296,7 @@ static HRESULT process_output(struct dmo_wrapper *filter, IMediaObject *dmo) } } while (more_data);
-out: - for (i = 0; i < filter->source_count; ++i) - { - if (filter->sources[i].buffer.sample) - { - IMediaSample_Release(filter->sources[i].buffer.sample); - filter->sources[i].buffer.sample = NULL; - } - } - + release_output_samples(filter); return hr; }
@@ -307,9 +322,14 @@ static HRESULT WINAPI dmo_wrapper_sink_Receive(struct strmbase_sink *iface, IMed /* Calling Discontinuity() might change the DMO's mind about whether it * has more data to process. The DirectX documentation explicitly * states that we should call ProcessOutput() again in this case. */ + if (FAILED(hr = get_output_samples(filter))) + goto out; process_output(filter, dmo); }
+ if (FAILED(hr = get_output_samples(filter))) + goto out; + if (IMediaSample_IsSyncPoint(sample) == S_OK) flags |= DMO_INPUT_DATA_BUFFERF_SYNCPOINT;
@@ -348,7 +368,8 @@ static HRESULT dmo_wrapper_sink_eos(struct strmbase_sink *iface) if (FAILED(hr = IMediaObject_Discontinuity(dmo, index))) ERR("Discontinuity() failed, hr %#lx.\n", hr);
- process_output(filter, dmo); + if (SUCCEEDED(get_output_samples(filter))) + process_output(filter, dmo); if (FAILED(hr = IMediaObject_Flush(dmo))) ERR("Flush() failed, hr %#lx.\n", hr);
diff --git a/dlls/qasf/tests/dmowrapper.c b/dlls/qasf/tests/dmowrapper.c index 632b7e2e558..ada45c447b1 100644 --- a/dlls/qasf/tests/dmowrapper.c +++ b/dlls/qasf/tests/dmowrapper.c @@ -1703,9 +1703,7 @@ static void test_sample_processing(IMediaControl *control, IMemInputPin *input, hr = IMemAllocator_Decommit(testsink->sink.pAllocator); ok(hr == S_OK, "Decommit returned %#lx.\n", hr); hr = IMemInputPin_Receive(input, sample); - todo_wine ok(hr == VFW_E_NOT_COMMITTED, "Receive returned %#lx.\n", hr); - todo_wine ok(got_ProcessInput == 0, "Got %u calls to ProcessInput().\n", got_ProcessInput); ok(got_ProcessOutput == 0, "Got %u calls to ProcessOutput().\n", got_ProcessOutput); ok(got_Receive == 0, "Got %u calls to Receive().\n", got_Receive); @@ -1720,7 +1718,6 @@ static void test_sample_processing(IMediaControl *control, IMemInputPin *input, hr = IMemInputPin_Receive(input, sample); todo_wine ok(hr == VFW_E_WRONG_STATE, "Receive returned %#lx.\n", hr); - todo_wine ok(got_ProcessInput == 0, "Got %u calls to ProcessInput().\n", got_ProcessInput); ok(got_ProcessOutput == 0, "Got %u calls to ProcessOutput().\n", got_ProcessOutput); ok(got_Receive == 0, "Got %u calls to Receive().\n", got_Receive);