summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/apple
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/platforms/apple')
-rw-r--r--dom/media/platforms/apple/AppleDecoderModule.cpp49
-rw-r--r--dom/media/platforms/apple/AppleDecoderModule.h1
-rw-r--r--dom/media/platforms/apple/AppleVTDecoder.cpp32
-rw-r--r--dom/media/platforms/apple/AppleVTDecoder.h2
-rw-r--r--dom/media/platforms/apple/AppleVTEncoder.cpp56
-rw-r--r--dom/media/platforms/apple/AppleVTEncoder.h5
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) {