Bug 1866265 - part6 : if no compatible type, check preferred type, then the last available type as final fallback. r=media-playback-reviewers,jolin

When running hevc test on the try server, the MFT on the try server has
MFVideoFormat_NV12 and MFVideoFormat_IYUV on its list. If we choose last
available type, it would be MFVideoFormat_IYUV, causing 10-bit hevc
failed to play on the try server.

As we know what format is usually used for video and audio, we should
use the preferred type first if we can't find the compatible type. If
none of them are found, then the last available type should be used as
a final fallback option.

Differential Revision: https://phabricator.services.mozilla.com/D223652
This commit is contained in:
alwu 2024-09-26 19:39:24 +00:00
parent 6796c20612
commit fb69105575
2 changed files with 52 additions and 12 deletions

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MFTDecoder.h"
#include "WMFUtils.h"
#include "mozilla/Logging.h"
#include "nsThreadUtils.h"
@ -46,24 +47,24 @@ MFTDecoder::Create(const GUID& aCategory, const GUID& aInSubtype,
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
// Use video by default, but select audio if necessary.
const GUID major = aCategory == MFT_CATEGORY_AUDIO_DECODER
? MFMediaType_Audio
: MFMediaType_Video;
mMajorType = aCategory == MFT_CATEGORY_AUDIO_DECODER ? MFMediaType_Audio
: MFMediaType_Video;
// Ignore null GUIDs to allow searching for all decoders supporting
// just one input or output type.
auto createInfo = [&major](const GUID& subtype) -> MFT_REGISTER_TYPE_INFO* {
auto createInfo = [](const GUID& majortype,
const GUID& subtype) -> MFT_REGISTER_TYPE_INFO* {
if (IsEqualGUID(subtype, GUID_NULL)) {
return nullptr;
}
MFT_REGISTER_TYPE_INFO* info = new MFT_REGISTER_TYPE_INFO();
info->guidMajorType = major;
info->guidMajorType = majortype;
info->guidSubtype = subtype;
return info;
};
const MFT_REGISTER_TYPE_INFO* inInfo = createInfo(aInSubtype);
const MFT_REGISTER_TYPE_INFO* outInfo = createInfo(aOutSubtype);
const MFT_REGISTER_TYPE_INFO* inInfo = createInfo(mMajorType, aInSubtype);
const MFT_REGISTER_TYPE_INFO* outInfo = createInfo(mMajorType, aOutSubtype);
// Request a decoder from the Windows API.
HRESULT hr;
@ -173,7 +174,12 @@ MFTDecoder::SetDecoderOutputType(
// type as fallback type.
RefPtr<IMFMediaType> outputType, lastOutputType;
GUID lastOutputSubtype;
bool foundCompatibleType = false;
enum class Result : uint8_t {
eNotFound,
eFoundCompatibleType,
eFoundPreferredType,
};
Result foundType = Result::eNotFound;
UINT32 typeIndex = 0;
while (SUCCEEDED(mDecoder->GetOutputAvailableType(
0, typeIndex++, getter_AddRefs(outputType)))) {
@ -184,21 +190,52 @@ MFTDecoder::SetDecoderOutputType(
lastOutputType = outputType;
lastOutputSubtype = outSubtype;
if (aSubType == outSubtype) {
foundCompatibleType = true;
foundType = Result::eFoundCompatibleType;
break;
}
outputType = nullptr;
}
if (foundType == Result::eNotFound) {
typeIndex = 0;
LOG("Can't find a compatible output type, searching with the preferred "
"type instead");
auto getPreferredSubtype = [](const GUID& aMajor) -> GUID {
if (aMajor == MFMediaType_Audio) {
return MFAudioFormat_Float;
}
return MFVideoFormat_NV12;
};
const GUID preferredSubtype = getPreferredSubtype(mMajorType);
while (SUCCEEDED(mDecoder->GetOutputAvailableType(
0, typeIndex++, getter_AddRefs(outputType)))) {
GUID outSubtype = {0};
RETURN_IF_FAILED(outputType->GetGUID(MF_MT_SUBTYPE, &outSubtype));
LOGV("Searching preferred type, input=%s, output=%s",
GetSubTypeStr(preferredSubtype).get(),
GetSubTypeStr(outSubtype).get());
lastOutputType = outputType;
lastOutputSubtype = outSubtype;
if (preferredSubtype == outSubtype) {
foundType = Result::eFoundPreferredType;
break;
}
outputType = nullptr;
}
}
if (!lastOutputType) {
LOG("No available output type!");
return E_FAIL;
}
if (foundCompatibleType ) {
LOG("Found compatible type %s", GetSubTypeStr(aSubType).get());
if (foundType != Result::eNotFound) {
LOG("Found %s type %s",
foundType == Result::eFoundCompatibleType ? "compatible" : "preferred",
GetSubTypeStr(lastOutputSubtype).get());
} else {
LOG("Can't find a compatible output type, use the last available type %s",
LOG("Can't find compatible and preferred type, use the last available type "
"%s",
GetSubTypeStr(lastOutputSubtype).get());
}
RETURN_IF_FAILED(aCallback(lastOutputType));

View File

@ -120,6 +120,9 @@ class MFTDecoder final {
RefPtr<IMFMediaType> mOutputType;
GUID mOutputSubType;
// Either MFMediaType_Audio or MFMediaType_Video.
GUID mMajorType;
// True if the IMFTransform allocates the samples that it returns.
bool mMFTProvidesOutputSamples = false;