使用Windows Media Foundation创建NV12编码视频

时间:2014-09-25 12:22:33

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

容器是MFTranscodeContainerType_ASF(在一秒内更多), 子类型是MFVideoFormat_WMV3, 结果是一个压缩良好的Windows媒体视频文件。

创建接收器编写器时,在您的情况下会自动创建容器,因为未指定该属性。实际上,添加的唯一属性是以下行中的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值都放在文件中。

正确获取容器和格式详细信息需要非常谨慎,有些细节很难研究。

希望这有帮助。