Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 77 ++++++++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 67 +++++++++++++++++++++++++++++++++ include/mfapi.h | 7 ++++ 4 files changed, 152 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index dddea4ba1b..6a8bd97557 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -20,6 +20,10 @@
#include "mfplat_private.h"
+#include "initguid.h" +#include "ks.h" +#include "ksmedia.h" + #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat); @@ -1679,3 +1683,76 @@ HRESULT WINAPI MFUnwrapMediaType(IMFMediaType *wrapper, IMFMediaType **ret)
return S_OK; } + +/*********************************************************************** + * MFCreateWaveFormatExFromMFMediaType (mfplat.@) + */ +HRESULT WINAPI MFCreateWaveFormatExFromMFMediaType(IMFMediaType *mediatype, WAVEFORMATEX **ret_format, + UINT32 *size, UINT32 flags) +{ + WAVEFORMATEXTENSIBLE *format_ext = NULL; + WAVEFORMATEX *format; + GUID major, subtype; + UINT32 value; + HRESULT hr; + + TRACE("%p, %p, %p, %#x.\n", mediatype, ret_format, size, flags); + + if (FAILED(hr = IMFMediaType_GetGUID(mediatype, &MF_MT_MAJOR_TYPE, &major))) + return hr; + + if (FAILED(hr = IMFMediaType_GetGUID(mediatype, &MF_MT_SUBTYPE, &subtype))) + return hr; + + if (!IsEqualGUID(&major, &MFMediaType_Audio)) + return E_INVALIDARG; + + if (!IsEqualGUID(&subtype, &MFAudioFormat_PCM)) + { + FIXME("Unsupported audio format %s.\n", debugstr_guid(&subtype)); + return E_NOTIMPL; + } + + /* FIXME: probably WAVE_FORMAT_MPEG/WAVE_FORMAT_MPEGLAYER3 should be handled separately. */ + if (flags == MFWaveFormatExConvertFlag_ForceExtensible) + { + format_ext = CoTaskMemAlloc(sizeof(*format_ext)); + *size = sizeof(*format_ext); + format = (WAVEFORMATEX *)format_ext; + } + else + { + format = CoTaskMemAlloc(sizeof(*format)); + *size = sizeof(*format); + } + + if (!format) + return E_OUTOFMEMORY; + + memset(format, 0, *size); + + format->wFormatTag = format_ext ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM; + + if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_NUM_CHANNELS, &value))) + format->nChannels = value; + IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &format->nSamplesPerSec); + IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &format->nAvgBytesPerSec); + if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &value))) + format->nBlockAlign = value; + if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_BITS_PER_SAMPLE, &value))) + format->wBitsPerSample = value; + if (format_ext) + { + format->cbSize = sizeof(*format_ext) - sizeof(*format); + + if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, &value))) + format_ext->Samples.wSamplesPerBlock = value; + + IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_CHANNEL_MASK, &format_ext->dwChannelMask); + memcpy(&format_ext->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(format_ext->SubFormat)); + } + + *ret_format = format; + + return S_OK; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 1d4035c60e..7823ac0d9e 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -74,7 +74,7 @@ @ stub MFCreateVideoMediaTypeFromSubtype @ stub MFCreateVideoMediaTypeFromVideoInfoHeader2 @ stub MFCreateVideoMediaTypeFromVideoInfoHeader -@ stub MFCreateWaveFormatExFromMFMediaType +@ stdcall MFCreateWaveFormatExFromMFMediaType(ptr ptr ptr long) @ stub MFDeserializeAttributesFromStream @ stub MFDeserializeEvent @ stub MFDeserializeMediaTypeFromStream diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index f62136f4ad..f081d976d7 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -2744,6 +2744,72 @@ static void test_wrapped_media_type(void) IMFMediaType_Release(mediatype2); }
+static void test_MFCreateWaveFormatExFromMFMediaType(void) +{ + WAVEFORMATEXTENSIBLE *format_ext; + IMFMediaType *mediatype; + WAVEFORMATEX *format; + UINT32 size; + HRESULT hr; + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = MFCreateWaveFormatExFromMFMediaType(mediatype, &format, &size, MFWaveFormatExConvertFlag_Normal); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFCreateWaveFormatExFromMFMediaType(mediatype, &format, &size, MFWaveFormatExConvertFlag_Normal); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + /* Audio/PCM */ + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFCreateWaveFormatExFromMFMediaType(mediatype, &format, &size, MFWaveFormatExConvertFlag_Normal); + ok(hr == S_OK, "Failed to create format, hr %#x.\n", hr); + ok(format != NULL, "Expected format structure.\n"); + ok(size == sizeof(*format), "Unexpected size %u.\n", size); + ok(format->wFormatTag == WAVE_FORMAT_PCM, "Unexpected tag.\n"); + ok(format->nChannels == 0, "Unexpected number of channels, %u.\n", format->nChannels); + ok(format->nSamplesPerSec == 0, "Unexpected sample rate, %u.\n", format->nSamplesPerSec); + ok(format->nAvgBytesPerSec == 0, "Unexpected average data rate rate, %u.\n", format->nAvgBytesPerSec); + ok(format->nBlockAlign == 0, "Unexpected alignment, %u.\n", format->nBlockAlign); + ok(format->wBitsPerSample == 0, "Unexpected sample size, %u.\n", format->wBitsPerSample); + ok(format->cbSize == 0, "Unexpected size field, %u.\n", format->cbSize); + CoTaskMemFree(format); + + hr = MFCreateWaveFormatExFromMFMediaType(mediatype, (WAVEFORMATEX **)&format_ext, &size, + MFWaveFormatExConvertFlag_ForceExtensible); + ok(hr == S_OK, "Failed to create format, hr %#x.\n", hr); + ok(format_ext != NULL, "Expected format structure.\n"); + ok(size == sizeof(*format_ext), "Unexpected size %u.\n", size); + ok(format_ext->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "Unexpected tag.\n"); + ok(format_ext->Format.nChannels == 0, "Unexpected number of channels, %u.\n", format_ext->Format.nChannels); + ok(format_ext->Format.nSamplesPerSec == 0, "Unexpected sample rate, %u.\n", format_ext->Format.nSamplesPerSec); + ok(format_ext->Format.nAvgBytesPerSec == 0, "Unexpected average data rate rate, %u.\n", + format_ext->Format.nAvgBytesPerSec); + ok(format_ext->Format.nBlockAlign == 0, "Unexpected alignment, %u.\n", format_ext->Format.nBlockAlign); + ok(format_ext->Format.wBitsPerSample == 0, "Unexpected sample size, %u.\n", format_ext->Format.wBitsPerSample); + ok(format_ext->Format.cbSize == sizeof(*format_ext) - sizeof(format_ext->Format), "Unexpected size field, %u.\n", + format_ext->Format.cbSize); + CoTaskMemFree(format_ext); + + hr = MFCreateWaveFormatExFromMFMediaType(mediatype, &format, &size, MFWaveFormatExConvertFlag_ForceExtensible + 1); + ok(hr == S_OK, "Failed to create format, hr %#x.\n", hr); + ok(size == sizeof(*format), "Unexpected size %u.\n", size); + CoTaskMemFree(format); + + IMFMediaType_Release(mediatype); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -2777,6 +2843,7 @@ START_TEST(mfplat) test_MFCompareFullToPartialMediaType(); test_attributes_serialization(); test_wrapped_media_type(); + test_MFCreateWaveFormatExFromMFMediaType();
CoUninitialize(); } diff --git a/include/mfapi.h b/include/mfapi.h index 775a89f240..cee9d403c4 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -344,6 +344,12 @@ typedef void (CALLBACK *MFPERIODICCALLBACK)(IUnknown *context); #define MF_4096_BYTE_ALIGNMENT 0x00000fff #define MF_8192_BYTE_ALIGNMENT 0x00001fff
+typedef enum _MFWaveFormatExConvertFlags +{ + MFWaveFormatExConvertFlag_Normal = 0, + MFWaveFormatExConvertFlag_ForceExtensible = 1, +} MFWaveFormatExConvertFlags; + HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue); HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue); @@ -363,6 +369,7 @@ HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HR HRESULT WINAPI MFCreateMediaType(IMFMediaType **type); HRESULT WINAPI MFCreateSample(IMFSample **sample); HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer); +HRESULT WINAPI MFCreateWaveFormatExFromMFMediaType(IMFMediaType *type, WAVEFORMATEX **format, UINT32 *size, UINT32 flags); void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type); void WINAPI MFHeapFree(void *ptr); HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size);