如何获取系统上可用的所有 Microsoft Media Foundation Transforms (MFT) 的列表

2024-02-25

我是 Windows 上本机开发的新手,但我的任务是创建一个小应用程序,该应用程序将列出各种视频+音频编解码器的所有转换器。

查看 MSDN 文档,似乎没有太多关于执行此操作的直接文档。我发现的文档表明此信息存储在注册表中(不确定在哪里),因此可能是一个向量。

  1. 这可能吗?
  2. 一般情况下我应该怎么做呢?

Thanks

EDIT:

看起来,使用 MFT_REGISTER_TYPE_INFO 类型的参数设置为 NULL 来调用 MFTEnumEx 会返回计数 8

MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER,MFT_ENUM_FLAG_ALL,NULL, NULL, &ppActivate, &count);
assert(count > 0);

但仍然必须获得实际值。但传递的 ppActivate 参数应包含它们的枚举。

EDIT:令人惊讶的是,虽然上面的计数 == 8,但没有视频或音频属性(视频/音频 IMFAttributes 对象为 NULL)

 IMFAttributes* videoAttributes = NULL;    
        if(SUCCEEDED(hr)){
            hr = pProfile->GetVideoAttributes(&videoAttributes);
            //If there are no container attributes set in the transcode profile, the GetVideoAttributes method succeeds and videoAttributes receives NULL.

        }
assert(videoAttributes != NULL);  //FAILS!

EDIT:

