本文介绍了如何获取系统上可用的所有 Microsoft Media Foundation Transforms (MFT) 的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm a newbie to native development on Windows, but I've been tasked with creating a small app that will list out all the transformers for various video+audio codecs.

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

Looking at the MSDN documentation, there doesn't seem to be much direct documentation on doing this. Docs that I've found indicate that this information is stored in the registry (not sure where) so that could be a vector.

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

谢谢

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

It does seem that a call to MFTEnumEx with the parameters of type MFT_REGISTER_TYPE_INFO set to NULL returns a count of 8

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

尽管如此,仍然必须获得实际值.但是传递的 ppActivate 参数应该包含它们的枚举.

Still have to get the actual values though. But the passed ppActivate param should contain an enumeration of them.

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

It's surprising, but while the count above == 8, there are no video or audio attributes(the video/audio IMFAttributes object is 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 的方法(修改后的调用来自书中 开发 Microsoft® Media Foundation 应用程序);然后我在调用者中枚举它们:

This is a method that pulls all the IMFMediaTypes from the machine(modified call from the book Developing Microsoft® Media Foundation Applications); I then enumerate over them in the caller:

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->GetUINT32(MF_MT_COMPRESSED, &isCompressedP) 不成功,但调用 (IMFMediaType*)mediaInterface)->IsCompressedFormat(&isCompressedP2)code> 是,这让我怀疑是不是我做错了.

It's getting some attributes from the IMFMediaInterface, but not many attributes are set and the call to mediaInterface->GetUINT32(MF_MT_COMPRESSED, &isCompressedP) isn't successful but the call to (IMFMediaType*)mediaInterface)->IsCompressedFormat(&isCompressedP2) is, which makes me wonder if I'm doing it wrong.

推荐答案

这是一个古老的问题,但没有人应该不回答就离开.

This is an old question, but noone should go away unanswered.

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

As you discovered, MFTEnumEx can give you the list of MFTs, either bulk list, or filtered with a criteria. Now once you have the collection of transforms, you have IMFActivate for every transform available.

拥有 IMFActivate,请参阅 此代码片段 如何获取有关此转换的信息:使用其键列出感兴趣的属性或访问属性,可以获得类别、输入和输出媒体类型(MFT_INPUT_TYPES_Attributes, MFT_OUTPUT_TYPES_Attributes).

Having IMFActivate on hands, see this code snippet how you can obtain information about this transform: you list attributes or access attribute of interest using its key, you can obtain the category, input and output media types (MFT_INPUT_TYPES_Attributes, MFT_OUTPUT_TYPES_Attributes).

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

Here is sample code and MFT dump samples:

这篇关于如何获取系统上可用的所有 Microsoft Media Foundation Transforms (MFT) 的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-04 22:51