Reputation: 6317
I am using Microsoft Media Foundation to encode a H.264 video file.
I am using the SinkWriter to create the video file. The input is a buffer (MFVideoFormat_RGB32
) where I draw the frames and the output is a MFVideoFormat_H264
.
The encoding works and it creates a video file with my frames in it. But I want to set the quality for that video file. More specifically, I want to set the CODECAPI_AVEncCommonQuality
property on the H.264 encoder.
In order to get a handle to the H.264 encoder, I call GetServiceForStream on the SinkWriter. Then I set the CODECAPI_AVEncCommonQuality
property.
The problem is that my property change is ignored. As stated in the documentation:
To set this parameter in Windows 7, set the property before calling IMFTransform::SetOutputType. The encoder ignores changes after the output type is set.
The problem is that I don't create the H.264 encoder manually. I set the input and the output type on the SinkWriter, and the SinkWriter creates the H.264 encoder automatically. As soon as it creates the encoder, it calls the IMFTransform::SetOutputType
method, and I can't change the CODECAPI_AVEncCommonQuality
property anymore. The documentation also says that the property change isn't ignored in Windows 8, but I need this to run on Windows 7.
Do you know how I can change the quality for the encoded file while using SinkWriter on Windows 7?
PS: Someone asked the same question on the msdn forums, and he didn't seem to get an answer.
Upvotes: 4
Views: 2198
Reputation: 22251
CODECAPI_AVEncCommonRateControlMode
and CODECAPI_AVEncCommonQuality
can be passed to the h.264 encoder using IMFSinkWriter->SetInputMediaType(/* ... */,, IMFAttributes pEncodingParameters)
. I suspect other CODECAPI_
values would work as well.
CComPtr<IMFAttributes> pEncAttrs;
ATLENSURE_SUCCEEDED(MFCreateAttributes(&pEncAttrs, 1));
ATLENSURE_SUCCEEDED(pEncAttrs->SetUINT32(CODECAPI_AVEncCommonRateControlMode, eAVEncCommonRateControlMode_Quality));
ATLENSURE_SUCCEEDED(pEncAttrs->SetUINT32(CODECAPI_AVEncCommonQuality, 40));
ATLENSURE_SUCCEEDED(writer->SetInputMediaType(sink_stream, mtSource, pEncAttrs));
// ^^^^^^^^^
Upvotes: 1
Reputation: 6317
As the documentation says, you just can't change the CODECAPI_AVEncCommonQuality
property after the output type is set, and the SinkWriter sets the output type before you can get a hand on the encoder.
In order to bypass this problem I managed to create a class factory and register it in Media Foundation, so that the SinkWriter uses it to create a new encoder. In my class factory, I create a new H264 encoder and set whatever properties I want before passing it on to the SinkWriter.
I have written in more detail the steps I took to create this class factory on the MSDN forums, here: http://social.msdn.microsoft.com/Forums/en-US/mediafoundationdevelopment/thread/6da521e9-7bb3-4b79-a2b6-b31509224638
That was the only way I could get around my problem on Windows 7.
Upvotes: 4