这是一种从机器中提取所有 IMFMediaTypes 的方法(修改了书中的调用开发 Microsoft® Media Foundation 应用程序 https://rads.stackoverflow.com/amzn/click/com/B005WZ0SJ6);然后我在调用者中枚举它们:

HRESULT CTranscoder::GetVideoOutputAvailableTypes(
    DWORD flags, 
    CComPtr<IMFCollection>& pTypeCollection)
{
    HRESULT hr = S_OK;
    IMFActivate** pActivateArray = NULL;
    MFT_REGISTER_TYPE_INFO outputType;
    UINT32 nMftsFound = 0;

    do
    {
        // create the collection in which we will return the types found
        hr = MFCreateCollection(&pTypeCollection);
        BREAK_ON_FAIL(hr);

        // initialize the structure that describes the output streams that the encoders must
        // be able to produce.  In this case we want video encoders - so major type is video, 
        // and we want the specified subtype
        outputType.guidMajorType = MFMediaType_Video;
        outputType.guidSubtype = MFVideoFormat_WMV3;

        // get a collection of MFTs that fit the requested pattern - video encoders,
        // with the specified subtype, and using the specified search flags
        hr = MFTEnumEx(
            MFT_CATEGORY_VIDEO_ENCODER,         // type of object to find - video encoders
            flags,                              // search flags
            NULL,                               // match all input types for an encoder
            &outputType,                        // get encoders with specified output type
            &pActivateArray,
            &nMftsFound);
        BREAK_ON_FAIL(hr);

        // now that we have an array of activation objects for matching MFTs, loop through 
        // each of those MFTs, extracting all possible and available formats from each of them
        for(UINT32 x = 0; x < nMftsFound; x++)
        {
            CComPtr<IMFTransform> pEncoder;
            UINT32 typeIndex = 0;

            // activate the encoder that corresponds to the activation object
            hr = pActivateArray[x]->ActivateObject(IID_IMFTransform, 
                (void**)&pEncoder);

            // while we don't have a failure, get each available output type for the MFT 
            // encoder we keep looping until there are no more available types.  If there 
            // are no more types for the encoder, IMFTransform::GetOutputAvailableTypes[] 
            // will return MF_E_NO_MORE_TYPES
            while(SUCCEEDED(hr))
            {
                IMFMediaType* pType;

                // get the avilable type for the type index, and increment the typeIndex 
                // counter
                hr = pEncoder->GetOutputAvailableType(0, typeIndex++, &pType);
                if(SUCCEEDED(hr))
                {
                    // store the type in the IMFCollection
                    hr = pTypeCollection->AddElement(pType);
                }
            }
        }
    } while(false);

    // possible valid errors that may be returned after the previous for loop is done
    if(hr == MF_E_NO_MORE_TYPES  ||  hr == MF_E_TRANSFORM_TYPE_NOT_SET)
        hr = S_OK;

    // if we successfully used MFTEnumEx() to allocate an array of the MFT activation 
    // objects, then it is our responsibility to release each one and free up the memory 
    // used by the array
    if(pActivateArray != NULL)
    {
        // release the individual activation objects
        for(UINT32 x = 0; x < nMftsFound; x++)
        {
            if(pActivateArray[x] != NULL)
                pActivateArray[x]->Release();
        }

        // free the memory used by the array
        CoTaskMemFree(pActivateArray);
        pActivateArray = NULL;
    }

    return hr;
}

Caller:

    hr=transcoder.GetVideoOutputAvailableTypes( MFT_ENUM_FLAG_ALL, availableTypes);
    if (FAILED(hr)){
        wprintf_s(L"didn't like the printVideoProfiles method");
    }

    DWORD availableInputTypeCount =0;
    if(SUCCEEDED(hr)){
        hr= availableTypes->GetElementCount(&availableInputTypeCount);
    }
    for(DWORD i = 0; i< availableInputTypeCount  && SUCCEEDED(hr); i++)
    {

        //really a IMFMediaType*
        IMFAttributes* mediaInterface = NULL;
            if(SUCCEEDED(hr)){
                hr = availableTypes->GetElement(i, (IUnknown**)&mediaInterface) ;}

            if(SUCCEEDED(hr)){ 
                //see http://msdn.microsoft.com/en-us/library/aa376629(v=VS.85).aspx for a list of attributes to pull off the media interface.

                GUID majorType;
                hr = mediaInterface->GetGUID(MF_MT_MAJOR_TYPE, &majorType);
                LPOLESTR majorGuidString = NULL;
                hr = StringFromCLSID(majorType,&majorGuidString);
                wprintf_s(L"major type: %s \n", majorGuidString);
                wprintf_s(L"is a video? %i \n", IsEqualGUID(MFMediaType_Video,majorType));

                GUID subType;
                if(SUCCEEDED(mediaInterface->GetGUID(MF_MT_SUBTYPE, &subType))){
                    LPOLESTR minorGuidString = NULL;
                    if(SUCCEEDED(StringFromCLSID(subType,&minorGuidString)))
                        wprintf_s(L"subtype: %s \n", minorGuidString);
                }

                //Contains a DirectShow format GUID for a media type: http://msdn.microsoft.com/en-us/library/dd373477(v=VS.85).aspx
                GUID formatType;
                if(SUCCEEDED(mediaInterface->GetGUID(MF_MT_AM_FORMAT_TYPE, &formatType))){
                    LPOLESTR formatTypeString = NULL;
                    if(SUCCEEDED(StringFromCLSID(formatType,&formatTypeString)))
                        wprintf_s(L"format type: %s \n", formatTypeString);
                }

                UINT32 numeratorFrameRate = 0;
                UINT32 denominatorFrameRate = 0;
                if(SUCCEEDED(MFGetAttributeRatio(mediaInterface, MF_MT_FRAME_RATE, &numeratorFrameRate, &denominatorFrameRate)))
                    wprintf_s(L"framerate: %i/%i \n", numeratorFrameRate, denominatorFrameRate);

                UINT32 widthOfFrame = 0;
                UINT32 heightOfFrame = 0;
                if(SUCCEEDED(MFGetAttributeSize(mediaInterface, MF_MT_FRAME_SIZE, &widthOfFrame, &heightOfFrame)))
                    wprintf_s(L"height of frame: %i width of frame: %i \n", heightOfFrame, widthOfFrame);

                UINT32 isCompressedP = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_COMPRESSED, &isCompressedP)))
                    wprintf_s(L"is media compressed? %iu \n", (BOOL)isCompressedP);

                BOOL isCompressedP2 = 0;
                if(SUCCEEDED((((IMFMediaType*)mediaInterface)->IsCompressedFormat(&isCompressedP2))))
                    wprintf_s(L"is media compressed2? %i \n", isCompressedP2);

                UINT32 fixedSampleSizeP = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_FIXED_SIZE_SAMPLES, &fixedSampleSizeP)))
                    wprintf_s(L"is fixed sample size? %iu \n", fixedSampleSizeP);

                UINT32 sampleSize = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_SAMPLE_SIZE, &sampleSize)))
                    wprintf_s(L"sample size: %iu \n", sampleSize);

                UINT32 averateBitrate = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_AVG_BITRATE, &averateBitrate)))
                    wprintf_s(L"average bitrate: %iu \n", averateBitrate);

                UINT32 aspectRatio = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_PAD_CONTROL_FLAGS, &aspectRatio)))
                    wprintf_s(L"4 by 3? %i  16 by 9? %i None? %i \n", aspectRatio == MFVideoPadFlag_PAD_TO_4x3, MFVideoPadFlag_PAD_TO_16x9 == aspectRatio, MFVideoPadFlag_PAD_TO_None == aspectRatio);

                UINT32 drmFlag = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_DRM_FLAGS, &drmFlag)))
                    wprintf_s(L"requires digital drm: %i requires analog drm: %i  requires no drm: %i", drmFlag == MFVideoDRMFlag_DigitallyProtected, drmFlag == MFVideoDRMFlag_AnalogProtected, MFVideoDRMFlag_None == drmFlag);

                UINT32 panScanEnabled = 0;
                if(SUCCEEDED(mediaInterface->GetUINT32(MF_MT_PAN_SCAN_ENABLED, &panScanEnabled)))
                    wprintf_s(L"pan/scan enabled? %i", panScanEnabled);

                UINT32 maxFrameRateNumerator = 0;
                UINT32 maxFrameRateDenominator = 0;
                if(SUCCEEDED(MFGetAttributeRatio(mediaInterface, MF_MT_FRAME_RATE_RANGE_MAX, &maxFrameRateNumerator, &maxFrameRateDenominator)))
                    wprintf_s(L"max framerate range: %i/%i \n", maxFrameRateNumerator, maxFrameRateDenominator);

            }

    }

