【问题标题】:Creating NV12 encoded video using windows media foundation使用 Windows Media Foundation 创建 NV12 编码视频
【发布时间】:2014-09-25 12:22:33
【问题描述】:

我正在学习使用本教程http://blogs.msdn.com/b/eternalcoding/archive/2013/03/06/developing-a-winrt-component-to-create-a-video-file-using-media-foundation.aspx使用 Windows Media Foundation 创建具有原始固定彩色图像的视频文件

我能够创建上面链接中显示的 RGB 编码的 WMV 视频。但我需要从图像中创建 NV12 格式的 YUV 编码 MP4 视频。由于 NV12 为每帧使用 (W x H x 3/2) 字节的内存缓冲区,我为图像缓冲区创建了 (W x H x 3/2) 字节的缓冲区(教程中的变量“目标”)并设置了一些固定的值作为图像数据。然后为 MFCopyImage() 设置图像步幅“W”(ARGB 使用 Wx4 作为步幅),并将高度设置为“H”。但这似乎不起作用。 MF_MT_SUBTYPE 设置为 MFVideoFormat_NV12。

创建 NV12 编码的 mp4 视频文件的正确方法是什么?

【问题讨论】:

    标签: video windows-runtime c++-cx yuv ms-media-foundation


    【解决方案1】:

    我怀疑你做的工作太多(希望这是个好消息)。首先请记住,该示例未将输出编码为 RGB。 RGB 只是接收器的输入类型,您可以随意保留它。

    容器是 MFTranscodeContainerType_ASF(稍后会详细介绍), 子类型是 MFVideoFormat_WMV3, 结果是一个压缩良好的 windows media 视频文件。

    创建接收器编写器时,在您的情况下,容器会自动创建,因为未指定属性。实际上,添加的唯一属性是 MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS 在以下几行:

    MFCreateAttributes(&spAttr, 10);
    spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true);
    hr = MFCreateSinkWriterFromURL(L".wmv", 
                                   spByteStream.Get(), 
                                   spAttr.Get(), 
                                   &sinkWriter);
    

    这引出了一个问题——“为什么要分配 10 个属性?” ... (耸耸肩)哦,好吧,没关系。

    关键是,您将 RGB 帧发送到接收器,并且正在执行转换以完成对您的规范的编码。容器可以在这里找到:

    http://msdn.microsoft.com/en-us/library/windows/desktop/dd388919(v=vs.85).aspx

    在创建接收器之前,您将指定一个类似于以下内容的给定容器:

    spAttr->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_ASF);
    // or MFTranscodeContainerType_MPEG4, MFTranscodeContainerType_AVI, etc
    

    您之前使用以下行设置了子类型:

    hr = mediaTypeOut->SetGUID(MF_MT_SUBTYPE, encodingFormat);
    // where encodingFormat was hardcoded to MFVideoFormat_WMV3 in the ctor
    

    但请记住,某些格式需要自下而上的图像。尝试将文件扩展名更改为“.mp4”,将容器更改为 MFTranscodeContainerType_AVI,将子类型更改为 MFVideoFormat_NV12,您将看到相同的视频倒置。与 wmv 相比,您的文件会很大,因为所有 YUV 值都已放入文件中。

    正确获取容器和格式细节需要非常小心,而且有些细节很难研究。

    希望这会有所帮助。

    【讨论】:

    • 非常感谢。我非常感谢您的详细解释,这对像我这样的新手非常有帮助。我也遇到了这个msdn.microsoft.com/en-us/library/windows/desktop/… 据我了解,这段代码使用接收器编写器写入文件'output.wmv'。但是代码在 'MFCreateSinkWriterFromURL(L"output.wmv", NULL, NULL, &pSinkWriter);' 处出现访问违规异常在“InitializeSinkWriter()”中。我想问你,你能确定可能是什么问题吗?
    • 你好。我遇到了一个小问题。我今天正在编写包含 MF_TRANSCODE_CONTAINERTYPE 的代码。但它说 MF_TRANSCODE_CONTAINERTYPE 未定义。我已经包含了“Mfidl.h”,但我似乎仍然找不到合适的头文件。
    • @croc - 很奇怪。检查顺序,以及包含每个头文件的位置。如果您使用的是预编译的标头(您可能已经知道),这是最简单的。
    • 我查看了 Mfidl.h 文件。 MF_TRANSCODE_CONTAINERTYPE 的部分显示为灰色。所以将该部分复制到我的解决方案文件中,代码工作正常。我将输入定义为 MFVideoFormat_RGB32,输出定义为 MFVideoFormat_NV12,容器类型定义为 MFTranscodeContainerType_AVI。我没有发送 NV12 格式的帧,而是发送 ARGB 帧,并且创建了一个 mp4 文件,没有任何错误。我有什么方法可以检查输出的视频帧格式是否真的是 NV12 编码的?如果我将容器从 AVI 更改为 MPGE4,则不会产生视频。
    • 首先,它变灰是有原因的。您应该确定评估哪个预处理器指令(在 Mfidl.h 中)以使其变灰。要验证视频流的类型,请使用“MediaInfo”等实用程序(可能有更好的实用程序)。如果您使用 MediaInfo,则有多个视图可供选择,其中显示各种信息。最后,让容器/子类型设置正确可能很困难,也很难研究。祝你的项目好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多