使用 IMFSourceReader 打开视频文件

Posted

技术标签:

【中文标题】使用 IMFSourceReader 打开视频文件【英文标题】:Using IMFSourceReader to open a video file 【发布时间】:2014-11-18 10:50:09 【问题描述】:

我想使用IMFSourceReader 打开一个视频文件,以将其帧作为 IMFSample 访问。 在 WinRT C++ 类中,我发送视频文件的 RandomAccessStream 并使用以下代码创建 IMFSourceReader 对象。

HRESULT hr = S_OK;

ComPtr<IMFSourceReader> pSourceReader;
ComPtr<IMFByteStream> spByteStream;

if (SUCCEEDED(hr))

    // Initialize the Media Foundation platform.
    hr = MFStartup(MF_VERSION);


    hr = MFCreateMFByteStreamOnStreamEx((IUnknown*)InputVideoStream, &spByteStream);

    ComPtr<IMFAttributes> Atrr;
    hr = MFCreateAttributes(&Atrr, 10);
    hr = Atrr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true);

    hr = MFCreateSourceReaderFromByteStream(spByteStream.Get(), Atrr.Get(), &pSourceReader);
 

但是函数 MFCreateSourceReaderFromByteStream() 的 HRESULT 正在返回 The Byte Stream Type of the Given URL is unsupported

我不知道我做错了什么。谁能告诉我正确的方法?我使用的是 Windows 8.1。

【问题讨论】:

返回码听起来很清楚。您要播放的文件的视频/音频格式是什么?如果您也无法使用 TopoEdit 播放它,那么您没有此格式的可用编解码器。 我可以打开一些 MP4 文件(编解码器 ID isom),但不能打开每个 MP4 文件(例如编解码器 ID mp42)。除了使用 IMFSourceReader 之外,还有其他方法可以提取视频帧吗? 【参考方案1】:

返回码听起来很清楚。您要播放的文件的视频/音频格式是什么?如果您也无法使用 TopoEdit 播放它,那么您没有此格式的可用编解码器。

除了使用 IMFSourceReader?

无论如何,要提取未压缩的视频样本,首先您必须从其编码流中对其进行解码。在您的情况下,您缺少解码器。也许您的问题应该是我可以使用另一个框架来代替 Media Foundation

我不这么认为。 DirectShow API 不适用于 Windows RT,据我所知,即使 ffmpeg 无法 为该操作系统编译。所以我猜你唯一的选择就是依赖 Media Foundation 和它的编解码器集。

我想到的唯一想法是找到第三方解码器组件 (MFT) 或构建自己的解码器。

编辑:

在您的情况下,IMFMSourceReader 工厂函数 (MFCreateMFByteStreamOnStreamEx) 无法创建源阅读器。这将意味着您的系统缺少足够的容器解析器(即分离器又名解复用器)。因此它无法从容器中提取基本媒体流。这真的是解码前的阶段。

同样,您可以搜索第三方媒体源解析器,或写入/移植一个。当然,您首先会发现 MF 缺少源代码阅读器的特定格式是什么。

一些链接:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms700134%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ee318417%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/aa371872%28v=vs.85%29.aspx

【讨论】:

我在这里有点困惑,因为我是新手。据我所知,MFT 有一个 ProcessInput(),其中传递了一个 IMFSample,ProcessOutput() 返回解码的 IMFSample。因此,首先我需要使用 IMFSourceReader->ReadSample() 从视频中提取 IMFSample,然后才能使用 MFT。但是 SourceReader 一开始就无法加载视频。因此,需要有一种方法可以同时使用 MFT 解码器通过源阅读器打开视频。你能指导我找到任何教程或链接吗? 我已经编辑了我的答案。我不知道好的MF教程,我也会有兴趣发布一些。你可以在 MSDN 上查看资料,也可以在 MF 的博客上查看:blogs.msdn.com/b/mf。你也可以看看这个项目:sourceforge.net/projects/mfnode 我可以用 TopoEdit 播放视频文件。它在图中显示它使用“Microsoft H264 Video Decoder MFT”。那么这是否意味着我已经为这种格式安装了必要的编解码器?如果我能以某种方式调用这个解码器 MFT,我是否能够使用 IMFSourceReader 来读取该视频的 IMFSamples? 您是否尝试过使用源解析器?首先创建IMFSoureResolver,然后调用它的方法创建媒体源对象。如图所示:msdn.microsoft.com/en-us/library/windows/desktop/… 如果您能够在 TopoEdit 中播放媒体文件,那么您拥有必要的 MF 解复用器/解码器。【参考方案2】:

我找到了解决IMFSourceReaderThe Byte Stream Type of the Given URL is unsupported 问题的方法。我可以读取WMV 文件的字节流,一些MP4 文件,但不是所有类型的视频文件。所以在使用MFCreateSourceReaderFromByteStream() 之前,我将视频流转换为VC-1/WMV 可以读取的MFCreateSourceReaderFromByteStream() 格式。我使用 MSDN 的Transcoding media sample 将他的视频转换为 WMV 视频。现在我可以毫无错误地使用MFCreateSourceReaderFromByteStream()

【讨论】:

以上是关于使用 IMFSourceReader 打开视频文件的主要内容,如果未能解决你的问题,请参考以下文章

在使用 IMFSourceReader 时转换流媒体类型

如何使用 Media Foundation 从 IMFSourceReader 播放音频缓冲区

如何通过 IMFSourceReader 使用自定义堆

处理来自 IMFSourceReader 和 IMFSample 的图像数据

使用 IMFSourceReader 进行音频流式传输(Microsoft Media Foundation)

IMFSourceReader.ReadSample 在读取流 1 后从不触发回调。对流 0 的调用工作正常