From: Ziqing Hui zhui@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index b6981479a1b..21758cc5aae 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1612,23 +1612,19 @@ static void test_sink_writer_mp4(void)
hr = MFCreateSinkWriterFromURL(NULL, stream, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - IMFSinkWriter_Release(writer); + IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, NULL, NULL, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - IMFSinkWriter_Release(writer); + IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, NULL, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - IMFSinkWriter_Release(writer); + IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, stream, NULL, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - IMFSinkWriter_Release(writer); + IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, stream, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 78 ++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 21758cc5aae..70c058eb29f 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1582,11 +1582,31 @@ static void test_sink_writer_create(void)
static void test_sink_writer_mp4(void) { + static const struct attribute_desc video_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), + ATTR_UINT32(MF_MT_AVG_BITRATE, 193540), + ATTR_UINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive), + {0}, + }; + static const struct attribute_desc video_input_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), + {0}, + }; + IMFMediaType *stream_type, *input_type; WCHAR tmp_file[MAX_PATH]; IMFSinkWriter *writer; IMFByteStream *stream; IMFAttributes *attr; IMFMediaSink *sink; + DWORD index; HRESULT hr;
GetTempPathW(ARRAY_SIZE(tmp_file), tmp_file); @@ -1598,6 +1618,10 @@ static void test_sink_writer_mp4(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = MFCreateTempFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, &stream); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = MFCreateMediaType(&stream_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = MFCreateMediaType(&input_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
/* Test MFCreateSinkWriterFromURL. */ writer = (void *)0xdeadbeef; @@ -1629,7 +1653,43 @@ static void test_sink_writer_mp4(void) hr = MFCreateSinkWriterFromURL(tmp_file, stream, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- /* Test GetServiceForStream. */ + /* BeginWriting fails before calling AddStream. */ + hr = IMFSinkWriter_BeginWriting(writer); + ok(hr == MF_E_INVALIDREQUEST, "BeginWriting returned %#lx.\n", hr); + + /* Test AddStream. */ + init_media_type(stream_type, video_stream_type_desc, -1); + + hr = IMFSinkWriter_AddStream(writer, NULL, NULL); + ok(hr == E_INVALIDARG, "AddStream returned %#lx.\n", hr); + hr = IMFSinkWriter_AddStream(writer, stream_type, NULL); + ok(hr == E_POINTER, "AddStream returned %#lx.\n", hr); + + index = 0xdeadbeef; + hr = IMFSinkWriter_AddStream(writer, NULL, &index); + ok(hr == E_INVALIDARG, "AddStream returned %#lx.\n", hr); + ok(index == 0xdeadbeef, "Unexpected index %lu.\n", index); + + hr = IMFSinkWriter_AddStream(writer, stream_type, &index); + ok(hr == S_OK, "AddStream returned %#lx.\n", hr); + ok(index == 0, "Unexpected index %lu.\n", index); + + /* Test SetInputMediaType. */ + init_media_type(input_type, video_input_type_desc, -1); + hr = IMFSinkWriter_SetInputMediaType(writer, 0xdeadbeef, NULL, NULL); + todo_wine + ok(hr == E_INVALIDARG, "SetInputMediaType returned %#lx.\n", hr); + hr = IMFSinkWriter_SetInputMediaType(writer, 0, NULL, NULL); + todo_wine + ok(hr == E_INVALIDARG, "SetInputMediaType returned %#lx.\n", hr); + hr = IMFSinkWriter_SetInputMediaType(writer, 0xdeadbeef, input_type, NULL); + todo_wine + ok(hr == MF_E_INVALIDSTREAMNUMBER, "SetInputMediaType returned %#lx.\n", hr); + hr = IMFSinkWriter_SetInputMediaType(writer, 0, input_type, NULL); + todo_wine + ok(hr == S_OK, "SetInputMediaType returned %#lx.\n", hr); + + /* Test GetServiceForStream before calling BeginWriting. */ sink = (void *)0xdeadbeef; hr = IMFSinkWriter_GetServiceForStream(writer, MF_SINK_WRITER_MEDIASINK, &GUID_NULL, &IID_IMFMediaSink, (void **)&sink); @@ -1638,8 +1698,24 @@ static void test_sink_writer_mp4(void) todo_wine ok(!sink, "Unexpected pointer %p.\n", sink);
+ /* Test BeginWriting. */ + hr = IMFSinkWriter_BeginWriting(writer); + todo_wine + ok(hr == S_OK, "BeginWriting returned %#lx.\n", hr); + hr = IMFSinkWriter_BeginWriting(writer); + todo_wine + ok(hr == MF_E_INVALIDREQUEST, "BeginWriting returned %#lx.\n", hr); + + /* Test GetServiceForStream after calling BeginWriting. */ + hr = IMFSinkWriter_GetServiceForStream(writer, MF_SINK_WRITER_MEDIASINK, + &GUID_NULL, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "GetServiceForStream returned %#lx.\n", hr); + IMFMediaSink_Release(sink); + DeleteFileW(tmp_file); IMFSinkWriter_Release(writer); + IMFMediaType_Release(input_type); + IMFMediaType_Release(stream_type); IMFByteStream_Release(stream); IMFAttributes_Release(attr); }
From: Ziqing Hui zhui@codeweavers.com
The tests indicate that writer has 2 transforms: a processor and a encoder. --- dlls/mfreadwrite/tests/mfplat.c | 49 +++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 70c058eb29f..6e49976aa4c 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1601,13 +1601,16 @@ static void test_sink_writer_mp4(void) {0}, }; IMFMediaType *stream_type, *input_type; + IMFSinkWriterEx *writer_ex = NULL; WCHAR tmp_file[MAX_PATH]; + IMFTransform *transform; IMFSinkWriter *writer; IMFByteStream *stream; IMFAttributes *attr; IMFMediaSink *sink; DWORD index; HRESULT hr; + GUID guid;
GetTempPathW(ARRAY_SIZE(tmp_file), tmp_file); wcscat(tmp_file, L"tmp.mp4"); @@ -1653,6 +1656,10 @@ static void test_sink_writer_mp4(void) hr = MFCreateSinkWriterFromURL(tmp_file, stream, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ hr = IMFSinkWriter_QueryInterface(writer, &IID_IMFSinkWriterEx, (void **)&writer_ex); + todo_wine + ok(hr == S_OK, "QueryInterface returned %#lx.\n", hr); + /* BeginWriting fails before calling AddStream. */ hr = IMFSinkWriter_BeginWriting(writer); ok(hr == MF_E_INVALIDREQUEST, "BeginWriting returned %#lx.\n", hr); @@ -1674,6 +1681,19 @@ static void test_sink_writer_mp4(void) ok(hr == S_OK, "AddStream returned %#lx.\n", hr); ok(index == 0, "Unexpected index %lu.\n", index);
+ /* Get transform before SetInputMediaType. */ + transform = (void *)0xdeadbeef; + hr = IMFSinkWriter_GetServiceForStream(writer, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + todo_wine + ok(hr == MF_E_UNSUPPORTED_SERVICE, "GetServiceForStream returned %#lx.\n", hr); + ok(!transform, "Unexpected pointer %p.\n", transform); + + if (writer_ex) + { + hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 0, &guid, &transform); + ok(hr == MF_E_INVALIDINDEX, "GetTransformForStream returned %#lx.\n", hr); + } + /* Test SetInputMediaType. */ init_media_type(input_type, video_input_type_desc, -1); hr = IMFSinkWriter_SetInputMediaType(writer, 0xdeadbeef, NULL, NULL); @@ -1689,7 +1709,30 @@ static void test_sink_writer_mp4(void) todo_wine ok(hr == S_OK, "SetInputMediaType returned %#lx.\n", hr);
- /* Test GetServiceForStream before calling BeginWriting. */ + /* Get transform after SetInputMediaType. */ + hr = IMFSinkWriter_GetServiceForStream(writer, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + todo_wine + ok(hr == S_OK, "GetServiceForStream returned %#lx.\n", hr); + if (hr == S_OK) + IMFTransform_Release(transform); + + if (writer_ex) + { + hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 0, &guid, &transform); + ok(hr == S_OK, "GetTransformForStream returned %#lx.\n", hr); + ok(IsEqualGUID(&guid, &MFT_CATEGORY_VIDEO_PROCESSOR), "Unexpected guid %s.\n", debugstr_guid(&guid)); + IMFTransform_Release(transform); + + hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 1, &guid, &transform); + ok(hr == S_OK, "GetTransformForStream returned %#lx.\n", hr); + ok(IsEqualGUID(&guid, &MFT_CATEGORY_VIDEO_ENCODER), "Unexpected guid %s.\n", debugstr_guid(&guid)); + IMFTransform_Release(transform); + + hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 2, &guid, &transform); + ok(hr == MF_E_INVALIDINDEX, "GetTransformForStream returned %#lx.\n", hr); + } + + /* Get media sink before BeginWriting. */ sink = (void *)0xdeadbeef; hr = IMFSinkWriter_GetServiceForStream(writer, MF_SINK_WRITER_MEDIASINK, &GUID_NULL, &IID_IMFMediaSink, (void **)&sink); @@ -1706,12 +1749,14 @@ static void test_sink_writer_mp4(void) todo_wine ok(hr == MF_E_INVALIDREQUEST, "BeginWriting returned %#lx.\n", hr);
- /* Test GetServiceForStream after calling BeginWriting. */ + /* Get media sink after BeginWriting. */ hr = IMFSinkWriter_GetServiceForStream(writer, MF_SINK_WRITER_MEDIASINK, &GUID_NULL, &IID_IMFMediaSink, (void **)&sink); ok(hr == S_OK, "GetServiceForStream returned %#lx.\n", hr); IMFMediaSink_Release(sink);
+ if (writer_ex) + IMFSinkWriterEx_Release(writer_ex); DeleteFileW(tmp_file); IMFSinkWriter_Release(writer); IMFMediaType_Release(input_type);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 72 ++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 6e49976aa4c..ad5506e8dd5 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -162,6 +162,37 @@ static void init_attributes_(const char *file, int line, IMFAttributes *attribut } }
+static IMFSample *create_sample(const BYTE *data, DWORD size) +{ + IMFMediaBuffer *media_buffer; + IMFSample *sample; + BYTE *buffer; + DWORD length; + HRESULT hr; + ULONG ret; + + hr = MFCreateSample(&sample); + ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr); + hr = MFCreateMemoryBuffer(size, &media_buffer); + ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr); + + hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length); + ok(hr == S_OK, "Lock returned %#lx\n", hr); + ok(length == 0, "Unexpected length %lu\n", length); + memcpy(buffer, data, size); + hr = IMFMediaBuffer_Unlock(media_buffer); + ok(hr == S_OK, "Unlock returned %#lx\n", hr); + + hr = IMFMediaBuffer_SetCurrentLength(media_buffer, size); + ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr); + hr = IMFSample_AddBuffer(sample, media_buffer); + ok(hr == S_OK, "AddBuffer returned %#lx\n", hr); + ret = IMFMediaBuffer_Release(media_buffer); + ok(ret == 1, "Release returned %lu\n", ret); + + return sample; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -1602,13 +1633,15 @@ static void test_sink_writer_mp4(void) }; IMFMediaType *stream_type, *input_type; IMFSinkWriterEx *writer_ex = NULL; + DWORD rgb32_data[96 * 96]; WCHAR tmp_file[MAX_PATH]; IMFTransform *transform; IMFSinkWriter *writer; IMFByteStream *stream; + DWORD index, i, size; IMFAttributes *attr; IMFMediaSink *sink; - DWORD index; + HANDLE file; HRESULT hr; GUID guid;
@@ -1641,10 +1674,6 @@ static void test_sink_writer_mp4(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFSinkWriter_Release(writer);
- hr = MFCreateSinkWriterFromURL(tmp_file, NULL, NULL, &writer); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - IMFSinkWriter_Release(writer); - hr = MFCreateSinkWriterFromURL(tmp_file, NULL, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFSinkWriter_Release(writer); @@ -1655,6 +1684,10 @@ static void test_sink_writer_mp4(void)
hr = MFCreateSinkWriterFromURL(tmp_file, stream, attr, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFSinkWriter_Release(writer); + + hr = MFCreateSinkWriterFromURL(tmp_file, NULL, NULL, &writer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFSinkWriter_QueryInterface(writer, &IID_IMFSinkWriterEx, (void **)&writer_ex); todo_wine @@ -1755,6 +1788,35 @@ static void test_sink_writer_mp4(void) ok(hr == S_OK, "GetServiceForStream returned %#lx.\n", hr); IMFMediaSink_Release(sink);
+ /* WriteSample. */ + for (i = 0; i < ARRAY_SIZE(rgb32_data); ++i) + rgb32_data[i] = 0x0000ff00; + for (i = 0; i < 30; ++i) + { + IMFSample *sample = create_sample((const BYTE *)rgb32_data, sizeof(rgb32_data)); + hr = IMFSample_SetSampleTime(sample, 333333 * i); + ok(hr == S_OK, "SetSampleTime returned %#lx.\n", hr); + hr = IMFSample_SetSampleDuration(sample, 333333); + ok(hr == S_OK, "SetSampleDuration returned %#lx.\n", hr); + hr = IMFSinkWriter_WriteSample(writer, 0, sample); + todo_wine + ok(hr == S_OK, "WriteSample returned %#lx.\n", hr); + IMFSample_Release(sample); + } + + /* Finalize. */ + hr = IMFSinkWriter_Finalize(writer); + todo_wine + ok(hr == S_OK, "Finalize returned %#lx.\n", hr); + + /* Check the output file. */ + file = CreateFileW(tmp_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + todo_wine + ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed.\n"); + size = GetFileSize(file, NULL); + todo_wine + ok(size != INVALID_FILE_SIZE && size > 0x400, "Unexpected file size %#lx.\n", size); + if (writer_ex) IMFSinkWriterEx_Release(writer_ex); DeleteFileW(tmp_file);
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); }
From: Ziqing Hui zhui@codeweavers.com
We will use this in writer.c, so make it non-static. For writer, the source type is from downstream, so rename this. --- dlls/mfreadwrite/mf_private.h | 1 + dlls/mfreadwrite/reader.c | 58 +++++++++++++++++------------------ 2 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/dlls/mfreadwrite/mf_private.h b/dlls/mfreadwrite/mf_private.h index d8b44712b4a..92e0e20f67d 100644 --- a/dlls/mfreadwrite/mf_private.h +++ b/dlls/mfreadwrite/mf_private.h @@ -22,6 +22,7 @@ extern HRESULT create_sink_writer_from_url(const WCHAR *url, IMFByteStream *stre IMFAttributes *attributes, REFIID riid, void **out); extern HRESULT create_sink_writer_from_sink(IMFMediaSink *sink, IMFAttributes *attributes, REFIID riid, void **out); +extern HRESULT update_media_type(IMFMediaType *dst_type, IMFMediaType *src_type);
static inline BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) { diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 4d223f1de6e..690569f4138 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -714,39 +714,39 @@ static void media_type_try_copy_attr(IMFMediaType *dst, IMFMediaType *src, const PropVariantClear(&value); }
-/* update a media type with additional attributes reported by upstream element */ -/* also present in mf/topology_loader.c pipeline */ -static HRESULT update_media_type_from_upstream(IMFMediaType *media_type, IMFMediaType *upstream_type) +/* Update a media type with additional attributes reported by another media type, */ +/* also present as update_media_type_from_upstream in mf/topology_loader.c pipeline. */ +HRESULT update_media_type(IMFMediaType *dst_type, IMFMediaType *src_type) { HRESULT hr = S_OK;
/* propagate common video attributes */ - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_FRAME_SIZE, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_FRAME_RATE, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_DEFAULT_STRIDE, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_VIDEO_ROTATION, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_FIXED_SIZE_SAMPLES, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_PIXEL_ASPECT_RATIO, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, &hr); - - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_VIDEO_CHROMA_SITING, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_INTERLACE_MODE, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_TRANSFER_FUNCTION, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_VIDEO_PRIMARIES, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_YUV_MATRIX, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_VIDEO_LIGHTING, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_VIDEO_NOMINAL_RANGE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_FRAME_SIZE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_FRAME_RATE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_DEFAULT_STRIDE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_VIDEO_ROTATION, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_FIXED_SIZE_SAMPLES, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_PIXEL_ASPECT_RATIO, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, &hr); + + media_type_try_copy_attr(dst_type, src_type, &MF_MT_VIDEO_CHROMA_SITING, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_INTERLACE_MODE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_TRANSFER_FUNCTION, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_VIDEO_PRIMARIES, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_YUV_MATRIX, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_VIDEO_LIGHTING, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_VIDEO_NOMINAL_RANGE, &hr);
/* propagate common audio attributes */ - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_NUM_CHANNELS, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_CHANNEL_MASK, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_SAMPLES_PER_BLOCK, &hr); - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_NUM_CHANNELS, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_CHANNEL_MASK, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_SAMPLES_PER_BLOCK, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, &hr);
return hr; } @@ -2120,7 +2120,7 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, BOOL if (SUCCEEDED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0)) && SUCCEEDED(hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type))) { - if (SUCCEEDED(hr = update_media_type_from_upstream(output_type, media_type)) + if (SUCCEEDED(hr = update_media_type(output_type, media_type)) && FAILED(hr = IMFTransform_SetOutputType(transform, 0, output_type, 0)) && FAILED(hr = set_matching_transform_output_type(transform, output_type)) && allow_processor && SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type))) @@ -2128,7 +2128,7 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, BOOL struct transform_entry *converter;
if (SUCCEEDED(hr = IMFTransform_SetOutputType(transform, 0, media_type, 0)) - && SUCCEEDED(hr = update_media_type_from_upstream(output_type, media_type)) + && SUCCEEDED(hr = update_media_type(output_type, media_type)) && SUCCEEDED(hr = source_reader_create_transform(reader, FALSE, FALSE, media_type, output_type, &converter))) list_add_tail(&entry->entry, &converter->entry);
From: Ziqing Hui zhui@codeweavers.com
We'll implement create_transform_entry later. --- dlls/mfreadwrite/writer.c | 61 ++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-)
diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index b4d71dfd942..48ff27f14d1 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -172,6 +172,12 @@ static HRESULT create_marker_context(unsigned int marker_type, void *user_contex return S_OK; }
+static HRESULT create_transform_entry(IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder, + struct transform_entry **out) +{ + return E_NOTIMPL; +} + static void stream_release_transforms(struct stream *stream) { struct transform_entry *entry, *next; @@ -185,6 +191,13 @@ static void stream_release_transforms(struct stream *stream) } }
+static struct stream *sink_writer_get_stream(const struct sink_writer *writer, DWORD index) +{ + if (index >= writer->streams.count) + return NULL; + return &writer->streams.items[index]; +} + static void sink_writer_release_pending_item(struct pending_item *item) { list_remove(&item->entry); @@ -326,8 +339,46 @@ static HRESULT WINAPI sink_writer_AddStream(IMFSinkWriter *iface, IMFMediaType * static HRESULT WINAPI sink_writer_SetInputMediaType(IMFSinkWriter *iface, DWORD index, IMFMediaType *type, IMFAttributes *parameters) { - FIXME("%p, %lu, %p, %p.\n", iface, index, type, parameters); - return E_NOTIMPL; + struct sink_writer *writer = impl_from_IMFSinkWriter(iface); + IMFMediaTypeHandler *type_handler = NULL; + struct transform_entry *entry = NULL; + IMFMediaType *stream_type = NULL; + struct stream *stream; + HRESULT hr; + + TRACE("%p, %lu, %p, %p.\n", iface, index, type, parameters); + + if (!type) + return E_INVALIDARG; + + EnterCriticalSection(&writer->cs); + + if (!(stream = sink_writer_get_stream(writer, index))) + { + LeaveCriticalSection(&writer->cs); + return MF_E_INVALIDSTREAMNUMBER; + } + + /* Get stream type from stream sink. */ + if (SUCCEEDED(hr = IMFStreamSink_GetMediaTypeHandler(stream->stream_sink, &type_handler)) + && SUCCEEDED((hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &stream_type)))) + { + /* Create transforms for encoding. + * Try converter first, then try again with encoder. */ + if (SUCCEEDED(hr = create_transform_entry(type, stream_type, FALSE, &entry)) + || SUCCEEDED(hr = create_transform_entry(type, stream_type, TRUE, &entry))) + { + if (!list_empty(&stream->transforms)) + stream_release_transforms(stream); + list_add_tail(&stream->transforms, &entry->entry); + } + + IMFMediaType_Release(stream_type); + IMFMediaTypeHandler_Release(type_handler); + } + + LeaveCriticalSection(&writer->cs); + return hr; }
static HRESULT sink_writer_set_presentation_clock(struct sink_writer *writer) @@ -391,12 +442,6 @@ static HRESULT WINAPI sink_writer_BeginWriting(IMFSinkWriter *iface) return hr; }
-static struct stream * sink_writer_get_stream(const struct sink_writer *writer, DWORD index) -{ - if (index >= writer->streams.count) return NULL; - return &writer->streams.items[index]; -} - static HRESULT sink_writer_get_buffer_length(IMFSample *sample, LONGLONG *timestamp, DWORD *length) { IMFMediaBuffer *buffer;
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mfreadwrite/writer.c | 138 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index 48ff27f14d1..b901a9b026c 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -172,10 +172,142 @@ static HRESULT create_marker_context(unsigned int marker_type, void *user_contex return S_OK; }
+static HRESULT enum_transforms(IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder, + IMFActivate ***activates, UINT32 *count) +{ + MFT_REGISTER_TYPE_INFO input_type_info, output_type_info; + GUID category; + HRESULT hr; + + /* Get type infos. */ + if (input_type) + { + if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &input_type_info.guidMajorType)) + || FAILED(hr = IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &input_type_info.guidSubtype))) + return hr; + } + if (FAILED(hr = IMFMediaType_GetMajorType(output_type, &output_type_info.guidMajorType)) + || FAILED(hr = IMFMediaType_GetGUID(output_type, &MF_MT_SUBTYPE, &output_type_info.guidSubtype))) + return hr; + + /* Set category according to major type. */ + if (IsEqualGUID(&output_type_info.guidMajorType, &MFMediaType_Video)) + category = use_encoder ? MFT_CATEGORY_VIDEO_ENCODER : MFT_CATEGORY_VIDEO_PROCESSOR; + else if (IsEqualGUID(&output_type_info.guidMajorType, &MFMediaType_Audio)) + category = use_encoder ? MFT_CATEGORY_AUDIO_ENCODER : MFT_CATEGORY_AUDIO_EFFECT; + else + return MF_E_TOPO_CODEC_NOT_FOUND; + + /* Enumerate available transforms. */ + *count = 0; + if (FAILED(hr = MFTEnumEx(category, 0, (input_type ? NULL : &input_type_info), &output_type_info, + activates, count))) + return hr; + if (!*count) + return MF_E_TOPO_CODEC_NOT_FOUND; + + return hr; +} + +static void transform_entry_release(struct transform_entry *entry) +{ + if (entry->transform) + IMFTransform_Release(entry->transform); + free(entry); +} + +static HRESULT create_transform_entry_from_activate(IMFActivate *activate, + IMFMediaType *input_type, IMFMediaType *output_type, struct transform_entry **out) +{ + IMFMediaType *output_current_type = NULL; + struct transform_entry *entry = NULL; + IMFTransform *transform = NULL; + HRESULT hr; + + /* Create object. */ + if (!(entry = calloc(1, sizeof(*entry)))) + return E_OUTOFMEMORY; + + /* Create transform. */ + if (FAILED(hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)&transform))) + goto done; + + /* Set output type on transform. */ + if (FAILED(hr = IMFTransform_SetOutputType(transform, 0, output_type, 0)) + || FAILED(hr = IMFTransform_GetOutputCurrentType(transform, 0, &output_current_type))) + goto done; + + /* Set input type on transform. */ + if (input_type) + { + if (FAILED(hr = update_media_type(input_type, output_current_type))) + goto done; + if (FAILED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0))) + goto done; + } + + list_init(&entry->entry); + IMFTransform_AddRef((entry->transform = transform)); + *out = entry; + + TRACE("Created transform entry %p, transform %p.\n", entry, entry->transform); + +done: + if (output_current_type) + IMFMediaType_Release(output_current_type); + if (transform) + IMFTransform_Release(transform); + if (FAILED(hr)) + free(entry); + return hr; +} + static HRESULT create_transform_entry(IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder, struct transform_entry **out) { - return E_NOTIMPL; + struct transform_entry *entry = NULL, *converter = NULL; + IMFMediaType *encoder_input_type; + IMFActivate **activates; + UINT32 count = 0, i; + HRESULT hr; + + if (FAILED(hr = enum_transforms(input_type, output_type, use_encoder, &activates, &count))) + return hr; + + for (i = 0; i < count; i++) + { + if (SUCCEEDED(hr = create_transform_entry_from_activate(activates[i], input_type, output_type, &entry))) + { + TRACE("Create transform entry %p, transform %p.", entry, entry->transform); + *out = entry; + break; + } + + /* Failed to use a single encoder, try using an encoder and a converter. */ + if (use_encoder && SUCCEEDED(hr = create_transform_entry_from_activate(activates[i], NULL, output_type, &entry))) + { + if (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(entry->transform, 0, 0, &encoder_input_type))) + { + hr = create_transform_entry(input_type, encoder_input_type, FALSE, &converter); + IMFMediaType_Release(encoder_input_type); + if (SUCCEEDED(hr)) + { + list_add_head(&entry->entry, &converter->entry); + TRACE("Create converter entry %p, transform %p; encoder entry %p, transform %p.", + converter, converter->transform, entry, entry->transform); + *out = converter; + break; + } + } + transform_entry_release(entry); + } + } + + for (i = 0; i < count; ++i) + IMFActivate_Release(activates[i]); + CoTaskMemFree(activates); + + return hr; }
static void stream_release_transforms(struct stream *stream) @@ -185,9 +317,7 @@ static void stream_release_transforms(struct stream *stream) 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); + transform_entry_release(entry); } }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150943
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
mfreadwrite: mfplat.c:1694: Test failed: QueryInterface returned 0x80004002. mfplat.c:1743: Test failed: SetInputMediaType returned 0xc00d36b4. mfplat.c:1748: Test failed: GetServiceForStream returned 0xc00d36ba. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1810: Test failed: Finalize returned 0xc00d4a44. mfplat.c:1815: Test failed: CreateFileW failed. mfplat.c:1818: Test failed: Unexpected file size 0xffffffff.
=== w7u_adm (32 bit report) ===
mfreadwrite: mfplat.c:1694: Test failed: QueryInterface returned 0x80004002. mfplat.c:1743: Test failed: SetInputMediaType returned 0xc00d36b4. mfplat.c:1748: Test failed: GetServiceForStream returned 0xc00d36ba. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1810: Test failed: Finalize returned 0x8000ffff. mfplat.c:1815: Test failed: CreateFileW failed. mfplat.c:1818: Test failed: Unexpected file size 0xffffffff.
=== w7u_el (32 bit report) ===
mfreadwrite: mfplat.c:1694: Test failed: QueryInterface returned 0x80004002. mfplat.c:1743: Test failed: SetInputMediaType returned 0xc00d36b4. mfplat.c:1748: Test failed: GetServiceForStream returned 0xc00d36ba. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1810: Test failed: Finalize returned 0xc00d4a44. mfplat.c:1815: Test failed: CreateFileW failed. mfplat.c:1818: Test failed: Unexpected file size 0xffffffff.
=== w7pro64 (64 bit report) ===
mfreadwrite: mfplat.c:1694: Test failed: QueryInterface returned 0x80004002. mfplat.c:1743: Test failed: SetInputMediaType returned 0xc00d36b4. mfplat.c:1748: Test failed: GetServiceForStream returned 0xc00d36ba. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1803: Test failed: WriteSample returned 0x8000ffff. mfplat.c:1810: Test failed: Finalize returned 0x8000ffff. mfplat.c:1815: Test failed: CreateFileW failed. mfplat.c:1818: Test failed: Unexpected file size 0xffffffff.
=== debian11 (32 bit report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit ar:MA report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit de report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit fr report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit he:IL report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit hi:IN report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit ja:JP report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11 (32 bit zh:CN report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11b (32 bit WoW report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
=== debian11b (64 bit WoW report) ===
mfreadwrite: mfplat.c:1734: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1737: Test succeeded inside todo block: SetInputMediaType returned 0x80070057. mfplat.c:1740: Test succeeded inside todo block: SetInputMediaType returned 0xc00d36b3. mfplat.c:1743: Test succeeded inside todo block: SetInputMediaType returned 0. mfplat.c:1748: Test succeeded inside todo block: GetServiceForStream returned 0.
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000E100E6, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
Nikolay Sivov (@nsivov) commented about dlls/mfreadwrite/writer.c:
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);
}
We should use encoder.
Nikolay Sivov (@nsivov) commented about dlls/mfreadwrite/writer.c:
};
+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 */
Array seems to be a better fit. Is it possible to have more than 2 transforms?
Test changes here only touch MP4 format case, that should be reflected in commits messages.
On Tue Jan 21 23:55:38 2025 +0000, Nikolay Sivov wrote:
Array seems to be a better fit. Is it possible to have more than 2 transforms?
I didn't met any cases that have more than 2 transforms. If that's true, it would be better to use array here?
On Wed Jan 22 00:47:24 2025 +0000, Nikolay Sivov wrote:
Test changes here only touch MP4 format case, that should be reflected in commits messages.
OK, I'll change this in the tests MR !7125
On Wed Jan 22 00:47:24 2025 +0000, Ziqing Hui wrote:
OK, I'll change this in the tests MR !7125
Changed in !7125.
On Wed Jan 22 00:46:58 2025 +0000, Ziqing Hui wrote:
I didn't met any cases that have more than 2 transforms. If that's true, it would be better to use array here?
If it's always 1 or 2, we don't need to allocate anything dynamically.