There is a lot of available formats and codecs for encoding. This article is about how to specify the required encoding configuration.
Encoding formats
The main parameter for encoding is a format. It specifies the target container and sets an MWriter (or an MFWriter) object to use only available for the specified format audio and video codecs.
To get a list of available formats you should use the ConfigGetCount method for and MWriter object and the WriterOptionGetCount method for an MFWriter object.
MFormats SDK
MFWriterClass m_objWriter = new MFWriterClass(); int nCount; m_objWriter.WriterOptionGetCount(eMFWriterOption.eMFWO_Format, out nCount); for (int i = 0; i < nCount; i++) { string myName, longName; m_objWriter.WriterOptionGetByIndex(eMFWriterOption.eMFWO_Format, i, out myName, out longName); }
The WriterOptionGetByIndex returns you a short name of the format, e.g. "mp4", and its full name, e.g. "MP4 (MPEG-4 Part 14)".
MPlatform SDK
MWriterClass m_objWriter = new MWriterClass(); int nCount; m_objWriter.ConfigGetCount("format", out nCount); for (int i = 0; i < nCount; i++) { string myName; m_objWriter.ConfigGetByIndex("format", i, out myName); }
The ConfigGetByIndex method returns you a short name of a format, e.g. "mp4".
MFormats SDK
You should use the WriterOptionSetByIndex method to specify the required format. It uses an index of target name:
IMFProps props; m_objWriter.WriterOptionSetByIndex(eMFWriterOption.eMFWO_Format, targetIndex, out props);
where props contain all the available parameters for the specified format (see below).
MPlatform SDK
To set the format you should use the ConfigSet method. This method uses a full or a short name of the required format.
IMAttributes myAttributes; m_objWriter.ConfigSet("format", "mp4", out myAttributes);
where the available parameters are stored in myAttributes.
Available video and audio codecs
Once the encoding format is specified, the MWriter (MFWriter) object is configured to set the desired audio and video codecs.
The way to get a list of available codecs and to set them is similar to setting a format. Note please that it is possible only after the format is set.
MFormats SDK
To get a list of video codecs:
int nCount; m_objWriter.WriterOptionGetCount(eMFWriterOption.eMFWO_VideoCodec, out nCount); for (int i = 0; i < nCount; i++) { string myName, longName; m_objWriter.WriterOptionGetByIndex(eMFWriterOption.eMFWO_VideoCodec, i, out myName, out longName); }
To get a list of audio codecs:
int nCount; m_objWriter.WriterOptionGetCount(eMFWriterOption.eMFWO_AudioCodec, out nCount); for (int i = 0; i < nCount; i++) { string myName, longName; m_objWriter.WriterOptionGetByIndex(eMFWriterOption.eMFWO_AudioCodec, i, out myName, out longName); }
To set the codecs:
IMFProps videoProps; m_objWriter.WriterOptionSetByIndex(eMFWriterOption.eMFWO_VideoCodec, targetIndex, out videoProps); IMFProps audioProps; m_objWriter.WriterOptionSetByIndex(eMFWriterOption.eMFWO_AudioCodec, targetIndex, out audioProps);
MPlatform SDK
To get a list of video codecs:
int nCount m_objWriter.ConfigGetCount("format::video", out nCount); for (int i = 0; i < nCount; i++) { string myName; m_objWriter.ConfigGetByIndex("format::video", i, out myName); }
To get a list of audio codecs:
int nCount m_objWriter.ConfigGetCount("format::audio", out nCount); for (int i = 0; i < nCount; i++) { string myName; m_objWriter.ConfigGetByIndex("format::audio", i, out myName); }
To set the codecs:
IMAttributes myVideoAttributes; m_objWriter.ConfigSet("format::video", "mpeg4", out myVideoAttributes); IMAttributes myAudioAttributes; m_objWriter.ConfigSet("format::audio", "libmp3lame", out myAudioAttributes);
Setting attributes
All the formats and codecs have specific attributes. For example, bitrate for audio and video codecs, or enabling SCC and ANC Closed Captions data encoding for a format.
You can get an interface with available attributes the moment you set a format or a codec. Or you can get them later with the WriterOptionGet method in MFormats SDK or the ConfigGet method in MPlatform SDK.
MFormats SDK
IMFProps videoProps; string videoName; m_objWriter.WriterOptionGet(eMFWriterOption.eMFWO_VideoCodec, out videoName, out videoProps);
MPlatform SDK
string videoName; IMAttributes videoProps; m_pConfigRoot.ConfigGet("format::video", out videoName, out videoProps)
Once you've got an object with attributes (IMAttributes or IMFProps), you can get a list of available parameters:
MFormats SDK
int nCount = 0; videoProps.PropsGetCount("", out nCount); for (int i = 0; i < nCount; i++) { string strName, strValue; int isNode; videoProps.PropsGetByIndex("", i, out strName, out strValue, out isNode); }
MPlatform SDK
int nCount = 0; videoProps.AttributesGetCount(out nCount); for (int i = 0; i < nCount; i++) { string strName, strValue; videoProps.AttributesGetByIndex("", i, out strName, out strValue); }
And finally, to set an attribute, you should use the AttributesStringSet method for MPlatform SDK, and the PropsSet method for MFormats SDK.
MFormats SDK
videoProps.PropsSet("b", "10M"); // to specify a bitrate
MPlatform SDK
videoProps.AttributesStringSet("b", "10M");
A full list of available parameters you can get in Formats and Codecs.
Using a ready-to-use string
Finally, you have specified format, audio, and video codecs and all the required parameters for encoding. The only thing is to use the result configuration for encoding.
To get a full encoding string, you should use the ConfigGetAll method for the MWriter object, and the WriterGet method for the MFWriter object.
MFormats SDK
string targetPath, encodingConfig; m_objWriter.WriterGet(out targetPath, out encodingConfig);
MPlatform SDK
string encodingConfig; m_objWriter.ConfigGetAll(1, out encodingConfig);
The result string looks like this:
format='mp4' video::codec='mpeg4' video::b='10M' audio::codec='libmp3lame'
You can save the string to use it as a template later.
To specify the encoding configuration for the actual encoding process you should use the string in the WriterNameSet method for the MWriter object, or in the WriterSet method for the MFWriter object. In both methods, you specify a target path for encoding.
MFormats SDK
m_objWriter.WriterSet(@"c:\testEncoding.mp4", 1, "format='mp4' video::codec='mpeg4' video::b='10M' audio::codec='libmp3lame'");
Note that you should use "1" in the WriterSet method to override the previous configuration.
MPlatform SDK
m_objWriter.WriterNameSet(@"c:\testEncoding.mp4", "format='mp4' video::codec='mpeg4' video::b='10M' audio::codec='libmp3lame'");
How to check is the configuration valid?
If the "config.auto_check" property enabled with PropsSet method for MFWriter object, the object returns you an error when you try to set an incorrect configuration. For example, if a video or an audio codec is not supported or is specified incorrectly.
m_objWriter.PropsSet("config.auto_check", "true");
m_objWriter.WriterSet(@"c:\testEncoding.mp4", 1, "format='mp4' video::codec='wrongCodecName' video::b='10M' audio::codec='libmp3lame'");
This is extremely useful when you work with NVIDIA-powered H.264 encoding on GTX devices - when the number of encoding streams you can use at the same time is limited. With this property, you can get a moment when NVENC can't be initialized and switch to another H.264 encoding option.
Next, you can start and control the encoding process.
How to encode with different audio codecs?
When you use the "split_channels" property, you record multiple audio tracks. In this case, you have the ability to encode each track with your own codec. For example, if your source has 4 audio channels and you want to record 2 audio tracks, the first with AAC codec and the second with AC3, then use the following configuration:
"format='mp4' split_channels='2' video::codec='mpeg2video' video::b='5M' audio::codec='aac' audio.1::codec='ac3'"
Please note that in the MFormats SDK, you should set the "_bResetOption" parameter of the "WriterSet" method to "true" for this feature to work correctly.