From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 146 ++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 75 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 1533693a32f..e402d042972 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -678,6 +678,27 @@ static HRESULT source_reader_allocate_stream_sample(MFT_OUTPUT_STREAM_INFO *info return hr; }
+/* update the output type with additional attributes reported by the decoder such as frame size */ +static HRESULT update_output_type_from_decoder(IMFMediaType *output_type, IMFMediaType *decoded_type) +{ + PROPVARIANT value; + UINT32 count; + HRESULT hr; + GUID key; + + hr = IMFMediaType_GetCount(decoded_type, &count); + while (SUCCEEDED(hr) && count--) + { + PropVariantInit(&value); + hr = IMFMediaType_GetItemByIndex(decoded_type, count, &key, &value); + if (SUCCEEDED(hr) && FAILED(IMFMediaType_GetItem(output_type, &key, NULL))) + hr = IMFMediaType_SetItem(output_type, &key, &value); + PropVariantClear(&value); + } + + return hr; +} + static HRESULT source_reader_pull_transform_samples(struct source_reader *reader, struct media_stream *stream, struct transform_entry *entry); static HRESULT source_reader_push_transform_samples(struct source_reader *reader, struct media_stream *stream, @@ -1756,82 +1777,16 @@ static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader return hr; }
-static HRESULT source_reader_configure_decoder(struct source_reader *reader, DWORD index, const CLSID *clsid, - IMFMediaType *input_type, IMFMediaType *output_type) -{ - IMFMediaTypeHandler *type_handler; - unsigned int block_alignment = 0; - IMFTransform *transform = NULL; - IMFMediaType *type = NULL; - GUID major = { 0 }; - DWORD flags; - HRESULT hr; - int i = 0; - - if (FAILED(hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform))) - { - WARN("Failed to create transform object, hr %#lx.\n", hr); - return hr; - } - - if (FAILED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0))) - { - WARN("Failed to set decoder input type, hr %#lx.\n", hr); - IMFTransform_Release(transform); - return hr; - } - - /* Find the relevant output type. */ - while (IMFTransform_GetOutputAvailableType(transform, 0, i++, &type) == S_OK) - { - flags = 0; - - if (SUCCEEDED(IMFMediaType_IsEqual(type, output_type, &flags))) - { - if (flags & MF_MEDIATYPE_EQUAL_FORMAT_TYPES) - { - if (SUCCEEDED(IMFTransform_SetOutputType(transform, 0, type, 0))) - { - if (SUCCEEDED(source_reader_get_source_type_handler(reader, index, &type_handler))) - { - IMFMediaTypeHandler_SetCurrentMediaType(type_handler, input_type); - IMFMediaTypeHandler_Release(type_handler); - } - - if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)reader->streams[index].current))) - WARN("Failed to copy attributes, hr %#lx.\n", hr); - if (SUCCEEDED(IMFMediaType_GetMajorType(type, &major)) && IsEqualGUID(&major, &MFMediaType_Audio)) - IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment); - IMFMediaType_Release(type); - - if (reader->streams[index].decoder.transform) - IMFTransform_Release(reader->streams[index].decoder.transform); - - reader->streams[index].decoder.transform = transform; - reader->streams[index].decoder.min_buffer_size = block_alignment; - - return S_OK; - } - } - } - - IMFMediaType_Release(type); - } - - WARN("Failed to find suitable decoder output type.\n"); - - IMFTransform_Release(transform); - - return MF_E_TOPO_CODEC_NOT_FOUND; -} - static HRESULT source_reader_create_transform(struct source_reader *reader, DWORD index, IMFMediaType *input_type, IMFMediaType *output_type) { + struct media_stream *stream = &reader->streams[index]; + struct transform_entry *entry = &stream->decoder; MFT_REGISTER_TYPE_INFO in_type, out_type; GUID *classes, category; + IMFTransform *transform; + UINT i, count; HRESULT hr; - UINT count;
if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &in_type.guidMajorType)) || FAILED(hr = IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &in_type.guidSubtype))) @@ -1847,13 +1802,35 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, DWOR else return MF_E_TOPO_CODEC_NOT_FOUND;
+ if (IsEqualGUID(&out_type.guidMajorType, &MFMediaType_Audio)) + IMFMediaType_GetUINT32(output_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, + &entry->min_buffer_size); + if (SUCCEEDED(hr = MFTEnum(category, 0, &in_type, &out_type, NULL, &classes, &count))) { - /* TODO: Should we iterate over all of them? */ - if (count) - hr = source_reader_configure_decoder(reader, index, &classes[0], input_type, output_type); - else - hr = MF_E_TOPO_CODEC_NOT_FOUND; + for (i = 0, hr = MF_E_TOPO_CODEC_NOT_FOUND; i < count; i++) + { + IMFMediaType *media_type; + + if (FAILED(hr = CoCreateInstance(&classes[i], NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform))) + break; + if (SUCCEEDED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0)) + && SUCCEEDED(hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type))) + { + if (SUCCEEDED(hr = update_output_type_from_decoder(output_type, media_type))) + hr = IMFTransform_SetOutputType(transform, 0, output_type, 0); + IMFMediaType_Release(media_type); + + if (SUCCEEDED(hr)) + { + entry->transform = transform; + return S_OK; + } + } + + IMFTransform_Release(transform); + } + CoTaskMemFree(classes); }
@@ -1862,6 +1839,7 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, DWOR
static HRESULT source_reader_create_decoder_for_stream(struct source_reader *reader, DWORD index, IMFMediaType *output_type) { + struct media_stream *stream = &reader->streams[index]; IMFMediaType *input_type; unsigned int i = 0; HRESULT hr; @@ -1870,6 +1848,24 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea { if (SUCCEEDED(hr = source_reader_create_transform(reader, index, input_type, output_type))) { + IMFMediaTypeHandler *type_handler; + + if (SUCCEEDED(source_reader_get_source_type_handler(reader, index, &type_handler))) + { + if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, input_type))) + WARN("Failed to set current input media type, hr %#lx\n", hr); + IMFMediaTypeHandler_Release(type_handler); + } + + if (FAILED(hr = IMFTransform_GetOutputCurrentType(stream->decoder.transform, 0, &output_type))) + WARN("Failed to get decoder output media type, hr %#lx\n", hr); + else + { + if (FAILED(hr = IMFMediaType_CopyAllItems(output_type, (IMFAttributes *)stream->current))) + WARN("Failed to set current output media type, hr %#lx\n", hr); + IMFMediaType_Release(output_type); + } + IMFMediaType_Release(input_type); return S_OK; }