[PATCH 0/4] MR9633: mfreadwrite: Implement transforms creation for writer.
From: Ziqing Hui <zhui(a)codeweavers.com> --- dlls/mfreadwrite/writer.c | 84 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index e57bf4764ec..2fef43dbee2 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -60,6 +60,7 @@ struct stream IMFStreamSink *stream_sink; IMFTransform *converter, *encoder; MF_SINK_WRITER_STATISTICS stats; + struct sink_writer *writer; struct list queue; /* struct pending_item. */ }; @@ -190,6 +191,82 @@ static HRESULT stream_get_type(struct stream *stream, IMFMediaType **out_type) return hr; } +static HRESULT stream_enumerate_transforms(struct stream *stream, IMFMediaType *input_type, IMFMediaType *output_type, + BOOL use_encoder, IMFActivate ***out_activates, UINT32 *out_count) +{ + UINT32 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER; + BOOL disable_converter = FALSE, use_hardware_transforms = FALSE; + MFT_REGISTER_TYPE_INFO input_type_info, output_type_info; + struct sink_writer *writer = stream->writer; + GUID category; + HRESULT hr; + + /* Check writer attributes. */ + if (writer->attributes) + { + IMFAttributes_GetUINT32(writer->attributes, + &MF_READWRITE_DISABLE_CONVERTERS, (UINT32 *)&disable_converter); + IMFAttributes_GetUINT32(writer->attributes, + &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, (UINT32 *)&use_hardware_transforms); + if (use_hardware_transforms) + flags |= MFT_ENUM_FLAG_HARDWARE; + } + + /* Neither encoder nor converter is allowed, return failure. */ + if (!use_encoder && disable_converter) + return E_FAIL; + + /* Get type infos. */ + 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. */ + *out_count = 0; + if (FAILED(hr = MFTEnumEx(category, flags, + (disable_converter ? &input_type_info : NULL), &output_type_info, out_activates, out_count))) + return hr; + if (!*out_count) + return MF_E_TOPO_CODEC_NOT_FOUND; + + return hr; +} + +static HRESULT stream_create_transforms(struct stream *stream, + IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder) +{ + IMFActivate **activates; + UINT32 count = 0, i; + HRESULT hr; + + /* Enumerate available transforms. */ + if (FAILED(hr = stream_enumerate_transforms(stream, input_type, output_type, use_encoder, &activates, &count))) + return hr; + for (i = 0; i < count; i++) + { + /* TODO: Create transform from activates. */ + hr = E_NOTIMPL; + break; + } + + for (i = 0; i < count; ++i) + IMFActivate_Release(activates[i]); + CoTaskMemFree(activates); + + return hr; +} + static struct stream *sink_writer_get_stream(const struct sink_writer *writer, DWORD index) { if (index >= writer->streams.count) @@ -298,6 +375,7 @@ static HRESULT sink_writer_add_stream(struct sink_writer *writer, IMFStreamSink stream->stream_sink = stream_sink; IMFStreamSink_AddRef(stream_sink); stream->stats.cb = sizeof(stream->stats); + stream->writer = writer; list_init(&stream->queue); writer->streams.next_id = max(writer->streams.next_id, id); @@ -372,9 +450,9 @@ static HRESULT WINAPI sink_writer_SetInputMediaType(IMFSinkWriterEx *iface, DWOR /* Types are not compatible, create transforms. */ if (!(flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA)) { - /* TODO: Try only using converter first, then try again with encoder. */ - FIXME("Not implemented.\n"); - hr = E_NOTIMPL; + /* Try only using converter first, then try again with encoder. */ + if (FAILED(hr = stream_create_transforms(stream, type, stream_type, FALSE))) + hr = stream_create_transforms(stream, type, stream_type, TRUE); } done: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9633
From: Ziqing Hui <zhui(a)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 | 59 ++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/dlls/mfreadwrite/mf_private.h b/dlls/mfreadwrite/mf_private.h index d8b44712b4a..77b55813ac9 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, BOOL advanced); 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 d7653c2dd14..68b90357928 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -714,41 +714,42 @@ 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, BOOL advanced) + +/* 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, BOOL advanced) { 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_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_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); if (!advanced) - media_type_try_copy_attr(media_type, upstream_type, &MF_MT_DEFAULT_STRIDE, &hr); + media_type_try_copy_attr(dst_type, src_type, &MF_MT_DEFAULT_STRIDE, &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; } @@ -2173,7 +2174,7 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, BOOL source_reader_allow_video_processor(reader, &enable_advanced); - if ((SUCCEEDED(hr = update_media_type_from_upstream(output_type, media_type, enable_advanced))) + if ((SUCCEEDED(hr = update_media_type(output_type, media_type, enable_advanced))) && 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))) @@ -2181,7 +2182,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, enable_advanced)) + && SUCCEEDED(hr = update_media_type(output_type, media_type, enable_advanced)) && (enable_advanced || SUCCEEDED(hr = set_default_video_attributes(reader, output_type))) && SUCCEEDED(hr = source_reader_create_transform(reader, FALSE, FALSE, media_type, output_type, &converter))) list_add_tail(&entry->entry, &converter->entry); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9633
From: Ziqing Hui <zhui(a)codeweavers.com> --- dlls/mfreadwrite/tests/mfplat.c | 3 --- dlls/mfreadwrite/writer.c | 44 ++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index a33ebd23194..7c256109ec0 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1772,14 +1772,11 @@ static void test_sink_writer_get_object(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_media_type(input_type, video_input_type_nv12_desc, -1); hr = IMFSinkWriter_SetInputMediaType(writer, 0, input_type, NULL); - todo_wine ok(hr == S_OK, "SetInputMediaType returned %#lx.\n", hr); IMFMediaType_Release(input_type); hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 0, &guid, &transform); - todo_wine ok(hr == S_OK, "GetTransformForStream returned %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&guid, &MFT_CATEGORY_VIDEO_ENCODER), "Unexpected guid %s.\n", debugstr_guid(&guid)); if (hr == S_OK) IMFTransform_Release(transform); diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index 2fef43dbee2..51476b5cde6 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -243,10 +243,46 @@ static HRESULT stream_enumerate_transforms(struct stream *stream, IMFMediaType * return hr; } +static HRESULT stream_set_transform(struct stream *stream, IMFTransform *transform, + IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder) +{ + IMFMediaType *output_current_type; + HRESULT hr; + + /* Set the output type on transform. */ + if (FAILED(hr = IMFTransform_SetOutputType(transform, 0, output_type, 0)) + || FAILED(hr = IMFTransform_GetOutputCurrentType(transform, 0, &output_current_type))) + return hr; + + /* Set the input type on transform. */ + if (FAILED(hr = update_media_type(input_type, output_current_type, FALSE)) + || FAILED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0))) + { + IMFMediaType_Release(output_current_type); + return hr; + } + + /* Set the transform to stream. */ + if (use_encoder) + { + TRACE("Created encoder %p.\n", transform); + stream->encoder = transform; + } + else + { + TRACE("Created converter %p.\n", transform); + stream->converter = transform; + } + + IMFMediaType_Release(output_current_type); + return hr; +} + static HRESULT stream_create_transforms(struct stream *stream, IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder) { IMFActivate **activates; + IMFTransform *transform; UINT32 count = 0, i; HRESULT hr; @@ -255,9 +291,11 @@ static HRESULT stream_create_transforms(struct stream *stream, return hr; for (i = 0; i < count; i++) { - /* TODO: Create transform from activates. */ - hr = E_NOTIMPL; - break; + if (FAILED(hr = IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform))) + continue; + if (SUCCEEDED(hr = stream_set_transform(stream, transform, input_type, output_type, use_encoder))) + break; + IMFTransform_Release(transform); } for (i = 0; i < count; ++i) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9633
From: Ziqing Hui <zhui(a)codeweavers.com> --- dlls/mfreadwrite/tests/mfplat.c | 8 -------- dlls/mfreadwrite/writer.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 7c256109ec0..6743347993d 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1735,29 +1735,23 @@ static void test_sink_writer_get_object(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_media_type(input_type, video_input_type_desc, -1); hr = IMFSinkWriter_SetInputMediaType(writer, 0, input_type, NULL); - todo_wine ok(hr == S_OK, "SetInputMediaType returned %#lx.\n", hr); IMFMediaType_Release(input_type); /* 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); hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 0, &guid, &transform); - todo_wine ok(hr == S_OK, "GetTransformForStream returned %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&guid, &MFT_CATEGORY_VIDEO_PROCESSOR), "Unexpected guid %s.\n", debugstr_guid(&guid)); if (hr == S_OK) IMFTransform_Release(transform); hr = IMFSinkWriterEx_GetTransformForStream(writer_ex, 0, 1, &guid, &transform); - todo_wine ok(hr == S_OK, "GetTransformForStream returned %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&guid, &MFT_CATEGORY_VIDEO_ENCODER), "Unexpected guid %s.\n", debugstr_guid(&guid)); if (hr == S_OK) IMFTransform_Release(transform); @@ -1878,7 +1872,6 @@ static void test_sink_writer_add_stream(void) 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); IMFMediaType_Release(input_type); @@ -1938,7 +1931,6 @@ static void test_sink_writer_sample_process(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_media_type(input_type, video_input_type_desc, -1); hr = IMFSinkWriter_SetInputMediaType(writer, 0, input_type, NULL); - todo_wine ok(hr == S_OK, "SetInputMediaType returned %#lx.\n", hr); IMFMediaType_Release(input_type); diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c index 51476b5cde6..3eea6727e13 100644 --- a/dlls/mfreadwrite/writer.c +++ b/dlls/mfreadwrite/writer.c @@ -281,6 +281,7 @@ static HRESULT stream_set_transform(struct stream *stream, IMFTransform *transfo static HRESULT stream_create_transforms(struct stream *stream, IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder) { + IMFMediaType *encoder_input_type; IMFActivate **activates; IMFTransform *transform; UINT32 count = 0, i; @@ -295,6 +296,22 @@ static HRESULT stream_create_transforms(struct stream *stream, continue; if (SUCCEEDED(hr = stream_set_transform(stream, transform, input_type, output_type, use_encoder))) break; + + /* Failed to use a single encoder, try using an encoder and a converter. */ + if (use_encoder && SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &encoder_input_type))) + { + /* Create the converter with a recursive call. */ + hr = stream_create_transforms(stream, input_type, encoder_input_type, FALSE); + IMFMediaType_Release(encoder_input_type); + if (SUCCEEDED(hr)) + { + /* Converter is already set in the recursive call, set encoder here. */ + stream->encoder = transform; + TRACE("Created encoder %p.", transform); + break; + } + } + IMFTransform_Release(transform); } @@ -486,6 +503,7 @@ static HRESULT WINAPI sink_writer_SetInputMediaType(IMFSinkWriterEx *iface, DWOR } /* Types are not compatible, create transforms. */ + stream_release_transforms(stream); if (!(flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA)) { /* Try only using converter first, then try again with encoder. */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9633
Nikolay Sivov (@nsivov) commented about dlls/mfreadwrite/writer.c:
+ IMFMediaType_Release(output_current_type); + return hr; +} + +static HRESULT stream_create_transforms(struct stream *stream, + IMFMediaType *input_type, IMFMediaType *output_type, BOOL use_encoder) +{ + IMFMediaType *encoder_input_type; + IMFActivate **activates; + IMFTransform *transform; + UINT32 count = 0, i; + HRESULT hr; + + /* Enumerate available transforms. */ + if (FAILED(hr = stream_enumerate_transforms(stream, input_type, output_type, use_encoder, &activates, &count))) + return hr; I don't remember details at this point. Was it decided that both encoder and converter can't be used at the same time? GetTransformForStream() suggests otherwise. If you potentially need both encoder and converter, like in a case of "input -> converter -> encoder -> output", then you'll need start negotiation from output side. Find appropriate encoders and then converter that works for {input type, supported encoder input type} pair, trying each pair.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9633#note_124870
Nikolay Sivov (@nsivov) commented about dlls/mfreadwrite/writer.c:
IMFStreamSink *stream_sink; IMFTransform *converter, *encoder; MF_SINK_WRITER_STATISTICS stats; + struct sink_writer *writer;
We don't need a back-reference like that. User attributes are already referenced, you can use them directly. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9633#note_124871
Nikolay Sivov (@nsivov) commented about dlls/mfreadwrite/writer.c:
+ BOOL use_encoder, IMFActivate ***out_activates, UINT32 *out_count) +{ + UINT32 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER; + BOOL disable_converter = FALSE, use_hardware_transforms = FALSE; + MFT_REGISTER_TYPE_INFO input_type_info, output_type_info; + struct sink_writer *writer = stream->writer; + GUID category; + HRESULT hr; + + /* Check writer attributes. */ + if (writer->attributes) + { + IMFAttributes_GetUINT32(writer->attributes, + &MF_READWRITE_DISABLE_CONVERTERS, (UINT32 *)&disable_converter); + IMFAttributes_GetUINT32(writer->attributes, + &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, (UINT32 *)&use_hardware_transforms); Properties are UINT32, there is no need to use BOOLs.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9633#note_124879
On Fri Dec 5 08:35:05 2025 +0000, Nikolay Sivov wrote:
I don't remember details at this point. Was it decided that both encoder and converter can't be used at the same time? GetTransformForStream() suggests otherwise. If you potentially need both encoder and converter, like in a case of "input -> converter -> encoder -> output", then you'll need start negotiation from output side. Find appropriate encoders and then converter that works for {input type, supported encoder input type} pair, trying each pair. Yes, we can use both encoder and converter the same time. It is implemented in PATCH 4 with a recursive call like what we have in reader.c: source_reader_create_transform().
In fact the whole implementations here is nearly the same as source_reader_create_decoder_for_stream(), but with same code refactor. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9633#note_125253
On Fri Dec 5 08:48:58 2025 +0000, Nikolay Sivov wrote:
Properties are UINT32, there is no need to use BOOLs. OK, I'll change this in next version.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9633#note_125254
participants (3)
-
Nikolay Sivov (@nsivov) -
Ziqing Hui -
Ziqing Hui (@zhui)