gpt4 book ai didi

h.264 - 媒体基金会 : Registering custom ClassFactory doesn't work

转载 作者:行者123 更新时间:2023-12-04 21:01:26 24 4
gpt4 key购买 nike

背景:
我正在使用 SinkWriter 将 NV12 缓冲区编码为包装在 MPEG4 容器中的 h264 视频流。一切正常,但有一个问题,因为 SinkWriter 抽象了低级编码器配置,我无法控制 GOP 大小、B 图片计数、CODECAPI_AVEncCommonRateControlMode 等属性。

问题是由于 水槽作家 仅在 之后实例化编码器变换设置输入媒体类型 打电话,我们就能得到编解码器API 仅在该点之后的实例。因此,在这一切发生之前,我们无法控制编码器并配置必要的 Prop ,它也永远不会通过 CodecAPI 实例对编码器进行进一步的更改。

实验:
我尝试了 PropertyStore( MF_SINK_WRITER_ENCODER_CONFIG ) 方法,但似乎没有任何变化(它可能是平台/编码器特定的行为),我还可以看到很多人提示这些 API 的不可预测行为。然后,我遇到了this MSDN 线程(差不多 7 年的帖子),其中用户描述了他如何通过在 Windows7 机器上本地注册一个自定义类工厂来处理这个问题。

问题:
the MSDN thread作为引用,我尝试实现 IClassFactory 并通过 MFTRegisterLocal 注册它但是我永远不会调用 CreateInstance 函数(Windows 10 机器)。我只获得了为 IID_IClassFactory 和 IID_IMFAttributes 接口(interface)调用的 QueryInterface 方法。而且,SinkWriter 似乎正在自行获取 MFT。

我知道我可能做错了什么,而且我不是 COM 专家。还有其他方法可以实现吗?

自定义类工厂实现:

class MyClassFactory : public IClassFactory  {

public:
MyClassFactory () : _cRef(1) {}

~MyClassFactory() {}

// Only this method is getting called
STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
{

HRESULT hr = E_NOTIMPL;

// Only the below 2 cases (IID_IClassFactory and IID_IMFAttributes) are getting hit
if (IID_IClassFactory == riid)
{
*ppv = static_cast<IClassFactory*>(this);

if (*ppv) {
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
}

hr = S_OK;
}
else if (IID_IMFAttributes == riid)
{
if (!pEncoder) {

hr = FindEncoderEx(&pEncoder);
}

IMFAttributes *attributes;
hr = pEncoder->GetAttributes(&attributes);

*ppv = attributes;
}
else
{
//This case has never been reached
}

return hr;
}

//This is never called
STDMETHODIMP CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppv)
{
HRESULT hr = S_OK;

if (pUnkOuter != NULL)
{
if (riid != __uuidof(IUnknown))
{
return E_NOINTERFACE;
}
}

if (!pEncoder) {

hr = FindEncoderEx(&pEncoder);
}

hr = pEncoder->QueryInterface(riid, ppv);

return hr;
}

IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
}

IFACEMETHODIMP_(ULONG) Release()
{
assert(_cRef > 0);

LONG cRef = InterlockedDecrement(&_cRef);

if (!cRef)

delete this;

return cRef;

}

STDMETHODIMP LockServer(BOOL fLock)
{
if (fLock)
{
AddRef();
}
else {
Release();
}

return S_OK;
}

HRESULT FindEncoderEx(IMFTransform** ppEncoder)
{
...
}

protected:
LONG _cRef;
CComPtr<IMFTransform> pEncoder = NULL;
};

注册定制类工厂:

MyClassFactory* cf = new MyClassFactory();
MFT_REGISTER_TYPE_INFO infoInput = { MFMediaType_Video, MFVideoFormat_NV12 };
MFT_REGISTER_TYPE_INFO infoOutput = { MFMediaType_Video, MFVideoFormat_H264 };
MFTRegisterLocal(cf, MFT_CATEGORY_VIDEO_ENCODER, L"MyClassFactory", 0, 1, &infoInput, 1, &infoOutput);

任何帮助,将不胜感激。

最佳答案

您在这里如履薄冰,因为您尝试做的事情不应该奏效。您确实(或至少可以)注册一个本地转换,但 API 通常更喜欢其他现有的 MFT,因为它们具有更高的内部值(value)(并且具有硬件辅助支持),因此您不应覆盖现有行为。

你真正的选择是:

  • 使用 MF_SINK_WRITER_ENCODER_CONFIG attribute传递编码器特定配置
  • 使用 COM 而不是 MF 为编码器的现有 CLSID 注册类工厂,以便 MFT 的 COM 实例化如您所愿;您必须弄清楚有关 COM 的详细信息才能实现这一点,一般来说,我不建议在没有充分理由的情况下干扰 COM 注册/实例化的标准行为
  • 在 Sink Writer API 之外单独运行编码 MFT(或其等价物 - 在这种情况下您不必完全使用 MFT),并为 Sink Writer 提供已压缩的数据
  • 关于h.264 - 媒体基金会 : Registering custom ClassFactory doesn't work,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59611835/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com