Creating NV12 encoded video using windows media foundation
I was learning to create video files with raw fixed colored images using Windows Media Foundation using this tutorial http://blogs.msdn.com/b/eternalcoding/archive/2013/03/06/developing-a-winrt-component-to-create-a-video-file-using-media-foundation.aspx
I was able to create RGB encoded WMV video shown in the above link. But i need to create YUV encoded MP4 video in NV12 format from image. Since NV12 use (W x H x 3/2) bytes of memory buffer for each frame, i created (W x H x 3/2) bytes of buffer for image buffer(variable 'target' in the tutorial) and set some fixed values to it as image data. Then set image stride 'W' (ARGB uses Wx4 as stride) for the MFCopyImage() and height is set to just 'H'. But that doesn't seem to work. MF_MT_SUBTYPE is set to MFVideoFormat_NV12.
What is the correct way to create a NV12 encoded mp4 video file?
I suspect you are doing too much of the work (which hopefully is good news). First keep in mind that the example does not encode the output as RGB. RGB was simply the input type to the sink, and you can feel free to leave it that way.
The container is MFTranscodeContainerType_ASF (more on that in a sec), and the subtypte is MFVideoFormat_WMV3, and the result is a well compressed windows media video file.
When the sink writer is created, in your case the container is automatically created, since the attribute wasn't specified. In fact, the only attribute added is MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS on the following lines:
MFCreateAttributes(&spAttr, 10); spAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true); hr = MFCreateSinkWriterFromURL(L".wmv", spByteStream.Get(), spAttr.Get(), &sinkWriter);
Which begs the question - 'why are 10 attributes allocated?' ... (shrug) oh well, doesn't matter.
The point being, you send RGB frames to the sink, and transforms are being done to complete the encoding to your specification. Containers may be found here:
and prior to creating the sink, you would specify a given container similar to the following:
spAttr->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_ASF); // or MFTranscodeContainerType_MPEG4, MFTranscodeContainerType_AVI, etc
You previously set the subtype using the following line:
hr = mediaTypeOut->SetGUID(MF_MT_SUBTYPE, encodingFormat); // where encodingFormat was hardcoded to MFVideoFormat_WMV3 in the ctor
Keep in mind however, some formats expect bottom-up images. Try changing the file extension to ".mp4", container to MFTranscodeContainerType_AVI, and the subtype to MFVideoFormat_NV12 and you will see your same video upside-down. And your file will be huge comparing to the wmv since all of the YUV values are placed into the file.
Getting the container and format details correct requires a good deal of care, and some details are difficult to research.
Hope this helps.