int mf_decoder_init(IMFTransform **transform, GUID audio_format) { HRESULT hr = S_OK; MFT_REGISTER_TYPE_INFO reg = { 0 }; GUID category = MFT_CATEGORY_AUDIO_DECODER; IMFActivate **activate; UINT32 num_activate; reg.guidMajorType = MFMediaType_Audio; reg.guidSubtype = audio_format; hr = MFTEnumEx(category, MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER, ®, NULL, &activate, &num_activate); if (FAILED(hr) || num_activate < 1) { ReportError(L"Failed to enumerate decoders", hr); CoTaskMemFree(activate); return -1; } std::cout << "Found " << num_activate << " decoder(s)" << std::endl; for (unsigned int n = 0; n < num_activate; n++) { hr = activate[n]->ActivateObject(IID_IMFTransform, (void**)transform); if (FAILED(hr)) *transform = NULL; activate[n]->Release(); } if (*transform == NULL) { ReportError(L"Failed to initialize MFT", hr); CoTaskMemFree(activate); return -1; } CoTaskMemFree(activate); return 0; }
MediaFoundationTransform *MediaFoundationTransform::LoadWmaEncoderTransform(WmaEncodingFormat encodingFormat) { MediaFoundationTransform *result = nullptr; UINT32 transformCount; IMFActivate **transformActivationObjs; MFT_REGISTER_TYPE_INFO typeInfo; typeInfo.guidMajorType = MFMediaType_Audio; typeInfo.guidSubtype = (encodingFormat == WmaEncodingFormat::Lossless) ? MFAudioFormat_WMAudio_Lossless : MFAudioFormat_WMAudioV8; HRESULT hr = MFTEnumEx(MFT_CATEGORY_AUDIO_ENCODER, MFT_ENUM_FLAG_TRANSCODE_ONLY, nullptr, &typeInfo, &transformActivationObjs, &transformCount); // early out if return code is bad or no transforms found if ((hr != S_OK) || (transformCount < 1)) return nullptr; // Regardless how many activation objects returned, just instantiate the first one // (would I want to instantiate another? Why? Which one?) result = new MediaFoundationTransform(*transformActivationObjs, encodingFormat); // release all the stupid activation pointers (because COM was such a GREAT idea) for (UINT32 i = 0; i < transformCount; i++) { IMFActivate *temp = *(transformActivationObjs + i); temp->Release(); } // free the stupid activation array object (because COM was such an f'ing great idea) // (did I ever mention I think COM was just... stupid?) CoTaskMemFree(transformActivationObjs); return result; }
void print_mft_(const GUID& guid, std::wfstream& out, uint32_t flags = MFT_ENUM_FLAG_ALL) { co_task_memory<IMFActivate*> activate; UINT32 count = 0; HRESULT hr = MFTEnumEx(guid, flags, NULL, NULL, &activate, &count); if (SUCCEEDED(hr) && count > 0) { for (int i = 0; i < count; ++i) { UINT32 l = 0; UINT32 l1 = 0; activate.get()[i]->GetStringLength(MFT_FRIENDLY_NAME_Attribute, &l); std::unique_ptr<wchar_t[]> name(new wchar_t[l + 1]); memset(name.get(), 0, l + 1); hr = activate.get()[i]->GetString(MFT_FRIENDLY_NAME_Attribute, name.get(), l + 1, &l1); out << name.get() << std::endl; activate.get()[i]->Release(); } //CoTaskMemFree(activate); } }
std::unique_ptr<MediaFoundation_DecompresserTransform> MediaFoundation_DecompresserTransform::getInstance(int width, int height, PixelFormat inputPixelFormat, PixelFormat outputPixelFormat, RESULT &result) { CComPtr<IMFTransform> transform; GUID inputSubtype; bool ok = MediaFoundation_Utils::pixelFormatToVideoFormat(inputPixelFormat, inputSubtype); if (!ok) { result = RESULT::UNSUPPORTED_INPUT; return nullptr; } GUID outputSubtype; ok = MediaFoundation_Utils::pixelFormatToVideoFormat(outputPixelFormat, outputSubtype); if (!ok) { result = RESULT::UNSUPPORTED_OUTPUT_FOR_INPUT; return nullptr; } MFT_REGISTER_TYPE_INFO inputFilter = {MFMediaType_Video, inputSubtype}; MFT_REGISTER_TYPE_INFO outputFilter = {MFMediaType_Video, outputSubtype}; IMFActivate **activateArr; UINT32 activateCount; // TODO(nurupo): maybe prioritize hardware decoders first? HRESULT hr = MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, MFT_ENUM_FLAG_ALL, &inputFilter, &outputFilter, &activateArr, &activateCount); if (FAILED(hr) || activateCount < 1) { DEBUG_PRINT_HR_ERROR("Couldn't find an appropriate transform.", hr); CoTaskMemFree(activateArr); // check whether it's RESULT::UNSUPPORTED_INPUT or RESULT::UNSUPPORTED_OUTPUT_FOR_INPUT hr = MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, MFT_ENUM_FLAG_ALL, &inputFilter, nullptr, &activateArr, &activateCount); if (FAILED(hr) || activateCount < 1) { // there is no transform for such input result = RESULT::UNSUPPORTED_INPUT; } else { // there is some transform for this input, but not this output for (UINT32 i = 0; i < activateCount; i ++) { activateArr[i]->Release(); } result = RESULT::UNSUPPORTED_OUTPUT_FOR_INPUT; } CoTaskMemFree(activateArr); return nullptr; } // release all but 1st transform for (UINT32 i = 1; i < activateCount; i ++) { activateArr[i]->Release(); } // Activate 1st transform IMFActivate *activate = activateArr[0]; CoTaskMemFree(activateArr); hr = activate->ActivateObject(IID_PPV_ARGS(&transform)); if (FAILED(hr)) { DEBUG_PRINT_HR_ERROR("Couldn't activate a transform.", hr); activate->Release(); result = RESULT::FAILURE; return nullptr; } std::unique_ptr<MediaFoundation_PixelFormatTransform> pixelFormatTransform = MediaFoundation_PixelFormatTransform::getInstance(transform, width, height, inputPixelFormat, outputPixelFormat, result); if (result != RESULT::OK) { activate->ShutdownObject(); return nullptr; } result = RESULT::OK; return std::unique_ptr<MediaFoundation_DecompresserTransform>(new MediaFoundation_DecompresserTransform(pixelFormatTransform, activate)); }