通过ICodecAPI为H.264 IMFSinkWriter编码器设置属性 [英] Set attributes via ICodecAPI for a H.264 IMFSinkWriter Encoder

查看:149
本文介绍了通过ICodecAPI为H.264 IMFSinkWriter编码器设置属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过检索ICodecAPI接口来调整通过ActivateObject()创建的H.264编码器的属性. 尽管我没有收到任何错误,但我的设置并未考虑在内.

I am trying to tweak the attributes of the H.264 encoder created via ActivateObject() by retrieving the ICodecAPI interface to it. Although I do not get errors, my settings are not taken into account.

代码在Windows 10下运行.

Code runs under Windows 10.

我复制用于创建IMFSinkWriter的代码,并在下面检索ICodecAPI.错误处理未显示,但没有错误产生.

I copy the code I use to create the IMFSinkWriter and retrieve the ICodecAPI below. Error handling not shown, but no error are produced.

我已经阅读过

I have read this thread which implies that tweaking the encoder used by IMFSinkWriter may not be possible, but since there's no statement on the MSDN documentation I'd like to hear if anyone has managed to use the ICodecAPI with IMFSinkWritter.

如果不可能,将采取什么方式?我需要在H.264中编码并流式传输到MP4.我想更改GOP,Qp,CABAC等,这似乎无法通过输出媒体类型实现. 我应该能够单独创建编码器并将其挂接到MP4文件编写器上吗?任何有关如何做到这一点的指针都表示赞赏...

If not possible, what would be the way to proceed? I need to encode in H.264 and stream to MP4. I want to change the GOP, Qp, CABAC, etc. which does not seem to be possible via the output media type. I should be able to create the encoder separately and hook it to a MP4 file writer? Any pointers as to how to do this appreciated...

hr = encoderToOpen.activate->ActivateObject(__uuidof(IMFTransform), (LPVOID *)&encoderTransform);
hr = encoderTransform->GetAttributes(&attributes);
hr = attributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
hr = MFCreateSinkWriterFromURL(fileName, NULL, attributes, &encoder);

// Initialise outputMediaType (code not shown)

hr = encoder->AddStream(outputMediaType, &streamIndex);
hr = encoder->SetInputMediaType(streamIndex, sourceMediaType, NULL);

// Retrieve the ICodecAPI
ICodecAPI *codecApi;
streamIndex = 0;
hr = encoder->GetServiceForStream(streamIndex, GUID_NULL, __uuidof(ICodecAPI), (LPVOID*)&codecApi);

VARIANT v;
hr = codecApi->GetValue(&CODECAPI_AVEncCommonQuality, &v);
v.vt = VT_UI4;
v.ulVal = 8;
hr = codecApi->SetValue(&CODECAPI_AVEncMPVGOPSize, &v);

// Start encoding (code not shown)

推荐答案

Media Foundation的Sink Writer是一个简化的API,它消除了编码器配置问题.这里的根本问题是,您不拥有编码器MFT,而是通过编写器访问它,然后在一切都设置好之后,编码器围绕更改设置的行为取决于实现,在编码器的情况下,这是特定于供应商的实现可能会因硬件而异.

Media Foundation's Sink Writer is a simplified API with a encoder configuration question slipped away. The fundamental problem here is that you don't own the encoder MFT and you are accessing it over the writer's head, then the behavior of encoders around changing settings after everything is set up depends on implementation, which is in encoder's case a vendor specific implementation and might vary across hardware.

您更可靠的选择是直接管理MFT编码,并为Sink Writer提供已经编码的视频.

Your more reliable option is to manage encoding MFT directly and supply Sink Writer with already encoded video.

使工作轻松进行的潜在技巧是也检索编码器的IMFTransform并清除,然后在完成ICodecAPI更新后重新设置输入/输出媒体类型.忽略媒体类型,建议编码器重新配置内部结构,并且已经进行了微调.请注意,通常来说,这可能会有一些副作用.

Your potential trick to make things work with less of effort is to retrieve IMFTransform of the encoder as well and clear and then set back the input/output media types after you finished with ICodecAPI update. Nudging the media types, you suggest that encoder re-configures the internals and it would do this already having your fine tunings. Note that this, generally speaking, might have side issues.

