【问题标题】:Change h.264 quality when using SinkWriter to encode video使用 SinkWriter 编码视频时更改 h.264 质量
【发布时间】:2012-11-08 10:42:13
【问题描述】:

我正在使用 Microsoft Media Foundation 对 H.264 视频文件进行编码。

我正在使用 SinkWriter 创建视频文件。输入是一个缓冲区 (MFVideoFormat_RGB32),我在其中绘制帧,输出是 MFVideoFormat_H264

编码有效,它会创建一个包含我的帧的视频文件。但我想设置该视频文件的质量。更具体地说,我想在 H.264 编码器上设置CODECAPI_AVEncCommonQuality 属性。

为了获得 H.264 编码器的句柄,我在 SinkWriter 上调用了GetServiceForStream。然后我设置CODECAPI_AVEncCommonQuality 属性。

问题是我的属性更改被忽略了。如documentation中所述:

要在 Windows 7 中设置此参数,请在调用 IMFTransform::SetOutputType 之前设置该属性。设置输出类型后,编码器会忽略更改。

问题是我没有手动创建 H.264 编码器。我在 SinkWriter 上设置了输入和输出类型,SinkWriter 会自动创建 H.264 编码器。一旦它创建了编码器,它就会调用IMFTransform::SetOutputType 方法,我不能再更改CODECAPI_AVEncCommonQuality 属性。文档还说在 Windows 8 中不会忽略属性更改,但我需要在 Windows 7 上运行它。

您知道在 Windows 7 上使用 SinkWriter 时如何更改编码文件的质量吗?

PS:在msdn论坛Someone asked the same question,他似乎没有得到答案。

【问题讨论】:

    标签: windows-7 encoding h.264 ms-media-foundation


    【解决方案1】:

    正如文档所述,设置输出类型后,您无法更改 CODECAPI_AVEncCommonQuality 属性,并且 SinkWriter 会在您开始使用编码器之前设置输出类型。

    为了绕过这个问题,我设法创建了一个类工厂并将其注册到 Media Foundation 中,以便 SinkWriter 使用它来创建一个新的编码器。在我的类工厂中,我创建了一个新的 H264 编码器并设置了我想要的任何属性,然后将其传递给 SinkWriter。

    我在 MSDN 论坛上更详细地写了创建这个类工厂的步骤,这里:http://social.msdn.microsoft.com/Forums/en-US/mediafoundationdevelopment/thread/6da521e9-7bb3-4b79-a2b6-b31509224638

    这是我在 Windows 7 上解决问题的唯一方法。

    【讨论】:

    • 我知道你已经很久没有处理这个问题了,我遵循了你的代码,但我没有调用 CreateInstance,而是只调用接口 IID_IMFAttributes 和 IID_IClassFactory 的 QueryInterface。我为 IID_IClassFactory 返回了我的类工厂的实例,并为 IID_IMFAttributes 查询了 IMFTransform,但在那之后没有按预期工作。 SinkWriter 似乎在自己枚举 MFT。您能告诉我在 QueryInterface 中应该做什么吗?
    • @Ram 我已经用我旧的 QueryInterface 实现更新了 MSDN 线程。您可以检查一下,看看它是否适合您。
    【解决方案2】:

    CODECAPI_AVEncCommonRateControlModeCODECAPI_AVEncCommonQuality 可以使用 IMFSinkWriter->SetInputMediaType(/* ... */,, IMFAttributes pEncodingParameters) 传递给 h.264 编码器。我怀疑其他 CODECAPI_ 值也会起作用。

    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));
    //                                                                   ^^^^^^^^^
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      • 2012-11-23
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多