枚举AAC音频格式返回不完整WAVEFORMATEX结果的解决方法
解决Media Foundation枚举AAC格式时WAVEFORMATEX扩展信息缺失的问题
核心问题原因
Media Foundation对AAC类型的IMFMediaType转换为AM_MEDIA_TYPE时,不会自动填充完整的HEAACWAVEINFO/HEAACWAVEFORMAT扩展结构体,仅返回基础WAVEFORMATEX部分,导致后续MFInitMediaTypeFromWaveFormatEx因参数不全失败。
解决方案
方案1:直接使用枚举得到的IMFMediaType(推荐)
无需将IMFMediaType转换为AM_MEDIA_TYPE再转回,直接将枚举到的IMFMediaType传递给IMFSinkWriter::AddStream或SetOutputType,跳过WAVEFORMATEX的转换环节:
// 枚举得到的pMediaType是IMFMediaType指针 DWORD streamIndex; hr = pSinkWriter->AddStream(pMediaType, &streamIndex); // 后续直接使用streamIndex进行编码操作
这种方式完全利用Media Foundation的原生类型,避免转换过程中的信息丢失,是最可靠的做法。
方案2:手动从IMFMediaType提取参数构建完整的AAC扩展结构体
如果因遗留代码必须使用WAVEFORMATEX扩展结构体,可从IMFMediaType中提取关键属性,手动初始化HEAACWAVEINFO或HEAACWAVEFORMAT:
- 从
IMFMediaType获取AAC核心属性:
UINT32 aacProfile = 0; UINT32 samplesPerFrame = 0; UINT32 bitrate = 0; UINT32 channels = 0; UINT32 sampleRate = 0; // 获取AAC profile(比如MF_AAC_PROFILE_HE_V2、MF_AAC_PROFILE_LC等) pMediaType->GetUINT32(MF_MT_AAC_PROFILE, &aacProfile); // 获取每帧采样数 pMediaType->GetUINT32(MF_MT_AAC_SAMPLES_PER_FRAME, &samplesPerFrame); // 获取比特率 pMediaType->GetUINT32(MF_MT_AAC_BITRATE, &bitrate); // 获取通道数 pMediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &channels); // 获取采样率 pMediaType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &sampleRate);
- 初始化HEAACWAVEINFO结构体:
HEAACWAVEINFO heAACInfo = {0}; WAVEFORMATEX* pWfx = &heAACInfo.wfx; // 填充基础WAVEFORMATEX部分 pWfx->wFormatTag = (aacProfile == MF_AAC_PROFILE_HE_V2 || aacProfile == MF_AAC_PROFILE_HE) ? WAVE_FORMAT_MPEG_HEAAC : WAVE_FORMAT_MPEG_AAC; pWfx->nChannels = channels; pWfx->nSamplesPerSec = sampleRate; pWfx->wBitsPerSample = 16; // AAC通常对应16位PCM输入 pWfx->nBlockAlign = pWfx->nChannels * (pWfx->wBitsPerSample / 8); pWfx->nAvgBytesPerSec = pWfx->nSamplesPerSec * pWfx->nBlockAlign; pWfx->cbSize = sizeof(HEAACWAVEINFO) - sizeof(WAVEFORMATEX); // 填充HEAACWAVEINFO扩展部分 heAACInfo.wPayloadType = 0; // 对于AAC通常设为0 heAACInfo.dwSampleRate = sampleRate; heAACInfo.dwCodecDelay = 0; // 可根据编码器实际情况调整,或从IMFMediaType获取MF_MT_DELAY属性 heAACInfo.dwPCMFrameSize = samplesPerFrame; heAACInfo.dwReserved1 = 0; heAACInfo.dwReserved2 = 0;
- 使用构建好的结构体初始化
IMFMediaType:
IMFMediaType* pOutputType = nullptr; hr = MFInitMediaTypeFromWaveFormatEx(&heAACInfo, sizeof(heAACInfo), &pOutputType); // 后续将pOutputType用于SinkWriter的AddStream或SetOutputType
方案3:直接构造目标AAC类型的IMFMediaType
如果枚举的类型无法满足需求,可直接手动创建IMFMediaType并设置必要属性,无需依赖枚举:
IMFMediaType* pAACType = nullptr; MFCreateMediaType(&pAACType); // 设置媒体类型为音频 pAACType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); // 设置子类型为AAC(HE-AAC对应MFAudioFormat_AAC_HE_V2) pAACType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); // 设置通道数、采样率等基础属性 pAACType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, 2); pAACType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100); // 设置AAC profile和比特率 pAACType->SetUINT32(MF_MT_AAC_PROFILE, MF_AAC_PROFILE_LC); pAACType->SetUINT32(MF_MT_AAC_BITRATE, 128000);
注意事项
- 不同版本的Windows对AAC编码器的支持有差异,HE-AAC可能需要Windows 8及以上版本
- 若使用HE-AAC,需确保设置正确的
MF_MT_AAC_PROFILE属性,对应WAVE_FORMAT_MPEG_HEAAC格式标签 - 手动构建结构体时,cbSize必须准确设置为扩展部分的大小,否则
MFInitMediaTypeFromWaveFormatEx会返回错误
内容的提问来源于stack exchange,提问作者Simpleton
相关产品推荐
相关产品推荐

