gpt4 book ai didi

audio - IMFTransform SetInputType()/SetOutputType() 失败

转载 作者:行者123 更新时间:2023-12-02 22:52:18 34 4
gpt4 key购买 nike

我正在尝试在 Windows 7 上使用 WASAPI 共享模式和媒体基础 IMFSourceReader 播放 MP3(和类似的音频文件)。据我了解,我必须在 IMFSourceReader 解码和 WASAPI 播放之间使用 IMFTransform。除了我在 IMFTransform 上调用 SetInputType()/SetOutputType() 之外,一切似乎都很好?
相关的代码片段是:

MFCreateSourceReaderFromURL(...);   //  Various test mp3 files
...

sourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &reader.audioType);
//sourceReader->GetNativeMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &reader.audioType);
...

audioClient->GetMixFormat(&player.mixFormat);
...

MFCreateMediaType(&player.audioType);
MFInitMediaTypeFromWaveFormatEx(player.audioType, player.mixFormat, sizeof(WAVEFORMATEX) + player.mixFormat->cbSize);
...




hr = CoCreateInstance(CLSID_CResamplerMediaObject, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&unknown);
ASSERT(SUCCEEDED(hr));

hr = unknown->QueryInterface(IID_PPV_ARGS(&resampler.transform));
ASSERT(SUCCEEDED(hr));
unknown->Release();

hr = resampler.transform->SetInputType(0, inType, 0);
ASSERT(hr != DMO_E_INVALIDSTREAMINDEX);
ASSERT(hr != DMO_E_TYPE_NOT_ACCEPTED);
ASSERT(SUCCEEDED(hr)); // Fails here with hr = 0xc00d36b4

hr = resampler.transform->SetOutputType(0, outType, 0);
ASSERT(hr != DMO_E_INVALIDSTREAMINDEX);
ASSERT(hr != DMO_E_TYPE_NOT_ACCEPTED);
ASSERT(SUCCEEDED(hr)); // Fails here with hr = 0xc00d6d60
我怀疑我误解了如何在事物之间协商输入/输出 IMFMediaType,以及如何考虑 IMFTransform 需要对未压缩数据进行操作?
对我来说,输出类型失败似乎很奇怪,但也许这是输入类型首先失败的链式 react - 如果我尝试先设置输出类型,它也会失败。

最佳答案

在最新版本的 Windows 中,您可能更愿意利用已经为您提供的库存功能。
当您配置 Source Reader 对象时, IMFSourceReader::SetCurrentMediaType 让你指定你想要你的数据的媒体类型。如果你设置的媒体类型与 WASAPI 要求兼容,Source Reader 会自动添加转换来为你转换数据。
然而...

Audio resampling support was added to the source reader with Windows 8. In versions of Windows prior to Windows 8, the source reader does not support audio resampling. If you need to resample the audio in versions of Windows earlier than Windows 8, you can use the Audio Resampler DSP.


...这意味着您确实可能需要自己管理 MFT。 MFT 的输入媒体类型应该来自 IMFSourceReader::GetCurrentMediaType .要指示源阅读器使用未压缩的音频,您需要为这种类型的流构建一个媒体类型解码器,将音频解码为。例如,如果您的文件是 MP3,那么您将读取 channel 数、采样率并构建兼容的 PCM 媒体类型(或使用系统解码器并单独询问输出媒体类型,这甚至是一种更简洁的方式)。您可以使用 IMFSourceReader::SetCurrentMediaType 设置这种未压缩的音频媒体类型。 .此媒体类型也将是音频重采样器 MFT 的输入媒体类型。这将指示源阅读器添加必要的解码器和 IMFSourceReader::ReadSample会给你转换后的数据。
reasmpler MFT 的输出媒体类型将派生自您从 WASAPI 获得的音频格式,并使用您在代码片段顶部提到的 API 调用进行转换。
要查看错误代码,您可以使用以下命令:
  • https://www.magnumdb.com/search?q=0xc00d36b4
  • https://www.magnumdb.com/search?q=0xc00d6d60

  • 此外,您通常应该能够使用 Media Foundation Media Session API 播放音频文件。用较小的努力。 Media Session 使用相同的原语来构建播放管道并负责格式拟合。

    Ah so are you saying I need to create an additional object that is the decoder to fit between the IMFSourceReader and IMFTransform/Resampler?


    没有。通过做 SetCurrentMediaType使用正确的媒体类型,您可以让 Source Reader 在内部添加解码器,以便它可以为您提供已经解压缩的数据。从 Windows 8 开始,它还能够在 PCM 风格之间进行转换,但在 Windows 7 中,您需要使用 Audio Resampler DSP 自己处理这个问题。
    您可以自己管理解码器,但您不需要这样做,因为 Source Reader 的解码器会更可靠地执行相同的操作。
    您可能需要一个单独的解码器来帮助您猜测 PCM 媒体类型解码器会产生什么,以便您从 Source Reader 请求它。 MFTEnumEx是查找解码器的正确 API。

    I am not sure how to decide on or create a suitable decoder object? Do I need to enumerate a list of suitable ones somehow rather than assume specific ones?


    提到的 MFTEnum , MFTEnumEx API 调用可以枚举所有可用或按给定标准过滤的解码器。
    另一种方法是使用部分媒体类型(请参阅此处的相关说明和代码片段: Tutorial: Decoding Audio)。部分媒体类型是有关所需格式的信号,要求媒体基础 API 提供与此部分类型匹配的原语。有关相关讨论链接,请参阅下面的评论。

    关于audio - IMFTransform SetInputType()/SetOutputType() 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64593597/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com