技巧"似乎适用于某些ICodecAPI参数(例如,CODECAPIAPI_AVEncCommonQualityVsSpeed),并且仅适用于Microsoft的h.264编码器.对CODECAPI_AVEncH264CABACEn无效.该文档确实确实是专门针对Microsoft的编码器,而不是通用的API.我使用的是QuickSync和NVidia编解码器,如果我自己创建MFT,您知道它们是否可以通过ICodecAPI配置吗?

The 'trick' seems to work for some of the ICodecAPI parameters (e.g. CODECAPI_AVEncCommonQualityVsSpeed) and only for Microsoft's h.264 encoder. No effect on CODECAPI_AVEncH264CABACEnable. The doc indeed seems to be specifically for Microsoft's encoder and not be a generic API. I'm using the QuickSync and NVidia codecs, do you know if those are configurable via the ICodecAPI assuming I create the MFT myself?

供应商提供的编码器属于

Vendor provided encoders fall under Certified Hardware Encoder requirements, so they must support ICodecAPI values mentioned in the MSDN article. Important is that it is not defined what the order of configuration calls is. If you are managing encoder yourself you would do ICodecAPI setup before setting up media types. In Sink Writer scenario it already configured the media types, then you jump in with your fine tuning. Hence, my trick suggestion includes the part of resetting existing media types. Because this trick is sensitive to implementation details I would suggest to get current media types, then clear them on the MFT, do ICodecAPI thing and get the types back. I assume that this should work in greater number of scenarios, not just MS encoder. Yet it still remains an unreliable hack.

IMO Nvidia的编码器实现非常糟糕(各供应商之间最差),Intel的编码器更好,但仍然存在其自身的问题.同样,仅提供IMO MFT来满足硬件视频编码的最低认证要求,因此,它们的实现方式不完全一致.各种软件包都倾向于通过供应商SDK而不是Media Foundation Transform接口来实现视频编码.在其中一个项目中,我曾经跳过了利用MFT进行编码的想法,而是在供应商SDK之上实现了自己的MFT.

IMO Nvidia's encoder implementation is terrible (worst across vendors), Intel's is better but it still has its own issues. Again IMO the MFTs are only provided to meet minimal certification requirements for hardware video encoding and for this reason their implementation is not well aligned. Various software packages prefer to implement video encoding via vendor SDKs rather than Media Foundation Transform interface. In one of the projects I used to also skip the idea of leveraging MFTs for encoding, and implemented my own MFTs on top of vendor SDKs.

在这篇文章中,类工厂方法是否可以与IMFSinkWriter一起使用?这样可以避免编写过多的代码...

Would the class factory approach in this post work with the IMFSinkWriter? This would avoid writing too much code...

我想是的,即使我觉得以这种方式修补它不是一件令人愉快的工作,它也应该起作用.另外,您可能需要考虑对HW编码器的支持,因为Sink Writer在某些情况下也倾向于使用硬件辅助编码,包括使用DXGI设备的情况.

I suppose that yes, this should work even though I feel that it's not a pleasant work to patch it that way. Also you might need to take into account support of HW encoders because Sink Writer also tends to use hardware assisted encoding in some cases, including scenario where it's given a DXGI device.

另一种类似的黑客手段,但可能没有那么侵入(尽管在实施过程中,您必须对内部结构有更好的了解)是在Sink Writer初始化范围内重新定义供应商特定的编码器CLSID.只有三种编码器(AMD,Intel,Nvidia;好吧,上海兆鑫半导体公司有第四种编码器,但它并不是很受欢迎),并且它们的CLSID是已知的.如果您以聪明的方式CoRegisterClassObject,则可以挂钩MFT实例,让Media Foundation决定选择哪种编码器.不过,这只是另一个主意,因此它可能取决于其他因素的最佳处理方法.

Another sort of a hack, which is similar but maybe a bit less intrusive (although in its implementation you would have to have a better understanding of internals) is to redefine vendor specific encoder CLSIDs within Sink Writer initialization scope. There are just three encoders (AMD, Intel, Nvidia; okay there is fourth from Shanghai Zhaoxin Semiconductor but it is not really popular) and their CLSIDs are known. If you CoRegisterClassObject in a smart way, you could hook MFT instantiation letting Media Foundation to decide which encoder to choose. It is just another idea though, so it might depend what is the best to do on other factors.

这篇关于通过ICodecAPI为H.264 IMFSinkWriter编码器设置属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