diff options
Diffstat (limited to 'dom/media/platforms/apple')
-rw-r--r-- | dom/media/platforms/apple/AppleDecoderModule.cpp | 49 | ||||
-rw-r--r-- | dom/media/platforms/apple/AppleDecoderModule.h | 1 | ||||
-rw-r--r-- | dom/media/platforms/apple/AppleVTDecoder.cpp | 32 | ||||
-rw-r--r-- | dom/media/platforms/apple/AppleVTDecoder.h | 2 | ||||
-rw-r--r-- | dom/media/platforms/apple/AppleVTEncoder.cpp | 56 | ||||
-rw-r--r-- | dom/media/platforms/apple/AppleVTEncoder.h | 5 |
6 files changed, 104 insertions, 41 deletions
diff --git a/dom/media/platforms/apple/AppleDecoderModule.cpp b/dom/media/platforms/apple/AppleDecoderModule.cpp index c54593a495..b92369601c 100644 --- a/dom/media/platforms/apple/AppleDecoderModule.cpp +++ b/dom/media/platforms/apple/AppleDecoderModule.cpp @@ -13,6 +13,7 @@ #include "MP4Decoder.h" #include "VideoUtils.h" #include "VPXDecoder.h" +#include "AOMDecoder.h" #include "mozilla/Logging.h" #include "mozilla/StaticPrefs_media.h" #include "mozilla/gfx/gfxVars.h" @@ -34,6 +35,7 @@ using media::MediaCodec; bool AppleDecoderModule::sInitialized = false; bool AppleDecoderModule::sCanUseVP9Decoder = false; +bool AppleDecoderModule::sCanUseAV1Decoder = false; /* static */ void AppleDecoderModule::Init() { @@ -45,6 +47,7 @@ void AppleDecoderModule::Init() { if (RegisterSupplementalVP9Decoder()) { sCanUseVP9Decoder = CanCreateHWDecoder(MediaCodec::VP9); } + sCanUseAV1Decoder = CanCreateHWDecoder(MediaCodec::AV1); } nsresult AppleDecoderModule::Startup() { @@ -83,7 +86,8 @@ DecodeSupportSet AppleDecoderModule::SupportsMimeType( const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { bool checkSupport = aMimeType.EqualsLiteral("audio/mp4a-latm") || MP4Decoder::IsH264(aMimeType) || - VPXDecoder::IsVP9(aMimeType); + VPXDecoder::IsVP9(aMimeType) || + AOMDecoder::IsAV1(aMimeType); DecodeSupportSet supportType{}; if (checkSupport) { @@ -142,6 +146,35 @@ bool AppleDecoderModule::IsVideoSupported( if (MP4Decoder::IsH264(aConfig.mMimeType)) { return true; } + if (AOMDecoder::IsAV1(aConfig.mMimeType)) { + if (!sCanUseAV1Decoder || + aOptions.contains( + CreateDecoderParams::Option::HardwareDecoderNotAllowed)) { + return false; + } + + // HW AV1 decoder only supports 8 or 10 bit color. + if (aConfig.mColorDepth != gfx::ColorDepth::COLOR_8 && + aConfig.mColorDepth != gfx::ColorDepth::COLOR_10) { + return false; + } + + if (aConfig.mColorSpace.isSome()) { + if (*aConfig.mColorSpace == gfx::YUVColorSpace::Identity) { + // HW AV1 decoder doesn't support RGB + return false; + } + } + + if (aConfig.mExtraData && aConfig.mExtraData->Length() < 2) { + return true; // Assume it's okay. + } + // top 3 bits are the profile. + int profile = aConfig.mExtraData->ElementAt(1) >> 5; + // 0 is main profile + return profile == 0; + } + if (!VPXDecoder::IsVP9(aConfig.mMimeType) || !sCanUseVP9Decoder || aOptions.contains( CreateDecoderParams::Option::HardwareDecoderNotAllowed)) { @@ -187,6 +220,20 @@ bool AppleDecoderModule::CanCreateHWDecoder(MediaCodec aCodec) { return false; } switch (aCodec) { + case MediaCodec::AV1: { + info.mMimeType = "video/av1"; + + // Build up a fake CBox + bool hasSeqHdr; + AOMDecoder::AV1SequenceInfo seqInfo; + AOMDecoder::OperatingPoint op; + seqInfo.mOperatingPoints.AppendElement(op); + seqInfo.mImage = {1920, 1080}; + AOMDecoder::WriteAV1CBox(seqInfo, info.mExtraData, hasSeqHdr); + + vtReportsSupport = VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1); + break; + } case MediaCodec::VP9: info.mMimeType = "video/vp9"; VPXDecoder::GetVPCCBox(info.mExtraData, VPXDecoder::VPXStreamInfo()); diff --git a/dom/media/platforms/apple/AppleDecoderModule.h b/dom/media/platforms/apple/AppleDecoderModule.h index f869243a5c..46b0223d75 100644 --- a/dom/media/platforms/apple/AppleDecoderModule.h +++ b/dom/media/platforms/apple/AppleDecoderModule.h @@ -39,6 +39,7 @@ class AppleDecoderModule : public PlatformDecoderModule { static void Init(); static bool sCanUseVP9Decoder; + static bool sCanUseAV1Decoder; static constexpr int kCMVideoCodecType_H264{'avc1'}; static constexpr int kCMVideoCodecType_VP9{'vp09'}; diff --git a/dom/media/platforms/apple/AppleVTDecoder.cpp b/dom/media/platforms/apple/AppleVTDecoder.cpp index ae34c2d142..6a70ed19d5 100644 --- a/dom/media/platforms/apple/AppleVTDecoder.cpp +++ b/dom/media/platforms/apple/AppleVTDecoder.cpp @@ -18,6 +18,7 @@ #include "MacIOSurfaceImage.h" #include "MediaData.h" #include "VPXDecoder.h" +#include "AOMDecoder.h" #include "VideoUtils.h" #include "gfxMacUtils.h" #include "mozilla/ArrayUtils.h" @@ -55,6 +56,7 @@ AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig, mColorDepth(aConfig.mColorDepth), mStreamType(MP4Decoder::IsH264(aConfig.mMimeType) ? StreamType::H264 : VPXDecoder::IsVP9(aConfig.mMimeType) ? StreamType::VP9 + : AOMDecoder::IsAV1(aConfig.mMimeType) ? StreamType::AV1 : StreamType::Unknown), mTaskQueue(TaskQueue::Create( GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER), @@ -89,7 +91,10 @@ AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig, MOZ_ASSERT(mStreamType != StreamType::Unknown); // TODO: Verify aConfig.mime_type. LOG("Creating AppleVTDecoder for %dx%d %s video", mDisplayWidth, - mDisplayHeight, mStreamType == StreamType::H264 ? "H.264" : "VP9"); + mDisplayHeight, + mStreamType == StreamType::H264 ? "H.264" + : mStreamType == StreamType::VP9 ? "VP9" + : "AV1"); } AppleVTDecoder::~AppleVTDecoder() { MOZ_COUNT_DTOR(AppleVTDecoder); } @@ -177,6 +182,9 @@ void AppleVTDecoder::ProcessDecode(MediaRawData* aSample) { case StreamType::VP9: flag |= MediaInfoFlag::VIDEO_VP9; break; + case StreamType::AV1: + flag |= MediaInfoFlag::VIDEO_AV1; + break; default: break; } @@ -377,6 +385,8 @@ nsCString AppleVTDecoder::GetCodecName() const { return "h264"_ns; case StreamType::VP9: return "vp9"_ns; + case StreamType::AV1: + return "av1"_ns; default: return "unknown"_ns; } @@ -598,13 +608,17 @@ MediaResult AppleVTDecoder::InitializeSession() { OSStatus rv; AutoCFRelease<CFDictionaryRef> extensions = CreateDecoderExtensions(); + CMVideoCodecType streamType; + if (mStreamType == StreamType::H264) { + streamType = kCMVideoCodecType_H264; + } else if (mStreamType == StreamType::VP9) { + streamType = CMVideoCodecType(AppleDecoderModule::kCMVideoCodecType_VP9); + } else { + streamType = kCMVideoCodecType_AV1; + } rv = CMVideoFormatDescriptionCreate( - kCFAllocatorDefault, - mStreamType == StreamType::H264 - ? kCMVideoCodecType_H264 - : CMVideoCodecType(AppleDecoderModule::kCMVideoCodecType_VP9), - AssertedCast<int32_t>(mPictureWidth), + kCFAllocatorDefault, streamType, AssertedCast<int32_t>(mPictureWidth), AssertedCast<int32_t>(mPictureHeight), extensions, &mFormat); if (rv != noErr) { return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, @@ -626,6 +640,7 @@ MediaResult AppleVTDecoder::InitializeSession() { &cb, &mSession); if (rv != noErr) { + LOG("AppleVTDecoder: VTDecompressionSessionCreate failed: %d", rv); return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Couldn't create decompression session!")); } @@ -656,7 +671,10 @@ CFDictionaryRef AppleVTDecoder::CreateDecoderExtensions() { AssertedCast<CFIndex>(mExtraData->Length())); const void* atomsKey[1]; - atomsKey[0] = mStreamType == StreamType::H264 ? CFSTR("avcC") : CFSTR("vpcC"); + atomsKey[0] = mStreamType == StreamType::H264 ? CFSTR("avcC") + : mStreamType == StreamType::VP9 ? CFSTR("vpcC") + : CFSTR("av1C"); + ; const void* atomsValue[] = {data}; static_assert(ArrayLength(atomsKey) == ArrayLength(atomsValue), "Non matching keys/values array size"); diff --git a/dom/media/platforms/apple/AppleVTDecoder.h b/dom/media/platforms/apple/AppleVTDecoder.h index 5b8f02b86f..a32bec112e 100644 --- a/dom/media/platforms/apple/AppleVTDecoder.h +++ b/dom/media/platforms/apple/AppleVTDecoder.h @@ -111,7 +111,7 @@ class AppleVTDecoder final : public MediaDataDecoder, CFDictionaryRef CreateDecoderSpecification(); CFDictionaryRef CreateDecoderExtensions(); - enum class StreamType { Unknown, H264, VP9 }; + enum class StreamType { Unknown, H264, VP9, AV1 }; const StreamType mStreamType; const RefPtr<TaskQueue> mTaskQueue; const uint32_t mMaxRefFrames; diff --git a/dom/media/platforms/apple/AppleVTEncoder.cpp b/dom/media/platforms/apple/AppleVTEncoder.cpp index 5ec9abebe2..c464ddd6f3 100644 --- a/dom/media/platforms/apple/AppleVTEncoder.cpp +++ b/dom/media/platforms/apple/AppleVTEncoder.cpp @@ -80,9 +80,8 @@ static bool SetConstantBitrate(VTCompressionSessionRef& aSession, } static bool SetBitrateAndMode(VTCompressionSessionRef& aSession, - MediaDataEncoder::BitrateMode aBitrateMode, - uint32_t aBitsPerSec) { - if (aBitrateMode == MediaDataEncoder::BitrateMode::Variable) { + BitrateMode aBitrateMode, uint32_t aBitsPerSec) { + if (aBitrateMode == BitrateMode::Variable) { return SetAverageBitrate(aSession, aBitsPerSec); } return SetConstantBitrate(aSession, aBitsPerSec); @@ -177,9 +176,8 @@ RefPtr<MediaDataEncoder::InitPromise> AppleVTEncoder::Init() { if (mConfig.mBitrate) { if (!SetBitrateAndMode(mSession, mConfig.mBitrateMode, mConfig.mBitrate)) { LOGE("failed to set bitrate to %d and mode to %s", mConfig.mBitrate, - mConfig.mBitrateMode == MediaDataEncoder::BitrateMode::Constant - ? "constant" - : "variable"); + mConfig.mBitrateMode == BitrateMode::Constant ? "constant" + : "variable"); return InitPromise::CreateAndReject( MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "fail to configurate bitrate"), @@ -228,26 +226,25 @@ RefPtr<MediaDataEncoder::InitPromise> AppleVTEncoder::Init() { } mError = NS_OK; - return InitPromise::CreateAndResolve(TrackInfo::TrackType::kVideoTrack, - __func__); + return InitPromise::CreateAndResolve(true, __func__); } -static Maybe<OSType> MapPixelFormat(MediaDataEncoder::PixelFormat aFormat) { +static Maybe<OSType> MapPixelFormat(dom::ImageBitmapFormat aFormat) { switch (aFormat) { - case MediaDataEncoder::PixelFormat::RGBA32: - case MediaDataEncoder::PixelFormat::BGRA32: + case dom::ImageBitmapFormat::RGBA32: + case dom::ImageBitmapFormat::BGRA32: return Some(kCVPixelFormatType_32BGRA); - case MediaDataEncoder::PixelFormat::RGB24: + case dom::ImageBitmapFormat::RGB24: return Some(kCVPixelFormatType_24RGB); - case MediaDataEncoder::PixelFormat::BGR24: + case dom::ImageBitmapFormat::BGR24: return Some(kCVPixelFormatType_24BGR); - case MediaDataEncoder::PixelFormat::GRAY8: + case dom::ImageBitmapFormat::GRAY8: return Some(kCVPixelFormatType_OneComponent8); - case MediaDataEncoder::PixelFormat::YUV444P: + case dom::ImageBitmapFormat::YUV444P: return Some(kCVPixelFormatType_444YpCbCr8); - case MediaDataEncoder::PixelFormat::YUV420P: + case dom::ImageBitmapFormat::YUV420P: return Some(kCVPixelFormatType_420YpCbCr8PlanarFullRange); - case MediaDataEncoder::PixelFormat::YUV420SP_NV12: + case dom::ImageBitmapFormat::YUV420SP_NV12: return Some(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); default: return Nothing(); @@ -459,11 +456,10 @@ void AppleVTEncoder::OutputFrame(CMSampleBufferRef aBuffer) { LOGD("::OutputFrame"); RefPtr<MediaRawData> output(new MediaRawData()); - bool forceAvcc = false; if (mConfig.mCodecSpecific->is<H264Specific>()) { forceAvcc = mConfig.mCodecSpecific->as<H264Specific>().mFormat == - H264BitStreamFormat::AVC; + H264BitStreamFormat::AVC; } bool asAnnexB = mConfig.mUsage == Usage::Realtime && !forceAvcc; bool succeeded = WriteExtraData(output, aBuffer, asAnnexB) && @@ -590,7 +586,9 @@ AppleVTEncoder::ProcessReconfigure( mConfig.mUsage = aChange.get(); return SetRealtime(mSession, aChange.get() == Usage::Realtime); }, - [&](const ContentHintChange& aChange) -> bool { return false; }); + [&](const ContentHintChange& aChange) -> bool { return false; }, + [&](const SampleRateChange& aChange) -> bool { return false; }, + [&](const NumberOfChannelsChange& aChange) -> bool { return false; }); }; using P = MediaDataEncoder::ReconfigurationPromise; if (ok) { @@ -599,18 +597,18 @@ AppleVTEncoder::ProcessReconfigure( return P::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); } -static size_t NumberOfPlanes(MediaDataEncoder::PixelFormat aPixelFormat) { +static size_t NumberOfPlanes(dom::ImageBitmapFormat aPixelFormat) { switch (aPixelFormat) { - case MediaDataEncoder::PixelFormat::RGBA32: - case MediaDataEncoder::PixelFormat::BGRA32: - case MediaDataEncoder::PixelFormat::RGB24: - case MediaDataEncoder::PixelFormat::BGR24: - case MediaDataEncoder::PixelFormat::GRAY8: + case dom::ImageBitmapFormat::RGBA32: + case dom::ImageBitmapFormat::BGRA32: + case dom::ImageBitmapFormat::RGB24: + case dom::ImageBitmapFormat::BGR24: + case dom::ImageBitmapFormat::GRAY8: return 1; - case MediaDataEncoder::PixelFormat::YUV444P: - case MediaDataEncoder::PixelFormat::YUV420P: + case dom::ImageBitmapFormat::YUV444P: + case dom::ImageBitmapFormat::YUV420P: return 3; - case MediaDataEncoder::PixelFormat::YUV420SP_NV12: + case dom::ImageBitmapFormat::YUV420SP_NV12: return 2; default: LOGE("Unsupported input pixel format"); diff --git a/dom/media/platforms/apple/AppleVTEncoder.h b/dom/media/platforms/apple/AppleVTEncoder.h index eded46c8c8..c7985a454c 100644 --- a/dom/media/platforms/apple/AppleVTEncoder.h +++ b/dom/media/platforms/apple/AppleVTEncoder.h @@ -24,9 +24,8 @@ class AppleVTEncoder final : public MediaDataEncoder { const RefPtr<TaskQueue>& aTaskQueue) : mConfig(aConfig), mTaskQueue(aTaskQueue), - mHardwareNotAllowed( - aConfig.mHardwarePreference == - MediaDataEncoder::HardwarePreference::RequireSoftware), + mHardwareNotAllowed(aConfig.mHardwarePreference == + HardwarePreference::RequireSoftware), mFramesCompleted(false), mError(NS_OK), mSession(nullptr) { |