如何获取系统上可用的所有 Microsoft 媒体基础转换 (MFT) 的列表

Posted

技术标签:

【中文标题】如何获取系统上可用的所有 Microsoft 媒体基础转换 (MFT) 的列表【英文标题】:How to get a list of all Microsoft Media Foundation Transforms (MFTs) available on a system 【发布时间】:2011-11-01 15:11:29 【问题描述】:

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

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

    这可能吗? 一般应该怎么做?

谢谢

编辑:

似乎调用 MFTEnumEx 并将 MFT_REGISTER_TYPE_INFO 类型的参数设置为 NULL 返回计数为 8

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

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

编辑: 令人惊讶的是,虽然上面的计数 == 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!

编辑:

这是一种从机器中提取所有 IMFMediaTypes 的方法(修改后的调用来自书 Developing Microsoft® Media Foundation Applications);然后我在调用者中枚举它们:

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;

来电者:

    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-&gt;GetUINT32(MF_MT_COMPRESSED, &amp;isCompressedP) 的调用不成功,但对(IMFMediaType*)mediaInterface)-&gt;IsCompressedFormat(&amp;isCompressedP2) 的调用成功,这让我怀疑我是否做错了。

【问题讨论】:

【参考方案1】:

这是一个古老的问题,但没有人应该在没有答案的情况下离开。

正如您所发现的,MFTEnumEx 可以为您提供MFTs 的列表,可以是批量列表,也可以是使用标准过滤的列表。现在,一旦您拥有了转换集合,您就可以为每个可用的转换提供IMFActivate

手头有IMFActivate,请参阅this code snippet如何获取有关此转换的信息:您列出属性或使用其键访问感兴趣的属性,您可以获得类别、输入和输出媒体类型(MFT_INPUT_TYPES_Attributes , MFT_OUTPUT_TYPES_Attributes)。

这里是示例代码和 MFT 转储示例:

How to enumerate Media Foundation transforms on your system Enumerating Media Foundation Transforms (MFTs)

【讨论】:

以上是关于如何获取系统上可用的所有 Microsoft 媒体基础转换 (MFT) 的列表的主要内容,如果未能解决你的问题,请参考以下文章

如何获取可用系统内存的大小?

microsoft azure Media Services 媒体服务解决方案

8.1.1 获取系统上可用的摄像头信息

如何获取 iOS 系统设置中列出的所有可用声音文件

使用 java,如何获取 solaris zfs 文件系统上的可用空间量?

如何获取 QMediaPlaylist 中所有媒体的元数据?