From: Torge Matthies tmatthies@codeweavers.com
--- dlls/winegstreamer/mfplat.c | 99 +++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index e6d9fb9fd2c..44422d1c12c 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -25,6 +25,7 @@ #include "initguid.h" #include "d3d9types.h" #include "mfapi.h" +#include "mferror.h" #include "mmreg.h"
#include "wine/debug.h" @@ -632,22 +633,112 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *sub FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth); }
+static inline int min_int(int a, int b) +{ + return a < b ? a : b; +} + +static inline void write_bits(BYTE *dst, int *bit_pos, UINT32 val, int bits) +{ + BYTE *start_ptr = dst + *bit_pos / 8; + int used = *bit_pos % 8; + *bit_pos += bits; + + do + { + int c = min_int(8 - used, bits); + BYTE m = ((1U << c) - 1); + BYTE v = val >> (bits - c); + *start_ptr = (*start_ptr & ~(m << (8 - c - used))) | ((v & m) << (8 - c - used)); + bits -= c; + start_ptr++; + used = 0; + } while (bits); +} + +static HRESULT generate_aac_user_data(IMFMediaType *type, BOOL raw, BYTE *out, size_t *len) +{ + UINT32 frequency, channels, payload_type, profile_level; + HEAACWAVEFORMAT *user_data; + int bits = 0; + + if (!raw) + { + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &payload_type))) + payload_type = 0; + else if (payload_type > 3) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, &profile_level))) + profile_level = 0x29; + else if (profile_level > 0xFFFF) + return MF_E_INVALIDMEDIATYPE; + + user_data = (HEAACWAVEFORMAT *)(out - FIELD_OFFSET(HEAACWAVEFORMAT, wfInfo.wPayloadType)); + user_data->wfInfo.wPayloadType = payload_type; + user_data->wfInfo.wAudioProfileLevelIndication = profile_level; + out = user_data->pbAudioSpecificConfig; + } + + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &frequency)) || + frequency > 0xFFFFFF) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)) || + channels < 1 || channels > 8 || channels == 7) + return MF_E_INVALIDMEDIATYPE; + + if (channels == 8) + channels = 7; + + write_bits(out, &bits, 2, 5); + switch (frequency) + { + case 96000: write_bits(out, &bits, 0, 4); break; + case 88200: write_bits(out, &bits, 1, 4); break; + case 64000: write_bits(out, &bits, 2, 4); break; + case 48000: write_bits(out, &bits, 3, 4); break; + case 44100: write_bits(out, &bits, 4, 4); break; + case 32000: write_bits(out, &bits, 5, 4); break; + case 24000: write_bits(out, &bits, 6, 4); break; + case 22050: write_bits(out, &bits, 7, 4); break; + case 16000: write_bits(out, &bits, 8, 4); break; + case 12000: write_bits(out, &bits, 9, 4); break; + case 11025: write_bits(out, &bits, 10, 4); break; + case 8000: write_bits(out, &bits, 11, 4); break; + case 7350: write_bits(out, &bits, 12, 4); break; + default: + write_bits(out, &bits, 15, 4); + write_bits(out, &bits, frequency, 24); + break; + } + write_bits(out, &bits, channels, 4); + + if (raw) + *len = (bits + 7) / 8; + else + *len = FIELD_OFFSET(HEAACWAVEFORMAT, pbAudioSpecificConfig[(bits + 7) / 8]) - sizeof(user_data->wfInfo.wfx); + return S_OK; +} + static void mf_media_type_to_wg_format_audio_mpeg4(IMFMediaType *type, const GUID *subtype, struct wg_format *format) { BYTE buffer[sizeof(HEAACWAVEFORMAT) + 64]; HEAACWAVEFORMAT *wfx = (HEAACWAVEFORMAT *)buffer; UINT32 codec_data_size; - BOOL raw_aac; + BOOL raw_aac = IsEqualGUID(subtype, &MFAudioFormat_RAW_AAC); + size_t len;
wfx->wfInfo.wfx.cbSize = sizeof(buffer) - sizeof(wfx->wfInfo.wfx); if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, (BYTE *)(&wfx->wfInfo.wfx + 1), wfx->wfInfo.wfx.cbSize, &codec_data_size))) { - FIXME("Codec data is not set.\n"); - return; + if (FAILED(generate_aac_user_data(type, raw_aac, (BYTE *)(&wfx->wfInfo.wfx + 1), &len))) + { + FIXME("Codec data is not set.\n"); + return; + } + codec_data_size = len; }
- raw_aac = IsEqualGUID(subtype, &MFAudioFormat_RAW_AAC); if (!raw_aac) codec_data_size -= min(codec_data_size, sizeof(HEAACWAVEINFO) - sizeof(WAVEFORMATEX)); if (codec_data_size > sizeof(format->u.audio_mpeg4.codec_data))