从 SinkWriter 或 ICodecAPI 或 IMFTransform 获取编码器名称

Posted

技术标签:

【中文标题】从 SinkWriter 或 ICodecAPI 或 IMFTransform 获取编码器名称【英文标题】:Get encoder name from SinkWriter or ICodecAPI or IMFTransform 【发布时间】:2014-01-06 09:07:07 【问题描述】:

我正在使用 SinkWriter 以便使用媒体基础对视频进行编码。

初始化 SinkWriter 后,我想获取它使用的底层编码器,并打印出它的名称,这样我就可以看到它使用的编码器。 (就我而言,编码器很可能是 MF 中包含的H.264 Video Encoder)。

我可以获得对编码器的 ICodecAPI 和 IMFTransform 接口的引用(使用 pSinkWriter->GetServiceForStream),但我不知道如何使用这些接口获取编码器的友好名称。

有谁知道如何从 sinkwriter 获取编码器的友好名称?还是从它的ICodecAPIIMFTransform 接口?

【问题讨论】:

还没有人找到对此的回应?这似乎是一件非常基本的事情,至少 GUID 会有所帮助。 【参考方案1】:

到目前为止,这是一个有效的解决方案,我不能 100% 确定它是否有效,但可以做的是:

1)在启动时枚举所有可以使用的编解码器(我理解在这种情况下是 H264 编码器)并订阅设置更改事件

MFT_REGISTER_TYPE_INFO TransformationOutput =  MFMediaType_Video, MFVideoFormat_H264 ;
DWORD nFlags = MFT_ENUM_FLAG_ALL;
UINT32 nCount = 0;
CLSID* pClsids;
MFTEnum( MFT_CATEGORY_VIDEO_ENCODER, nFlags, NULL, &TransformationOutput, NULL, &pClsids, &nCount);
// Ok here we assume nCount is 1 and we got the MS encoder
ICodecAPI *pMsEncoder;
hr = CoCreateInstance(pClsids[0], NULL, CLSCTX_INPROC_SERVER, __uuidof(ICodecAPI), (void**)&pMsEncoder);
// nCodecIds is supposed to be an array of identifiers to distinguish the sender
hr = pMsEncoder->RegisterForEvent(CODECAPI_AVEncVideoOutputFrameRate, (LONG_PTR)&nCodecIds[0]);

2) 不能 100% 确定在设置流的输入媒体类型时是否还设置了帧速率设置,但无论如何您可以尝试在从 SinkWriter 检索到的 ICodecAPI 上设置相同的属性.然后在获得事件后,您应该能够通过将lParam1 与传递的值进行比较来识别编解码器。但这仍然很糟糕,因为它依赖于所有编码器都支持事件通知这一事实,并且如果我对流构建时生成的事件的假设是错误的,则需要更改不必要的参数。

【讨论】:

【参考方案2】:

拥有IMFTransform 您没有编码器的友好名称。

您有一个选项是检查转换输出类型并与众所周知的 GUID 进行比较以识别编码器,特别是您将拥有一个带有 H264 编码器 MFT 的 MFVideoFormat_H264 子类型。

另一种选择是到达编码器的CLSIDIMFTransform 无法获得它,但您可能会获得它,例如通过IMFActivate 或查询MFT_TRANSFORM_CLSID_Attribute 属性,或通过IPersist* 接口) .然后,您可以在注册表中查找友好名称或枚举转换,并通过比较 CLSID 在该列表中查找您的转换。

【讨论】:

MS H.264 视频编码器没有实现IPersist,并且不支持属性(->GetAttributes() 返回 E_NOTIMPL)。此外,SinkWriter 枚举并创建编码器,因此我无法访问 IMFActivate 对象。编码器实现的唯一两个接口是ICodecAPIIMFTransform,看起来我无法从它们中的任何一个中获取名称。 这是真的。它并非旨在使此信息可从 IMFTransform 向后访问。很难说为什么,添加对IPersist 的支持将是一件简单而有效的事情。每当我需要进行转换时,我肯定会在那里进行转换,但是库存过滤器就这样......对开发人员不太友好。

以上是关于从 SinkWriter 或 ICodecAPI 或 IMFTransform 获取编码器名称的主要内容,如果未能解决你的问题,请参考以下文章

媒体基础 SinkWriter (MP4 FastStart)

MF SinkWriter 写入样本失败

如何将音频添加到使用 SinkWriter 创建的 mp4 文件中?

MF SinkWriter mp4 文件的播放持续时间是添加音频样本时的一半时间,图像的播放速度也快两倍

优化 h264 MediaFoundation 编码

IMFMediaSink,如何设置编码器属性?