它从 IMFMediaInterface 获取一些属性,但设置的属性并不多 打电话给mediaInterface->GetUINT32(MF_MT_COMPRESSED, &isCompressedP)未成功,但调用(IMFMediaType*)mediaInterface)->IsCompressedFormat(&isCompressedP2)是的,这让我想知道我是否做错了。


这是一个老问题,但任何人都不应得不到答案。

正如你发现的那样,MFTEnumEx可以给你清单MFTs,可以是批量列表,也可以是使用条件过滤。现在一旦你有了变换的集合,你就拥有了IMFActivate对于每个可用的变换。

Having IMFActivate在手上,看到这段代码片段 http://www.alax.info/trac/public/browser/trunk/Utilities/MediaFoundation/EnumerateTransforms/EnumerateTransforms.cpp#L136如何获取有关此转换的信息:您列出属性或使用其键访问感兴趣的属性,您可以获得类别、输入和输出媒体类型(MFT_INPUT_TYPES_Attributes, MFT_OUTPUT_TYPES_Attributes).

以下是示例代码和 MFT 转储示例:

  • 如何枚举系统上的 Media Foundation 转换 https://matthewvaneerde.wordpress.com/2010/05/03/how-to-enumerate-media-foundation-transforms-on-your-system/
  • 枚举媒体基础转换 (MFT) http://alax.info/blog/1375
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何获取系统上可用的所有 Microsoft Media Foundation Transforms (MFT) 的列表 的相关文章

随机推荐