Ove
Ove

Reputation: 6317

Change h.264 quality when using SinkWriter to encode video

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

Answers (2)

Mitch
Mitch

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

Ove
Ove

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

Related Questions