Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 71 ++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 97 ++++++++++++++++++++++++++++++++++++++ include/mfapi.h | 1 + 4 files changed, 170 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 196d803722..b832e00bdd 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -2089,3 +2089,74 @@ HRESULT WINAPI MFCreateWaveFormatExFromMFMediaType(IMFMediaType *mediatype, WAVE
return S_OK; } + +static void mediatype_set_uint32(IMFMediaType *mediatype, const GUID *attr, unsigned int value, HRESULT *hr) +{ + if (SUCCEEDED(*hr)) + *hr = IMFMediaType_SetUINT32(mediatype, attr, value); +} + +static void mediatype_set_guid(IMFMediaType *mediatype, const GUID *attr, const GUID *value, HRESULT *hr) +{ + if (SUCCEEDED(*hr)) + *hr = IMFMediaType_SetGUID(mediatype, attr, value); +} + +/*********************************************************************** + * MFInitMediaTypeFromWaveFormatEx (mfplat.@) + */ +HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WAVEFORMATEX *format, UINT32 size) +{ + GUID subtype; + HRESULT hr; + + TRACE("%p, %p, %u.\n", mediatype, format, size); + + if (!mediatype || !format) + return E_POINTER; + + if (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + FIXME("WAVE_FORMAT_EXTENSIBLE is not supported.\n"); + return E_NOTIMPL; + } + else + { + hr = IMFMediaType_DeleteAllItems(mediatype); + + mediatype_set_guid(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio, &hr); + + memcpy(&subtype, &MFAudioFormat_Base, sizeof(subtype)); + subtype.Data1 = format->wFormatTag; + mediatype_set_guid(mediatype, &MF_MT_SUBTYPE, &subtype, &hr); + + if (format->nChannels) + mediatype_set_uint32(mediatype, &MF_MT_AUDIO_NUM_CHANNELS, format->nChannels, &hr); + + if (format->nSamplesPerSec) + mediatype_set_uint32(mediatype, &MF_MT_AUDIO_SAMPLES_PER_SECOND, format->nSamplesPerSec, &hr); + + if (format->nAvgBytesPerSec) + mediatype_set_uint32(mediatype, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, format->nAvgBytesPerSec, &hr); + + if (format->nBlockAlign) + mediatype_set_uint32(mediatype, &MF_MT_AUDIO_BLOCK_ALIGNMENT, format->nBlockAlign, &hr); + + if (format->wBitsPerSample) + mediatype_set_uint32(mediatype, &MF_MT_AUDIO_BITS_PER_SAMPLE, format->wBitsPerSample, &hr); + + mediatype_set_uint32(mediatype, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1, &hr); + } + + switch (subtype.Data1) + { + case WAVE_FORMAT_PCM: + case WAVE_FORMAT_IEEE_FLOAT: + mediatype_set_uint32(mediatype, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1, &hr); + break; + default: + FIXME("Unhandled type %d.\n", subtype.Data1); + } + + return hr; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 25e5f62f21..a1833312fc 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -121,7 +121,7 @@ @ stub MFInitMediaTypeFromMPEG2VideoInfo @ stub MFInitMediaTypeFromVideoInfoHeader2 @ stub MFInitMediaTypeFromVideoInfoHeader -@ stub MFInitMediaTypeFromWaveFormatEx +@ stdcall MFInitMediaTypeFromWaveFormatEx(ptr ptr long) @ stub MFInitVideoFormat @ stub MFInitVideoFormat_RGB @ stdcall MFInvokeCallback(ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 78d73b7580..d9fbff570f 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -5084,6 +5084,102 @@ static void test_MFCreateMediaBufferFromMediaType(void) IMFMediaType_Release(media_type); }
+static void validate_media_type(IMFMediaType *mediatype, const WAVEFORMATEX *format) +{ + GUID guid, subtype; + UINT32 value; + HRESULT hr; + + hr = IMFMediaType_GetMajorType(mediatype, &guid); + ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid)); + + hr = IMFMediaType_GetGUID(mediatype, &MF_MT_SUBTYPE, &guid); + ok(hr == S_OK, "Failed to get subtype, hr %#x.\n", hr); + + if (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + } + else + { + memcpy(&subtype, &MFAudioFormat_Base, sizeof(subtype)); + subtype.Data1 = format->wFormatTag; + ok(IsEqualGUID(&guid, &subtype), "Unexpected subtype %s.\n", wine_dbgstr_guid(&guid)); + + if (format->nChannels) + { + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_NUM_CHANNELS, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value == format->nChannels, "Unexpected NUM_CHANNELS %u.\n", value); + } + + if (format->nSamplesPerSec) + { + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value == format->nSamplesPerSec, "Unexpected SAMPLES_PER_SECOND %u.\n", value); + } + + if (format->nAvgBytesPerSec) + { + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value == format->nAvgBytesPerSec, "Unexpected AVG_BYTES_PER_SECOND %u.\n", value); + } + + if (format->nBlockAlign) + { + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value == format->nBlockAlign, "Unexpected BLOCK_ALIGNMENT %u.\n", value); + } + + if (format->wBitsPerSample) + { + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_BITS_PER_SAMPLE, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value == format->wBitsPerSample, "Unexpected BITS_PER_SAMPLE %u.\n", value); + } + + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value, "Unexpected value.\n"); + } + + /* Only set for uncompressed formats. */ + if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_ALL_SAMPLES_INDEPENDENT, &value))) + ok(value, "Unexpected ALL_SAMPLES_INDEPENDENT value.\n"); +} + +static void test_MFInitMediaTypeFromWaveFormatEx(void) +{ + static const WAVEFORMATEX waveformatex_tests[] = + { + { WAVE_FORMAT_PCM, 2, 44100, 0, 2, 8 }, + { WAVE_FORMAT_PCM, 2, 44100, 1, 2, 8 }, + { WAVE_FORMAT_PCM, 0, 44100, 0, 0, 0 }, + { WAVE_FORMAT_PCM, 0, 0, 0, 0, 0 }, + { 1234, 0, 0, 0, 0, 0 }, + { WAVE_FORMAT_MPEGLAYER3, 0, 0, 0, 0, 0 }, + }; + IMFMediaType *mediatype; + unsigned int i; + HRESULT hr; + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create mediatype, hr %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(waveformatex_tests); ++i) + { + hr = MFInitMediaTypeFromWaveFormatEx(mediatype, &waveformatex_tests[i], sizeof(waveformatex_tests[i])); + ok(hr == S_OK, "Failed to initialize media type, hr %#x.\n", hr); + + validate_media_type(mediatype, &waveformatex_tests[i]); + } + + IMFMediaType_Release(mediatype); +} + START_TEST(mfplat) { char **argv; @@ -5138,6 +5234,7 @@ START_TEST(mfplat) test_MFGetStrideForBitmapInfoHeader(); test_MFCreate2DMediaBuffer(); test_MFCreateMediaBufferFromMediaType(); + test_MFInitMediaTypeFromWaveFormatEx();
CoUninitialize(); } diff --git a/include/mfapi.h b/include/mfapi.h index b9383630ab..c8ae665b10 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -532,6 +532,7 @@ HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_IN const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *pcount); HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 *buffer, UINT size); +HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WAVEFORMATEX *format, UINT32 size); HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result); HRESULT WINAPI MFLockPlatform(void); HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state);