diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 0670fbd5181..596f7a5011a 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -278,6 +278,68 @@ static bool amt_from_wg_format_audio_mpeg1(AM_MEDIA_TYPE *mt, const struct wg_fo return false; } +static bool amt_from_wg_format_audio_wma(AM_MEDIA_TYPE *mt, const struct wg_format *format) +{ + DWORD codec_data_len, size; + WAVEFORMATEX *wave_format; + const GUID *subtype; + WORD fmt_tag; + + mt->majortype = MEDIATYPE_Audio; + mt->formattype = FORMAT_WaveFormatEx; + + switch (format->u.audio_wma.version) + { + case 1: + subtype = &MEDIASUBTYPE_MSAUDIO1; + codec_data_len = MSAUDIO1_WFX_EXTRA_BYTES; + fmt_tag = WAVE_FORMAT_MSAUDIO1; + break; + case 2: + subtype = &MEDIASUBTYPE_WMAUDIO2; + codec_data_len = WMAUDIO2_WFX_EXTRA_BYTES; + fmt_tag = WAVE_FORMAT_WMAUDIO2; + break; + case 3: + subtype = &MEDIASUBTYPE_WMAUDIO3; + codec_data_len = WMAUDIO3_WFX_EXTRA_BYTES; + fmt_tag = WAVE_FORMAT_WMAUDIO3; + break; + case 4: + subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS; + codec_data_len = 18; + fmt_tag = WAVE_FORMAT_WMAUDIO_LOSSLESS; + break; + default: + assert(false); + return false; + } + + size = sizeof(WAVEFORMATEX) + codec_data_len; + if (!(wave_format = CoTaskMemAlloc(size))) + return false; + memset(wave_format, 0, size); + + mt->subtype = *subtype; + mt->bFixedSizeSamples = TRUE; + mt->lSampleSize = format->u.audio_wma.block_align; + mt->cbFormat = size; + mt->pbFormat = (BYTE *)wave_format; + wave_format->wFormatTag = fmt_tag; + wave_format->nChannels = format->u.audio_wma.channels; + wave_format->nSamplesPerSec = format->u.audio_wma.rate; + wave_format->nAvgBytesPerSec = format->u.audio_wma.bitrate / 8; + wave_format->nBlockAlign = format->u.audio_wma.block_align; + wave_format->wBitsPerSample = format->u.audio_wma.depth; + wave_format->cbSize = codec_data_len; + + if (format->u.audio_wma.codec_data_len == codec_data_len) + memcpy(wave_format+1, format->u.audio_wma.codec_data, format->u.audio_wma.codec_data_len); + else + FIXME("Unexpected codec_data length; got %u, expected %lu\n", format->u.audio_wma.codec_data_len, codec_data_len); + return true; +} + #define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1)) static unsigned int wg_format_get_max_size_video_raw(enum wg_video_format format, unsigned int width, unsigned int height) @@ -384,8 +446,13 @@ unsigned int wg_format_get_max_size(const struct wg_format *format) } break; - case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_AUDIO_WMA: + /* Estimated max size of a compressed audio frame. + * There's no way to no way to know the real upper bound, + * so let's just use one second of decompressed size and hope it works. */ + return format->u.audio_wma.rate * format->u.audio_wma.channels * format->u.audio_wma.depth / 8; + + case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_VIDEO_H264: case WG_MAJOR_TYPE_VIDEO_WMV: case WG_MAJOR_TYPE_VIDEO_INDEO: @@ -643,7 +710,6 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool switch (format->major_type) { case WG_MAJOR_TYPE_AUDIO_MPEG4: - case WG_MAJOR_TYPE_AUDIO_WMA: case WG_MAJOR_TYPE_VIDEO_H264: case WG_MAJOR_TYPE_VIDEO_INDEO: FIXME("Format %u not implemented!\n", format->major_type); @@ -657,6 +723,9 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool case WG_MAJOR_TYPE_AUDIO_MPEG1: return amt_from_wg_format_audio_mpeg1(mt, format); + case WG_MAJOR_TYPE_AUDIO_WMA: + return amt_from_wg_format_audio_wma(mt, format); + case WG_MAJOR_TYPE_VIDEO: return amt_from_wg_format_video(mt, format, wm); @@ -787,6 +856,55 @@ static bool amt_to_wg_format_audio_mpeg1_layer3(const AM_MEDIA_TYPE *mt, struct return true; } +static bool amt_to_wg_format_audio_wma(const AM_MEDIA_TYPE *mt, struct wg_format *format) +{ + const WAVEFORMATEX *audio_format = (const WAVEFORMATEX *)mt->pbFormat; + + if (!IsEqualGUID(&mt->formattype, &FORMAT_WaveFormatEx)) + { + FIXME("Unknown format type %s.\n", debugstr_guid(&mt->formattype)); + return false; + } + if (mt->cbFormat < sizeof(*audio_format) || !mt->pbFormat) + { + ERR("Unexpected format size %lu.\n", mt->cbFormat); + return false; + } + + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MSAUDIO1)) + format->u.audio_wma.version = 1; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO2)) + format->u.audio_wma.version = 2; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO3)) + format->u.audio_wma.version = 3; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO_LOSSLESS)) + format->u.audio_wma.version = 4; + else + assert(false); + format->major_type = WG_MAJOR_TYPE_AUDIO_WMA; + format->u.audio_wma.bitrate = audio_format->nAvgBytesPerSec * 8; + format->u.audio_wma.rate = audio_format->nSamplesPerSec; + format->u.audio_wma.depth = audio_format->wBitsPerSample; + format->u.audio_wma.channels = audio_format->nChannels; + format->u.audio_wma.block_align = audio_format->nBlockAlign; + + format->u.audio_wma.codec_data_len = 0; + if (format->u.audio_wma.version == 1) + format->u.audio_wma.codec_data_len = 4; + if (format->u.audio_wma.version == 2) + format->u.audio_wma.codec_data_len = 10; + if (format->u.audio_wma.version == 3) + format->u.audio_wma.codec_data_len = 18; + if (format->u.audio_wma.version == 4) + format->u.audio_wma.codec_data_len = 18; + if (mt->cbFormat >= sizeof(WAVEFORMATEX) + format->u.audio_wma.codec_data_len) + memcpy(format->u.audio_wma.codec_data, audio_format+1, format->u.audio_wma.codec_data_len); + else + FIXME("Too small format block, can't copy codec data\n"); + + return true; +} + static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *format) { static const struct @@ -932,6 +1050,11 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format) return amt_to_wg_format_audio_mpeg1(mt, format); if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MP3)) return amt_to_wg_format_audio_mpeg1_layer3(mt, format); + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MSAUDIO1) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO2) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO3) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO_LOSSLESS)) + return amt_to_wg_format_audio_wma(mt, format); return amt_to_wg_format_audio(mt, format); } diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index f40ae37c0ce..1741299e654 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -1455,7 +1455,7 @@ static void check_audio_type(const WM_MEDIA_TYPE *mt) } static void test_stream_media_props(IWMStreamConfig *config, - const GUID *majortype, const GUID *subtype, const GUID *formattype, BOOL todo_subtype) + const GUID *majortype, const GUID *subtype, const GUID *formattype) { char mt_buffer[2000]; WM_MEDIA_TYPE *mt = (WM_MEDIA_TYPE *)mt_buffer; @@ -1484,7 +1484,6 @@ static void test_stream_media_props(IWMStreamConfig *config, ok(size == sizeof(WM_MEDIA_TYPE) + mt->cbFormat, "got %lu.\n", size); ok(IsEqualGUID(&mt->majortype, majortype), "Expected major type %s, got %s.\n", debugstr_guid(majortype), debugstr_guid(&mt->majortype)); - todo_wine_if(todo_subtype) ok(IsEqualGUID(&mt->subtype, subtype), "Expected sub type %s, got %s.\n", debugstr_guid(subtype), debugstr_guid(&mt->subtype)); ok(IsEqualGUID(&mt->formattype, formattype), "Expected format type %s, got %s.\n", @@ -1546,9 +1545,9 @@ static void test_sync_reader_types(void) ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype)); if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) - test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE); + test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx); else - test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE); + test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo); ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %ld.\n", ref); @@ -3425,9 +3424,9 @@ static void test_async_reader_types(void) ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype)); if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) - test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE); + test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx); else - test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE); + test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo); ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %ld.\n", ref);