Bug 1652945 - Added support for the Windows Media Foundation AV1 decoder for hardware decoding. r=alwu

The method of creating decoder MFTs was replaced with MFEnumEx queries in order to get an instance of the AV1 decoder.

Differential Revision: https://phabricator.services.mozilla.com/D138884
This commit is contained in:
Zaggy1024 2022-03-17 20:39:51 +00:00
Родитель 7cde443dc0
Коммит b2ffa025f0
11 изменённых файлов: 215 добавлений и 98 удалений

Просмотреть файл

@ -239,6 +239,26 @@ static const GUID DXVA2_Intel_ModeH264_E = {
0x4c54,
{0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6}};
// VP8, VP9 and AV1 from:
// https://docs.microsoft.com/en-us/windows/win32/medfound/direct3d-12-video-guids
static const GUID DXVA2_ModeVP8_VLD = {
0x90b899ea,
0x3a62,
0x4705,
{0x88, 0xb3, 0x8d, 0xf0, 0x4b, 0x27, 0x44, 0xe7}};
static const GUID DXVA2_ModeVP9_VLD_Profile0 = {
0x463707f8,
0xa1d0,
0x4585,
{0x87, 0x6d, 0x83, 0xaa, 0x6d, 0x60, 0xb8, 0x9e}};
static const GUID DXVA2_ModeAV1_Profile0 = {
0xb8be4ccb,
0xcf53,
0x46ba,
{0x8d, 0x59, 0xd6, 0xb8, 0xa6, 0xda, 0x5d, 0x2a}};
// This tests if a DXVA video decoder can be created for the given media
// type/resolution. It uses the same decoder device (DXVA2_ModeH264_E -
// DXVA2_ModeH264_VLD_NoFGT) as the H264 decoder MFT provided by windows
@ -614,15 +634,37 @@ class D3D11DXVA2Manager : public DXVA2Manager {
};
bool D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate) {
D3D11_VIDEO_DECODER_DESC desc;
desc.Guid = mDecoderGUID;
desc.OutputFormat = DXGI_FORMAT_NV12;
D3D11_VIDEO_DECODER_DESC desc = {.OutputFormat = DXGI_FORMAT_NV12};
GUID subtype;
HRESULT hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &desc.SampleWidth,
&desc.SampleHeight);
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
NS_ENSURE_TRUE(desc.SampleWidth <= MAX_VIDEO_WIDTH, false);
NS_ENSURE_TRUE(desc.SampleHeight <= MAX_VIDEO_HEIGHT, false);
hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype);
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
if (subtype == MFVideoFormat_H264) {
// IsUnsupportedResolution is only used to work around an AMD H264 issue.
NS_ENSURE_FALSE(IsUnsupportedResolution(desc.SampleWidth, desc.SampleHeight,
aFramerate),
false);
// Use the GUID defined earlier since some systems use an Intel-provided
// decoder.
// TODO: Move Intel-specific check from ::InitInternal to here.
desc.Guid = mDecoderGUID;
} else if (subtype == MFVideoFormat_VP80) {
desc.Guid = DXVA2_ModeVP8_VLD;
} else if (subtype == MFVideoFormat_VP90) {
desc.Guid = DXVA2_ModeVP9_VLD_Profile0;
} else if (subtype == MFVideoFormat_AV1) {
desc.Guid = DXVA2_ModeAV1_Profile0;
} else {
return false;
}
return CanCreateDecoder(desc, aFramerate);
}
@ -733,11 +775,13 @@ D3D11DXVA2Manager::InitInternal(layers::KnowsCompositor* aKnowsCompositor,
RefPtr<MFTDecoder> mft;
mozilla::mscom::EnsureMTA([&]() -> void {
mft = new MFTDecoder();
hr = mft->Create(CLSID_VideoProcessorMFT);
hr = mft->Create(MFT_CATEGORY_VIDEO_PROCESSOR, MFVideoFormat_NV12,
MFVideoFormat_ARGB32);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString(
"MFTDecoder::Create(CLSID_VideoProcessorMFT) failed with code %X",
"MFTDecoder::Create of Video Processor MFT for color conversion "
"failed with code %X",
hr);
return;
}
@ -1194,10 +1238,6 @@ D3D11DXVA2Manager::ConfigureForSize(IMFMediaType* aInputType,
bool D3D11DXVA2Manager::CanCreateDecoder(const D3D11_VIDEO_DECODER_DESC& aDesc,
const float aFramerate) const {
if (IsUnsupportedResolution(aDesc.SampleWidth, aDesc.SampleHeight,
aFramerate)) {
return false;
}
RefPtr<ID3D11VideoDecoder> decoder = CreateDecoder(aDesc);
return decoder.get() != nullptr;
}

Просмотреть файл

@ -14,7 +14,6 @@
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
namespace mozilla {
MFTDecoder::MFTDecoder() {
memset(&mInputStreamInfo, 0, sizeof(MFT_INPUT_STREAM_INFO));
memset(&mOutputStreamInfo, 0, sizeof(MFT_OUTPUT_STREAM_INFO));
@ -23,13 +22,52 @@ MFTDecoder::MFTDecoder() {
MFTDecoder::~MFTDecoder() {}
HRESULT
MFTDecoder::Create(const GUID& aMFTClsID) {
MFTDecoder::Create(const GUID& aCategory, const GUID& aInSubtype,
const GUID& aOutSubtype) {
// Note: IMFTransform is documented to only be safe on MTA threads.
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
// Create the IMFTransform to do the decoding.
// Use video by default, but select audio if necessary.
const GUID major = 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* {
if (IsEqualGUID(subtype, GUID_NULL)) {
return nullptr;
}
MFT_REGISTER_TYPE_INFO* info = new MFT_REGISTER_TYPE_INFO();
info->guidMajorType = major;
info->guidSubtype = subtype;
return info;
};
const MFT_REGISTER_TYPE_INFO* inInfo = createInfo(aInSubtype);
const MFT_REGISTER_TYPE_INFO* outInfo = createInfo(aOutSubtype);
// Request a decoder from the Windows API.
HRESULT hr;
hr = CoCreateInstance(
aMFTClsID, nullptr, CLSCTX_INPROC_SERVER,
IMFActivate** acts = nullptr;
UINT32 actsNum = 0;
hr = wmf::MFTEnumEx(aCategory, MFT_ENUM_FLAG_SORTANDFILTER, inInfo, outInfo,
&acts, &actsNum);
delete inInfo;
delete outInfo;
NS_ENSURE_TRUE(actsNum > 0, WINCODEC_ERR_COMPONENTNOTFOUND);
auto guard = MakeScopeExit([&] {
for (int i = 0; i < actsNum; i++) {
acts[i]->Release();
}
});
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
// Create the IMFTransform to do the decoding.
hr = acts[0]->ActivateObject(
IID_PPV_ARGS(static_cast<IMFTransform**>(getter_AddRefs(mDecoder))));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
@ -344,6 +382,13 @@ MFTDecoder::Flush() {
return S_OK;
}
HRESULT
MFTDecoder::GetInputMediaType(RefPtr<IMFMediaType>& aMediaType) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
NS_ENSURE_TRUE(mDecoder, E_POINTER);
return mDecoder->GetInputCurrentType(0, getter_AddRefs(aMediaType));
}
HRESULT
MFTDecoder::GetOutputMediaType(RefPtr<IMFMediaType>& aMediaType) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());

Просмотреть файл

@ -22,12 +22,17 @@ class MFTDecoder final {
MFTDecoder();
// Creates the MFT. First thing to do as part of setup.
// Creates the MFT by querying a category and media subtype.
// First thing to do as part of setup.
//
// Params:
// - aMFTClsID the clsid used by CoCreateInstance to instantiate the
// decoder MFT.
HRESULT Create(const GUID& aMFTClsID);
// - aCategory the GUID of the MFT category to use.
// - aInSubType the GUID of the input MFT media type to use.
// GUID_NULL may be used as a wildcard.
// - aOutSubType the GUID of the output MFT media type to use.
// GUID_NULL may be used as a wildcard.
HRESULT Create(const GUID& aCategory, const GUID& aInSubtype,
const GUID& aOutSubtype);
// Sets the input and output media types. Call after Init().
//
@ -47,6 +52,9 @@ class MFTDecoder final {
// Returns the MFT's IMFAttributes object for an output stream.
already_AddRefed<IMFAttributes> GetOutputStreamAttributes();
// Retrieves the media type being input.
HRESULT GetInputMediaType(RefPtr<IMFMediaType>& aMediaType);
// Retrieves the media type being output. This may not be valid until
// the first sample is decoded.
HRESULT GetOutputMediaType(RefPtr<IMFMediaType>& aMediaType);

Просмотреть файл

@ -32,12 +32,6 @@
# undef max
#endif
// Some SDK versions don't define the AAC decoder CLSID.
#ifndef CLSID_CMSAACDecMFT
extern "C" const CLSID CLSID_CMSAACDecMFT;
# define WMF_MUST_DEFINE_AAC_MFT_CLSID
#endif
namespace mozilla {
namespace wmf {

Просмотреть файл

@ -103,18 +103,6 @@ WMFAudioMFTManager::~WMFAudioMFTManager() {
MOZ_COUNT_DTOR(WMFAudioMFTManager);
}
const GUID& WMFAudioMFTManager::GetMFTGUID() {
MOZ_ASSERT(mStreamType != Unknown);
switch (mStreamType) {
case AAC:
return CLSID_CMSAACDecMFT;
case MP3:
return CLSID_CMP3DecMediaObject;
default:
return GUID_NULL;
};
}
const GUID& WMFAudioMFTManager::GetMediaSubtypeGUID() {
MOZ_ASSERT(mStreamType != Unknown);
switch (mStreamType) {
@ -131,8 +119,10 @@ bool WMFAudioMFTManager::Init() {
NS_ENSURE_TRUE(mStreamType != Unknown, false);
RefPtr<MFTDecoder> decoder(new MFTDecoder());
HRESULT hr = decoder->Create(GetMFTGUID());
// Note: MP3 MFT isn't registered as supporting Float output, but it works.
// Find PCM output MFTs as this is the common type.
HRESULT hr = decoder->Create(MFT_CATEGORY_AUDIO_DECODER,
GetMediaSubtypeGUID(), MFAudioFormat_PCM);
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
// Setup input/output media types

Просмотреть файл

@ -16,6 +16,7 @@
#include "MediaInfo.h"
#include "PDMFactory.h"
#include "VPXDecoder.h"
#include "AOMDecoder.h"
#include "WMF.h"
#include "WMFAudioMFTManager.h"
#include "WMFMediaDataDecoder.h"
@ -37,8 +38,6 @@
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
extern const GUID CLSID_WebmMfVpxDec;
namespace mozilla {
// Helper function to add a profile marker and log at the same time.
@ -85,7 +84,19 @@ static bool IsRemoteAcceleratedCompositor(
ident.mParentProcessType == GeckoProcessType_GPU;
}
static bool CanCreateMFTDecoder(const GUID& aGuid) {
static bool CanCreateMFTDecoder(const GUID& aCategory, const GUID& aInSubtype) {
const GUID outSubtype = [&]() {
if (aCategory == MFT_CATEGORY_VIDEO_DECODER) {
// H264 decoder MFT doesn't always support NV12
if (aInSubtype == MFVideoFormat_H264) {
return GUID_NULL;
}
return MFVideoFormat_NV12;
} else {
return MFAudioFormat_PCM;
}
}();
// The IMFTransform interface used by MFTDecoder is documented to require to
// run on an MTA thread.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ee892371(v=vs.85).aspx#components
@ -98,7 +109,8 @@ static bool CanCreateMFTDecoder(const GUID& aGuid) {
return;
}
RefPtr<MFTDecoder> decoder(new MFTDecoder());
canCreateDecoder = SUCCEEDED(decoder->Create(aGuid));
canCreateDecoder =
SUCCEEDED(decoder->Create(aCategory, aInSubtype, outSubtype));
wmf::MFShutdown();
});
return canCreateDecoder;
@ -137,7 +149,9 @@ void WMFDecoderModule::Init() {
WmfDecoderModuleMarkerAndLog("WMFInit VPx Pending",
"Attempting to create MFT decoder for VPx");
sUsableVPXMFT = CanCreateMFTDecoder(CLSID_WebmMfVpxDec);
sUsableVPXMFT =
CanCreateMFTDecoder(MFT_CATEGORY_VIDEO_DECODER, MFVideoFormat_VP80) &&
CanCreateMFTDecoder(MFT_CATEGORY_VIDEO_DECODER, MFVideoFormat_VP90);
WmfDecoderModuleMarkerAndLog("WMFInit VPx Initialized",
"CanCreateMFTDecoder returned %s for VPx",
@ -240,40 +254,48 @@ already_AddRefed<MediaDataDecoder> WMFDecoderModule::CreateAudioDecoder(
return decoder.forget();
}
template <const GUID& aGuid>
template <const GUID& aCategory, const GUID& aInSubtype>
static bool CanCreateWMFDecoder() {
static StaticMutex sMutex MOZ_UNANNOTATED;
StaticMutexAutoLock lock(sMutex);
static Maybe<bool> result;
if (result.isNothing()) {
result.emplace(CanCreateMFTDecoder(aGuid));
result.emplace(CanCreateMFTDecoder(aCategory, aInSubtype));
}
return result.value();
}
/* static */
bool WMFDecoderModule::HasH264() {
return CanCreateWMFDecoder<CLSID_CMSH264DecoderMFT>();
return CanCreateWMFDecoder<MFT_CATEGORY_VIDEO_DECODER, MFVideoFormat_H264>();
}
/* static */
bool WMFDecoderModule::HasVP8() {
return sUsableVPXMFT && CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
return sUsableVPXMFT &&
CanCreateWMFDecoder<MFT_CATEGORY_VIDEO_DECODER, MFVideoFormat_VP80>();
}
/* static */
bool WMFDecoderModule::HasVP9() {
return sUsableVPXMFT && CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
return sUsableVPXMFT &&
CanCreateWMFDecoder<MFT_CATEGORY_VIDEO_DECODER, MFVideoFormat_VP90>();
}
/* static */
bool WMFDecoderModule::HasAV1() {
return StaticPrefs::media_wmf_av1_enabled() &&
CanCreateWMFDecoder<MFT_CATEGORY_VIDEO_DECODER, MFVideoFormat_AV1>();
}
/* static */
bool WMFDecoderModule::HasAAC() {
return CanCreateWMFDecoder<CLSID_CMSAACDecMFT>();
return CanCreateWMFDecoder<MFT_CATEGORY_AUDIO_DECODER, MFAudioFormat_AAC>();
}
/* static */
bool WMFDecoderModule::HasMP3() {
return CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>();
return CanCreateWMFDecoder<MFT_CATEGORY_AUDIO_DECODER, MFAudioFormat_MP3>();
}
bool WMFDecoderModule::SupportsMimeType(
@ -326,6 +348,10 @@ bool WMFDecoderModule::Supports(const SupportDecoderParams& aParams,
return true;
}
if (AOMDecoder::IsAV1(trackInfo.mMimeType) && WMFDecoderModule::HasAV1()) {
return true;
}
// Some unsupported codec.
return false;
}

Просмотреть файл

@ -43,6 +43,7 @@ class WMFDecoderModule : public PlatformDecoderModule {
static bool HasH264();
static bool HasVP8();
static bool HasVP9();
static bool HasAV1();
static bool HasAAC();
static bool HasMP3();

Просмотреть файл

@ -21,13 +21,6 @@
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/WindowsVersion.h"
#ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID
// Some SDK versions don't define the AAC decoder CLSID.
// {32D186A7-218F-4C75-8876-DD77273A8999}
DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD,
0x77, 0x27, 0x3A, 0x89, 0x99);
#endif
namespace mozilla {
using media::TimeUnit;

Просмотреть файл

@ -18,6 +18,7 @@
#include "MediaInfo.h"
#include "MediaTelemetryConstants.h"
#include "VPXDecoder.h"
#include "AOMDecoder.h"
#include "VideoUtils.h"
#include "WMFDecoderModule.h"
#include "WMFUtils.h"
@ -62,14 +63,6 @@ const GUID MFVideoFormat_VP90 = {
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
#endif
// Note: CLSID_WebmMfVpxDec needs to be extern for the CanCreateWMFDecoder
// template in WMFDecoderModule.cpp to work.
extern const GUID CLSID_WebmMfVpxDec = {
0xe3aaf548,
0xc9a4,
0x4c6e,
{0x23, 0x4d, 0x5a, 0xda, 0x37, 0x4b, 0x00, 0x00}};
#if !defined(__MINGW32__) && _WIN32_WINNT < _WIN32_WINNT_WIN8
const GUID MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT = {
0x851745d5,
@ -162,6 +155,8 @@ WMFVideoMFTManager::WMFVideoMFTManager(
mStreamType = VP8;
} else if (VPXDecoder::IsVP9(aConfig.mMimeType)) {
mStreamType = VP9;
} else if (AOMDecoder::IsAV1(aConfig.mMimeType)) {
mStreamType = AV1;
} else {
mStreamType = Unknown;
}
@ -178,20 +173,6 @@ WMFVideoMFTManager::~WMFVideoMFTManager() {
MOZ_COUNT_DTOR(WMFVideoMFTManager);
}
const GUID& WMFVideoMFTManager::GetMFTGUID() {
MOZ_ASSERT(mStreamType != Unknown);
switch (mStreamType) {
case H264:
return CLSID_CMSH264DecoderMFT;
case VP8:
return CLSID_WebmMfVpxDec;
case VP9:
return CLSID_WebmMfVpxDec;
default:
return GUID_NULL;
};
}
const GUID& WMFVideoMFTManager::GetMediaSubtypeGUID() {
MOZ_ASSERT(mStreamType != Unknown);
switch (mStreamType) {
@ -201,6 +182,8 @@ const GUID& WMFVideoMFTManager::GetMediaSubtypeGUID() {
return MFVideoFormat_VP80;
case VP9:
return MFVideoFormat_VP90;
case AV1:
return MFVideoFormat_AV1;
default:
return GUID_NULL;
};
@ -310,7 +293,16 @@ MediaResult WMFVideoMFTManager::InitInternal() {
InitializeDXVA();
RefPtr<MFTDecoder> decoder = new MFTDecoder();
HRESULT hr = decoder->Create(GetMFTGUID());
const GUID subtype = GetMediaSubtypeGUID();
HRESULT hr =
decoder->Create(MFT_CATEGORY_VIDEO_DECODER, subtype, MFVideoFormat_NV12);
if (FAILED(hr)) {
NS_WARNING(
"Hardware decoder MFT creation failed, trying software decoding");
hr = decoder->Create(
MFT_CATEGORY_VIDEO_DECODER, subtype,
mStreamType == H264 ? MFVideoFormat_YUY2 : MFVideoFormat_YV12);
}
NS_ENSURE_TRUE(SUCCEEDED(hr),
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Can't create the MFT decoder.")));
@ -377,10 +369,11 @@ MediaResult WMFVideoMFTManager::InitInternal() {
// MFT_MESSAGE_SET_D3D_MANAGER failed
mDXVA2Manager.reset();
}
if (mStreamType == VP9 || mStreamType == VP8) {
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Use VP8/9 MFT only if HW acceleration "
"is available."));
if (mStreamType == VP9 || mStreamType == VP8 || mStreamType == AV1) {
return MediaResult(
NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Use VP8/VP9/AV1 MFT only if HW acceleration "
"is available."));
}
Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
uint32_t(media::MediaDecoderBackend::WMFSoftware));
@ -393,14 +386,14 @@ MediaResult WMFVideoMFTManager::InitInternal() {
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to set the decoder media types.")));
RefPtr<IMFMediaType> outputType;
hr = mDecoder->GetOutputMediaType(outputType);
RefPtr<IMFMediaType> inputType;
hr = mDecoder->GetInputMediaType(inputType);
NS_ENSURE_TRUE(
SUCCEEDED(hr),
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to get the output media type.")));
RESULT_DETAIL("Fail to get the input media type.")));
if (mUseHwAccel && !CanUseDXVA(outputType, mFramerate)) {
if (mUseHwAccel && !CanUseDXVA(inputType, mFramerate)) {
mDXVAEnabled = false;
// DXVA initialization with current decoder actually failed,
// re-do initialization.
@ -410,6 +403,13 @@ MediaResult WMFVideoMFTManager::InitInternal() {
LOG("Video Decoder initialized, Using DXVA: %s",
(mUseHwAccel ? "Yes" : "No"));
RefPtr<IMFMediaType> outputType;
hr = mDecoder->GetOutputMediaType(outputType);
NS_ENSURE_TRUE(
SUCCEEDED(hr),
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to get the output media type.")));
if (mUseHwAccel) {
hr = mDXVA2Manager->ConfigureForSize(
outputType,
@ -536,29 +536,31 @@ WMFVideoMFTManager::Input(MediaRawData* aSample) {
return mDecoder->Input(inputSample);
}
// The MFTransform we use for decoding h264 video will silently fall
// The MFTransforms we use for decoding H264 and AV1 video will silently fall
// back to software decoding (even if we've negotiated DXVA) if the GPU
// doesn't support decoding the given resolution. It will then upload
// doesn't support decoding the given codec and resolution. It will then upload
// the software decoded frames into d3d textures to preserve behaviour.
//
// Unfortunately this seems to cause corruption (see bug 1193547) and is
// slow because the upload is done into a non-shareable texture and requires
// us to copy it.
//
// This code tests if the given resolution can be supported directly on the GPU,
// and makes sure we only ask the MFT for DXVA if it can be supported properly.
// This code tests if the given codec and resolution can be supported directly
// on the GPU, and makes sure we only ask the MFT for DXVA if it can be
// supported properly.
//
// Ideally we'd know the framerate during initialization and would also ensure
// that new decoders are created if the resolution changes. Then we could move
// this check into Init and consolidate the main thread blocking code.
bool WMFVideoMFTManager::CanUseDXVA(IMFMediaType* aType, float aFramerate) {
MOZ_ASSERT(mDXVA2Manager);
// SupportsConfig only checks for valid h264 decoders currently.
if (mStreamType != H264) {
return true;
// Check if we're able to use hardware decoding with H264 or AV1.
// TODO: Do the same for VPX, if the VPX MFT has a slow software fallback?
if (mStreamType == H264 || mStreamType == AV1) {
return mDXVA2Manager->SupportsConfig(aType, aFramerate);
}
return mDXVA2Manager->SupportsConfig(aType, aFramerate);
return true;
}
TimeUnit WMFVideoMFTManager::GetSampleDurationOrLastKnownDuration(
@ -855,6 +857,18 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutData) {
}
TimeUnit pts = GetSampleTime(sample);
TimeUnit duration = GetSampleDurationOrLastKnownDuration(sample);
// AV1 MFT fix: Sample duration after seeking is always equal to the
// sample time, for some reason. Set it to last duration instead.
if (mStreamType == AV1 && duration == pts) {
LOG("Video sample duration (%" PRId64 ") matched timestamp (%" PRId64
"), setting to previous sample duration (%" PRId64 ") instead.",
pts.ToMicroseconds(), duration.ToMicroseconds(),
mLastDuration.ToMicroseconds());
duration = mLastDuration;
sample->SetSampleDuration(UsecsToHNs(duration.ToMicroseconds()));
}
if (!pts.IsValid() || !duration.IsValid()) {
return E_FAIL;
}

Просмотреть файл

@ -97,7 +97,7 @@ class WMFVideoMFTManager : public MFTManager {
nsCString mDXVAFailureReason;
enum StreamType { Unknown, H264, VP8, VP9 };
enum StreamType { Unknown, H264, VP8, VP9, AV1 };
StreamType mStreamType;
@ -110,13 +110,14 @@ class WMFVideoMFTManager : public MFTManager {
return "VP8";
case StreamType::VP9:
return "VP9";
case StreamType::AV1:
return "AV1";
default:
MOZ_ASSERT(mStreamType == StreamType::Unknown);
return "Unknown";
}
}
const GUID& GetMFTGUID();
const GUID& GetMediaSubtypeGUID();
uint32_t mNullOutputCount = 0;

Просмотреть файл

@ -8995,6 +8995,11 @@
value: true
mirror: once
- name: media.wmf.av1.enabled
type: RelaxedAtomicBool
value: true
mirror: always
#endif # MOZ_WMF
- name: media.decoder-doctor.testing