From: Ziqing Hui zhui@codeweavers.com
Our tests show that there will be more than one transforms created for encoding. So we use a list here rather than a single encoder transform. --- dlls/mfreadwrite/writer.c | 47 ++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index c708664d2fc..b4d71dfd942 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -55,12 +55,18 @@ struct pending_item void *user_context; };
+struct transform_entry +{ + struct list entry; + IMFTransform *transform; +}; + struct stream { IMFStreamSink *stream_sink; - IMFTransform *encoder; MF_SINK_WRITER_STATISTICS stats; - struct list queue; + struct list queue; /* struct pending_item */ + struct list transforms; /* struct transform_entry */ };
struct sink_writer @@ -166,6 +172,19 @@ static HRESULT create_marker_context(unsigned int marker_type, void *user_contex return S_OK; }
+static void stream_release_transforms(struct stream *stream) +{ + struct transform_entry *entry, *next; + + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &stream->transforms, struct transform_entry, entry) + { + list_remove(&entry->entry); + if (entry->transform) + IMFTransform_Release(entry->transform); + free(entry); + } +} + static void sink_writer_release_pending_item(struct pending_item *item) { list_remove(&item->entry); @@ -233,9 +252,8 @@ static ULONG WINAPI sink_writer_Release(IMFSinkWriter *iface)
if (stream->stream_sink) IMFStreamSink_Release(stream->stream_sink); - if (stream->encoder) - IMFTransform_Release(stream->encoder); sink_writer_drop_pending_items(stream); + stream_release_transforms(stream); } DeleteCriticalSection(&writer->cs); free(writer); @@ -266,6 +284,7 @@ static HRESULT sink_writer_add_stream(struct sink_writer *writer, IMFStreamSink IMFStreamSink_AddRef(stream_sink); stream->stats.cb = sizeof(stream->stats); list_init(&stream->queue); + list_init(&stream->transforms);
writer->streams.next_id = max(writer->streams.next_id, id);
@@ -308,7 +327,6 @@ static HRESULT WINAPI sink_writer_SetInputMediaType(IMFSinkWriter *iface, DWORD IMFAttributes *parameters) { FIXME("%p, %lu, %p, %p.\n", iface, index, type, parameters); - return E_NOTIMPL; }
@@ -350,6 +368,7 @@ static HRESULT WINAPI sink_writer_BeginWriting(IMFSinkWriter *iface) for (i = 0; i < writer->streams.count; ++i) { struct stream *stream = &writer->streams.items[i]; + struct transform_entry *transform;
if (FAILED(hr = IMFStreamSink_BeginGetEvent(stream->stream_sink, &writer->events_callback, (IUnknown *)stream->stream_sink))) @@ -357,8 +376,8 @@ static HRESULT WINAPI sink_writer_BeginWriting(IMFSinkWriter *iface) WARN("Failed to subscribe to events for steam %u, hr %#lx.\n", i, hr); }
- if (stream->encoder) - IMFTransform_ProcessMessage(stream->encoder, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); + LIST_FOR_EACH_ENTRY(transform, &stream->transforms, struct transform_entry, entry) + IMFTransform_ProcessMessage(transform->transform, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); }
if (SUCCEEDED(hr)) @@ -458,6 +477,7 @@ static HRESULT sink_writer_notify_end_of_segment(struct sink_writer *writer, uns
static HRESULT sink_writer_flush(struct sink_writer *writer, unsigned int index) { + struct transform_entry *transform; struct stream *stream;
if (!(stream = sink_writer_get_stream(writer, index))) return MF_E_INVALIDSTREAMNUMBER; @@ -466,8 +486,8 @@ static HRESULT sink_writer_flush(struct sink_writer *writer, unsigned int index)
IMFStreamSink_Flush(stream->stream_sink);
- if (stream->encoder) - IMFTransform_ProcessMessage(stream->encoder, MFT_MESSAGE_COMMAND_FLUSH, 0); + LIST_FOR_EACH_ENTRY(transform, &stream->transforms, struct transform_entry, entry) + IMFTransform_ProcessMessage(transform->transform, MFT_MESSAGE_COMMAND_FLUSH, 0);
return sink_writer_place_marker(writer, stream, MFSTREAMSINK_MARKER_ENDOFSEGMENT, 0, NULL); } @@ -728,6 +748,7 @@ static HRESULT WINAPI sink_writer_GetServiceForStream(IMFSinkWriter *iface, DWOR { struct sink_writer *writer = impl_from_IMFSinkWriter(iface); HRESULT hr = E_UNEXPECTED; + struct list *list_entry; struct stream *stream;
TRACE("%p, %lu, %s, %s, %p.\n", iface, index, debugstr_guid(service), debugstr_guid(riid), object); @@ -738,8 +759,12 @@ static HRESULT WINAPI sink_writer_GetServiceForStream(IMFSinkWriter *iface, DWOR hr = sink_writer_get_service(writer->sink, service, riid, object); else if ((stream = sink_writer_get_stream(writer, index))) { - if (stream->encoder) - hr = sink_writer_get_service(stream->encoder, service, riid, object); + if ((list_entry = list_head(&stream->transforms))) + { + /* FIXME: Which transform should we use here if there are more than one? */ + hr = sink_writer_get_service(LIST_ENTRY(list_entry, struct transform_entry, entry)->transform, + service, riid, object); + } if (FAILED(hr)) hr = sink_writer_get_service(stream->stream_sink, service, riid, object); }