在MediaFoundation硬件MFT中设置更大的GOP大小

3

我试图通过桌面复制API捕获的桌面直播,H264编码工作正常,但是桌面复制API仅在屏幕更改时提供帧,而视频编码器期望按恒定的帧率提供帧。因此,我被迫保存先前的样本以便在没有屏幕更改触发时以恒定的速率向编码器馈送数据。这有效,我可以在另一端看到实时输出。

然而,有一个问题,编码器以恒定的速率生成等于全屏新样本大小的大样本(可能是关键帧)。我还注意到,即使没有屏幕更改,我只提供了先前创建的样本,并且它们之间几乎没有差异(除了我设置的样本时间),也会每隔1秒钟(我猜测可能是默认的GOP大小)产生一个I帧(即大样本)。这对于实时流而言是昂贵的,我不希望解码器能够在流中间寻找或加入流(至少我对此有控制),是否可以通过设置较大的GOP来解决这个问题?

我尝试了以下所有设置,但似乎没有任何改变。

FPS: 30

CHECK_HR(pMFTOutputMediaType->SetUINT32(CODECAPI_AVEncMPVGOPSize, 1024), "Failed to set GOP size");
CHECK_HR(pMFTOutputMediaType->SetUINT32(CODECAPI_AVEncMPVGOPSInSeq, 1024), "Failed to set GOPInSeq");
CHECK_HR(pMFTOutputMediaType->SetUINT32(MF_MT_MAX_KEYFRAME_SPACING, 1024), "Failed to set keyframe spacing");

我尝试设置CODECAPI_AVEncCommonRealTime属性,这两个设置是否不兼容?

我还尝试了以下代码(从Chromium https://github.com/chromium/chromium/blob/master/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc复制而来)。关键帧计数仍然没有变化,它仍然每秒生成一个I帧。我想我可能漏掉了一些东西。

这是代码审查链接,其中包含他们讨论此特定配置的讨论。阅读此讨论给了我一些希望,但仍未成功。

void SetEncoderModes() {

    VARIANT var = { 0 };

    if (!mpCodecAPI) {
        CHECK_HR(_pTransform->QueryInterface(IID_PPV_ARGS(&mpCodecAPI)), "Failed to get codec api");
    }

    var.vt = VT_UI4;
    var.lVal = 1024;

    CHECK_HR(mpCodecAPI->SetValue(&CODECAPI_AVEncMPVGOPSize, &var), "Failed to set GOP size");
}

非常感谢您的帮助。


我认为你可以尝试不同的编码器比特率。 - VuVirt
更改比特率可能无法起作用。如果降低比特率,它仍会以恒定的速率产生相同数量的I帧,从而产生质量较低的视频输出,这是不可取的。 - iamrameshkumar
我也尝试了来自Chromium的这段代码(https://chromium-review.googlesource.com/c/chromium/src/+/738916/3/media/gpu/media_foundation_video_encode_accelerator_win.cc#516),但似乎没有任何变化。 - iamrameshkumar
1个回答

2
这段代码片段来自Chromium,实现的方法是使用ICodecAPI接口。正如MSDN(MSDN文档)中所述:
“认证的硬件编码器 [...] 以下是编码器必需和可选的ICodecAPI属性集,以通过HCK编码器认证。 以下是Windows 8和Windows 8.1 ICodecAPI属性要求: [...] CODECAPI_AVEncMPVGOPSize”
因此,在大多数情况下,您将拥有此属性。
请注意,您可能需要在开始实际流之前设置该属性。

1
成功了。似乎在设置输出类型之前设置此属性很重要。我之前是反过来做的,认为只要在那个调用之后启动编码器就可以了。 - iamrameshkumar
看起来这个设置在英特尔编码器中没有被遵守。但在Nvidia上完美地工作。https://dev59.com/Nbfna4cB1Zd3GeqPx7z- - iamrameshkumar
我没有在英特尔设备上测试它。它在 Nvidia 设备上运行得非常完美。我错误地假设它在所有硬件上的表现都是相同的。我进行了很多实验,但无法找出原因。 - iamrameshkumar
看起来其他编码器配置存在一些问题。我只是在试错的基础上玩弄参数。将CODECAPI_AVEncCommonRateControlMode设置为eAVEncCommonRateControlMode_UnconstrainedVBR实际上会将空闲时间比特率降至不到6KBps,但仅持续几秒钟(3至8秒)后,又回到了同样的情况。我已经在我的线程中更新了相同的内容。 - iamrameshkumar
发生了一些奇迹。我不小心将我的机器上的主显示器更改为另一个,现在问题已经解决了。切换回先前选择的主显示器会导致相同的问题。我怀疑d3ddevice是制造麻烦的罪魁祸首。还不确定,需要进行一些实验。 - iamrameshkumar
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接