From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/media_sink.c | 68 +++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/media_sink.c b/dlls/winegstreamer/media_sink.c index eab81ff0914..075ef0e73b5 100644 --- a/dlls/winegstreamer/media_sink.c +++ b/dlls/winegstreamer/media_sink.c @@ -32,6 +32,7 @@ enum async_op ASYNC_STOP, ASYNC_PAUSE, ASYNC_PROCESS, + ASYNC_FINALIZE, };
struct async_command @@ -48,6 +49,10 @@ struct async_command IMFSample *sample; UINT32 stream_id; } process; + struct + { + IMFAsyncResult *result; + } finalize; } u; };
@@ -80,6 +85,7 @@ struct media_sink STATE_STARTED, STATE_STOPPED, STATE_PAUSED, + STATE_FINALIZED, STATE_SHUTDOWN, } state; struct wg_container_format format; @@ -630,6 +636,23 @@ static HRESULT media_sink_process(struct media_sink *media_sink, IMFSample *samp return wg_muxer_push_sample(muxer, wg_sample); }
+static HRESULT media_sink_finalize(struct media_sink *media_sink, IMFAsyncResult *result) +{ + HRESULT hr; + + media_sink->state = STATE_FINALIZED; + + hr = wg_muxer_finalize(media_sink->muxer); + + if (SUCCEEDED(hr)) + hr = media_sink_write_stream(media_sink); + + IMFAsyncResult_SetStatus(result, hr); + MFInvokeCallback(result); + + return hr; +} + static HRESULT WINAPI media_sink_QueryInterface(IMFFinalizableMediaSink *iface, REFIID riid, void **obj) { struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface); @@ -869,16 +892,49 @@ static HRESULT WINAPI media_sink_Shutdown(IMFFinalizableMediaSink *iface)
static HRESULT WINAPI media_sink_BeginFinalize(IMFFinalizableMediaSink *iface, IMFAsyncCallback *callback, IUnknown *state) { - FIXME("iface %p, callback %p, state %p stub!\n", iface, callback, state); + struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface); + struct async_command *command; + IMFAsyncResult *result; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, callback %p, state %p.\n", iface, callback, state); + + EnterCriticalSection(&media_sink->cs); + + if (media_sink->state == STATE_SHUTDOWN) + { + LeaveCriticalSection(&media_sink->cs); + return MF_E_SHUTDOWN; + } + + if (FAILED(hr = async_command_create(ASYNC_FINALIZE, &command))) + { + LeaveCriticalSection(&media_sink->cs); + return hr; + } + if (callback) + { + if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &result))) + { + LeaveCriticalSection(&media_sink->cs); + free(command); + return hr; + } + IMFAsyncResult_AddRef((command->u.finalize.result = result)); + } + + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &media_sink->async_callback, &command->IUnknown_iface); + + LeaveCriticalSection(&media_sink->cs); + + return hr; }
static HRESULT WINAPI media_sink_EndFinalize(IMFFinalizableMediaSink *iface, IMFAsyncResult *result) { - FIXME("iface %p, result %p stub!\n", iface, result); + TRACE("iface %p, result %p.\n", iface, result);
- return E_NOTIMPL; + return result ? IMFAsyncResult_GetStatus(result) : E_INVALIDARG; }
static const IMFFinalizableMediaSinkVtbl media_sink_vtbl = @@ -1134,6 +1190,10 @@ static HRESULT WINAPI media_sink_callback_Invoke(IMFAsyncCallback *iface, IMFAsy if (FAILED(hr = media_sink_process(media_sink, command->u.process.sample, command->u.process.stream_id))) WARN("Failed to process sample, hr %#lx.\n", hr); break; + case ASYNC_FINALIZE: + if (FAILED(hr = media_sink_finalize(media_sink, command->u.finalize.result))) + WARN("Failed to finalize, hr %#lx.\n", hr); + break; default: WARN("Unsupported op %u.\n", command->op); break;