如何获取系统上可用的所有 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->GetUINT32(MF_MT_COMPRESSED, &isCompressedP)
的调用不成功,但对(IMFMediaType*)mediaInterface)->IsCompressedFormat(&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 媒体服务解决方案