【问题标题】:UWP, Media Foundation, choosing specific encoderUWP,媒体基金会,选择特定编码器
【发布时间】:2017-11-03 09:09:24
【问题描述】:

我想在 UWP 下的 Media Foundation 中使用 c++/cx 选择一个特定的编码器。目前我使用 SinkWriter 并让系统选择默认编码器。

此代码在 UWP 下返回“类未注册”错误,但在 win32 控制台应用程序中有效:

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
MFStartup(MF_VERSION);
IMFTransform* mtf;
CLSID id;
CLSIDFromString(L"{966F107C-8EA2-425D-B822-E4A71BEF01D7}", &id);    // "NVIDIA HEVC Encoder MFT"
//CLSIDFromString(L"{F2F84074-8BCA-40BD-9159-E880F673DD3B}", &id);  // "H265 Encoder MFT"
//CLSIDFromString(L"{BC10864D-2B34-408F-912A-102B1B867B6C}", &id);  // "Intel« Hardware H265 Encoder MFT"
//HRESULT hr = CoCreateInstance(id, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (void **)&mtf);
HRESULT hr = CoCreateInstance(id, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&mtf));

我还注意到 UWP 下的头文件中没有定义 MFTEnumEx(),所以我无法枚举编码器。

我注意到有 C# 文档允许这样的内容:

auto codecQuery = ref new Windows::Media::Core::CodecQuery();

但是使用 c++/cx 时好像不可用。

我还想问一下 SinkWriter 它实际选择了什么编码器,但是这段代码不起作用,因为 ICodecAPI 未定义:

IMFTransform* pEncoder = NULL;
mWriter->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, GUID_NULL, IID_IMFTransform, (void**)&pEncoder);
if (pEncoder)
{
    ICodecAPI* pCodecApi = NULL;
    hr = pEncoder->QueryInterface<ICodecAPI>(&pCodecApi);
}

请帮我选择编码器或找出选择了哪个编码器?

【问题讨论】:

    标签: c++ video encoding uwp ms-media-foundation


    【解决方案1】:

    Media Foundation 不提供使用 Sink Writer API 指定编码器的灵活性。你只能指示使用或不使用硬件编码器,使用MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS attribute

    使源读取器或接收器写入器能够使用基于硬件的媒体基础转换 (MFT)。

    一旦设置了 Sink Writer,您就可以使用 IMFSinkWriterEx::GetTransformForStream 枚举 API 为处理准备的转换,并从枚举中选择编码器。这将使您了解实际使用的编码器。

    Media Foundation Sink Writer API 保留解码要使用的编码器的权利。通常情况下,如果您更喜欢经过认证的兼容编码器,尤其是在您启用 Direct3D 方案的情况下。

    最后,我不确定其中哪些可用于 C++/CX,但您的代码 sn-ps 表明上述 API 可用。

    要使用您选择的编码器,您应该使用 Media Foundation Media Session API,而不是 Sink Writer。

    【讨论】:

    • 关于媒体会话 API,然后 MFTRegister() 似乎不可用。我需要制作一个自定义 IMFTransform 来处理视频。也是文件读取器和写入器。必须专门选择编码器。所以这对我来说似乎是不可能的?
    • 您无法选择带有 Sink Writer 的显式编码器。只有两个选项:最合适的编码器(通常是硬件编码器)和最合适的非硬件编码器(通常解析为 MS 软件编码器)。你从两者中选择。如果您不满意,您可以使用 Media Session API,或者管理您需要自己将已经压缩的数据提供给 Sink Writer 的编码器。我看不出MFTRegister 与此处有何关联,您通常不会将它用于此任务。
    • MFCreateMediaSession() 不可用,这篇文章表明媒体会话 API 在 UWP 下根本不可用:stackoverflow.com/questions/47059898/…
    • 好吧,媒体会话不是一个选项,你还有另一个,不是吗?好吧,实际上这可能并不像听起来那么容易(实例化 MFT 并路由流量,然后将其转发给 Sink Writer),但它可能仍然是一个可行的选择。
    【解决方案2】:

    谢谢罗曼。我试过GetTranformForStream。使用 nvidia 驱动程序,我得到了 IMFTransform 的属性:

    {206B4FC8-FCF9-4C51-AFE3-9764369E33A0}=1,
    {2FB866AC-B078-4942-AB6C-003D05CDA674}=NVIDIA HEVC Encoder MFT,
    FRIENDLY_NAME_Attribute=NVIDIA HEVC Encoder MFT,
    {3AECB0CC-035B-4BCC-8185-2B8D551EF3AF}=VEN_10DE,
    MAJOR_TYPE=Video,
    {53476A11-3F13-49FB-AC42-EE2733C96741}=1,
    {86A355AE-3A77-4EC4-9F31-01149A4E92DE}=1,
    {88A7CB15-7B07-4A34-9128-E64C6703C4D3}=8,
    {E3F2E203-D445-4B8C-9211-AE390D3BA017}=2303214,
    {E5666D6B-3422-4EB6-A421-DA7DB1F8E207}=1,
    {F34B9093-05E0-4B16-993D-3E2A2CDE6AD3}=860522,
    SUBTYPE=Base,
    {F81A699A-649A-497D-8C73-29F8FED6AD7A}=1,
    

    当禁用 nvidia 驱动时,我只得到:

    {86A355AE-3A77-4EC4-9F31-01149A4E92DE}=1
    

    我想知道最后一个转换是否是几个转换的列表?如何得到它们?我可以从 sinkwriter 遍历拓扑吗?

    我的电脑有以下我可以使用的编解码器:

    {966F107C-8EA2-425D-B822-E4A71BEF01D7}   // "NVIDIA HEVC Encoder MFT"
    {F2F84074-8BCA-40BD-9159-E880F673DD3B} // "H265 Encoder MFT"
    {BC10864D-2B34-408F-912A-102B1B867B6C} // "Intel« Hardware H265 Encoder MFT"
    

    在 nvidia 的情况下,我得到了一个有意义的字符串,但当它显然不是 nvidia(英特尔或软件)时却没有。

    现在我也会按照您的建议尝试查看 Media Session API。

    【讨论】:

      猜你喜欢
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多