From: Ziqing Hui zhui@codeweavers.com
For media sink which can not be created without setting media types, instead of creating the media sink during sink writer creation, we store the factory and bytestream objects and create the media sink later. --- dlls/mfreadwrite/tests/mfplat.c | 2 +- dlls/mfreadwrite/writer.c | 94 +++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 29 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 27a503a8025..da9966e78fc 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1548,7 +1548,7 @@ START_TEST(mfplat) test_source_reader_from_media_source(); test_reader_d3d9();
- test_sink_writer_create("wav", TRUE); + test_sink_writer_create("wav", FALSE); test_sink_writer_create("mp3", TRUE); test_sink_writer_create("mp4", TRUE); test_sink_writer_create("asf", TRUE); diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index 83b0442b20e..a3d105c0994 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -71,6 +71,9 @@ struct sink_writer IMFAsyncCallback events_callback; LONG refcount;
+ IMFSinkClassFactory *factory; + IMFByteStream *bytestream; + struct { struct stream *items; @@ -223,6 +226,10 @@ static ULONG WINAPI sink_writer_Release(IMFSinkWriter *iface)
if (!refcount) { + if (writer->factory) + IMFSinkClassFactory_Release(writer->factory); + if (writer->bytestream) + IMFByteStream_Release(writer->bytestream); if (writer->clock) IMFPresentationClock_Release(writer->clock); if (writer->sink) @@ -942,6 +949,8 @@ static HRESULT sink_writer_initialize_existing_streams(struct sink_writer *write DWORD count = 0, i, index; HRESULT hr;
+ IMFMediaSink_AddRef(writer->sink = sink); + if (FAILED(hr = IMFMediaSink_GetStreamSinkCount(sink, &count))) return hr; if (!count) return S_OK;
@@ -956,10 +965,33 @@ static HRESULT sink_writer_initialize_existing_streams(struct sink_writer *write return hr; }
+static HRESULT create_sink_writer(IMFAttributes *attributes, struct sink_writer **out) +{ + struct sink_writer *writer; + + if (!(writer = calloc(1, sizeof(*writer)))) + return E_OUTOFMEMORY; + + writer->IMFSinkWriter_iface.lpVtbl = &sink_writer_vtbl; + writer->events_callback.lpVtbl = &sink_writer_events_callback_vtbl; + writer->refcount = 1; + writer->stats.cb = sizeof(writer->stats); + InitializeCriticalSection(&writer->cs); + + if (attributes) + { + IMFAttributes_GetUnknown(attributes, &MF_SINK_WRITER_ASYNC_CALLBACK, + &IID_IMFSinkWriterCallback, (void **)&writer->callback); + } + + *out = writer; + return S_OK; +} + HRESULT create_sink_writer_from_sink(IMFMediaSink *sink, IMFAttributes *attributes, REFIID riid, void **out) { - struct sink_writer *object; + struct sink_writer *writer; HRESULT hr;
*out = NULL; @@ -967,31 +999,36 @@ HRESULT create_sink_writer_from_sink(IMFMediaSink *sink, IMFAttributes *attribut if (!sink) return E_INVALIDARG;
- if (!(object = calloc(1, sizeof(*object)))) - return E_OUTOFMEMORY; - - object->IMFSinkWriter_iface.lpVtbl = &sink_writer_vtbl; - object->events_callback.lpVtbl = &sink_writer_events_callback_vtbl; - object->refcount = 1; - object->sink = sink; - IMFMediaSink_AddRef(sink); - object->stats.cb = sizeof(object->stats); - InitializeCriticalSection(&object->cs); + if (FAILED(hr = create_sink_writer(attributes, &writer))) + return hr;
- if (attributes) + if (FAILED(hr = sink_writer_initialize_existing_streams(writer, sink))) { - IMFAttributes_GetUnknown(attributes, &MF_SINK_WRITER_ASYNC_CALLBACK, - &IID_IMFSinkWriterCallback, (void **)&object->callback); + IMFSinkWriter_Release(&writer->IMFSinkWriter_iface); + return hr; }
- if (FAILED(hr = sink_writer_initialize_existing_streams(object, sink))) - { - IMFSinkWriter_Release(&object->IMFSinkWriter_iface); + hr = IMFSinkWriter_QueryInterface(&writer->IMFSinkWriter_iface, riid, out); + IMFSinkWriter_Release(&writer->IMFSinkWriter_iface); + return hr; +} + +HRESULT create_sink_writer_from_factory(IMFSinkClassFactory *factory, IMFByteStream *bytestream, + IMFAttributes *attributes, REFIID riid, void **out) +{ + struct sink_writer *writer; + HRESULT hr; + + *out = NULL; + + if (FAILED(hr = create_sink_writer(attributes, &writer))) return hr; - }
- hr = IMFSinkWriter_QueryInterface(&object->IMFSinkWriter_iface, riid, out); - IMFSinkWriter_Release(&object->IMFSinkWriter_iface); + IMFSinkClassFactory_AddRef(writer->factory = factory); + IMFByteStream_AddRef(writer->bytestream = bytestream); + + hr = IMFSinkWriter_QueryInterface(&writer->IMFSinkWriter_iface, riid, out); + IMFSinkWriter_Release(&writer->IMFSinkWriter_iface); return hr; }
@@ -1112,16 +1149,17 @@ HRESULT create_sink_writer_from_url(const WCHAR *url, IMFByteStream *bytestream, }
hr = IMFSinkClassFactory_CreateMediaSink(factory, bytestream, NULL, NULL, &sink); - IMFSinkClassFactory_Release(factory); - IMFByteStream_Release(bytestream); - if (FAILED(hr)) + if (SUCCEEDED(hr)) { - WARN("Failed to create a sink, hr %#lx.\n", hr); - return hr; + hr = create_sink_writer_from_sink(sink, attributes, riid, out); + IMFMediaSink_Release(sink); } - - hr = create_sink_writer_from_sink(sink, attributes, riid, out); - IMFMediaSink_Release(sink); + else + { + hr = create_sink_writer_from_factory(factory, bytestream, attributes, riid, out); + } + IMFSinkClassFactory_Release(factory); + IMFByteStream_Release(bytestream);
return hr; }