如何使用 Media Foundation 从 MP4 视频中丢弃任意帧?

Posted

技术标签:

【中文标题】如何使用 Media Foundation 从 MP4 视频中丢弃任意帧?【英文标题】:How can arbitrary frames be discarded from an MP4 video using Media Foundation? 【发布时间】:2014-03-05 17:16:45 【问题描述】:

我目前正在尝试实现一种算法,该算法可以在编码到另一个 MP4 时快速丢弃 MP4 视频中不需要的帧(使用 Media Foundation)。

编码部分似乎还不错——“Source Reader plus Sink Writer”方法既好又快。您基本上只需要创建一个 IMFSourceReader 和一个 IMFSinkWriter,在 writer、yada、yada、yada 上设置源原生媒体类型,然后循环:source.ReadSample(&sample) --> writer.WriteSample(&sample )。 WriteSample() 调用可以以它们是否“!2 b 丢弃”为条件。

如果您认为读取的样本将是“预测帧”,也就是 H.264 编码流中的 P 帧,那么这种幼稚的方法并不好。在此之前丢弃任何前面的“帧内编码图片帧”(I 帧或关键帧)将导致视频乱码。

所以,我的问题是,是否可以在接收器写入器中恢复样本写入之前(以某种方式)将 I 帧引入接收器写入器?

使用MFSampleExtension_CleanPoint 属性做某事似乎没有帮助。我可以手动创建一个 IMFSample(通过MFCreateSample),但要获得正确的 H.264 格式可能会很棘手。

有什么想法吗?或者对在编码期间丢帧的其他方法有什么想法?

【问题讨论】:

【参考方案1】:

我认为如果不重新编码视频,这是不可能的! P 和 I 帧之间的参考在 h264 比特流中,而不是在容器 (MP4) 中。您只能安全地跳过其他帧未引用的帧:

GOP 的最后一个 P 帧(在下一个 I 帧之前) B 帧

通常这些框架不被引用,但它们可以被引用!这取决于用于创建 h264 流的编码器设置

【讨论】:

解决这个问题的方法肯定是在尝试丢弃任何帧之前解压缩流。也就是说,我让 IMFSourceReader 使用 MFVideoFormat_YUY12 作为输出 IMFMediaType 并在 IMFSinkWriter 输入上设置相同的格式。然后,ReadSample() 和 WriteSample() 之间的任何中间处理都可以依赖于整个帧。这样做的代价是编码速度要慢得多。 :(

以上是关于如何使用 Media Foundation 从 MP4 视频中丢弃任意帧?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Media Foundation 从 MP4 视频中丢弃任意帧?

使用 Microsoft Media Foundation 从文件播放视频

使用 Media Foundation .NET 从 MP4 获取帧速率

使用 Media Foundation 将音频从文件播放到扬声器

如何确定 Media Foundation 中特定 MJPEG 子类型的色度子采样?

使用 MS Media Foundation 从 Windows 应用程序中隐藏相机设备名称?