Skip to content

Commit

Permalink
fix hw media decoding for < 10.8 systems (central)
Browse files Browse the repository at this point in the history
  • Loading branch information
i3roly committed Dec 15, 2024
1 parent af15acf commit a3d97e7
Show file tree
Hide file tree
Showing 19 changed files with 682 additions and 57 deletions.
12 changes: 12 additions & 0 deletions dom/media/platforms/apple/AppleCMFunctions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Construct references to each of the CoreMedia symbols we use.

LINK_FUNC(CMVideoFormatDescriptionCreate)
LINK_FUNC(CMBlockBufferCreateWithMemoryBlock)
LINK_FUNC(CMSampleBufferCreate)
LINK_FUNC(CMTimeMake)
85 changes: 85 additions & 0 deletions dom/media/platforms/apple/AppleCMLinker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <dlfcn.h>

#include "AppleCMLinker.h"
#include "MainThreadUtils.h"
#include "nsDebug.h"

#ifdef PR_LOGGING
PRLogModuleInfo* GetAppleMediaLog();
#define LOG(...) PR_LOG(GetAppleMediaLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#define LOG(...)
#endif

namespace mozilla {

AppleCMLinker::LinkStatus
AppleCMLinker::sLinkStatus = LinkStatus_INIT;

void* AppleCMLinker::sLink = nullptr;
nsrefcnt AppleCMLinker::sRefCount = 0;

#define LINK_FUNC(func) typeof(func) func;
#include "AppleCMFunctions.h"
#undef LINK_FUNC

/* static */ bool
AppleCMLinker::Link()
{
// Bump our reference count every time we're called.
// Add a lock or change the thread assertion if
// you need to call this off the main thread.
MOZ_ASSERT(NS_IsMainThread());
++sRefCount;

if (sLinkStatus) {
return sLinkStatus == LinkStatus_SUCCEEDED;
}

const char* dlname =
"/System/Library/Frameworks/CoreMedia.framework/CoreMedia";
if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) {
NS_WARNING("Couldn't load CoreMedia framework");
goto fail;
}

#define LINK_FUNC(func) \
func = (typeof(func))dlsym(sLink, #func); \
if (!func) { \
NS_WARNING("Couldn't load CoreMedia function " #func ); \
goto fail; \
}
#include "AppleCMFunctions.h"
#undef LINK_FUNC

LOG("Loaded CoreMedia framework.");
sLinkStatus = LinkStatus_SUCCEEDED;
return true;

fail:
Unlink();

sLinkStatus = LinkStatus_FAILED;
return false;
}

/* static */ void
AppleCMLinker::Unlink()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sRefCount > 0, "Unbalanced Unlink()");
--sRefCount;
if (sLink && sRefCount < 1) {
LOG("Unlinking CoreMedia framework.");
dlclose(sLink);
sLink = nullptr;
}
}

} // namespace mozilla
43 changes: 43 additions & 0 deletions dom/media/platforms/apple/AppleCMLinker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef AppleCMLinker_h
#define AppleCMLinker_h

extern "C" {
#pragma GCC visibility push(default)
#include <CoreMedia/CoreMedia.h>
#pragma GCC visibility pop
}

#include "nscore.h"

namespace mozilla {

class AppleCMLinker
{
public:
static bool Link();
static void Unlink();

private:
static void* sLink;
static nsrefcnt sRefCount;

static enum LinkStatus {
LinkStatus_INIT = 0,
LinkStatus_FAILED,
LinkStatus_SUCCEEDED
} sLinkStatus;
};

#define LINK_FUNC(func) extern typeof(func)* func;
#include "AppleCMFunctions.h"
#undef LINK_FUNC

} // namespace mozilla

#endif // AppleCMLinker_h
21 changes: 17 additions & 4 deletions dom/media/platforms/apple/AppleDecoderModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "AppleATDecoder.h"
#include "AppleVTDecoder.h"
#include "AppleVDADecoder.h"
#include "AppleVDALinker.h"
#include "AppleCMLinker.h"
#include "AppleVTLinker.h"

#include "MP4Decoder.h"
#include "VideoUtils.h"
Expand Down Expand Up @@ -39,11 +42,21 @@ bool AppleDecoderModule::sInitialized = false;
bool AppleDecoderModule::sCanUseVP9Decoder = false;
bool AppleDecoderModule::sCanUseAV1Decoder = false;

bool AppleDecoderModule::sIsCoreMediaAvailable = false;
bool AppleDecoderModule::sIsVTAvailable = false;
bool AppleDecoderModule::sIsVDAAvailable = false;

/* static */
void AppleDecoderModule::Init() {
if (sInitialized) {
return;
}

//10.7.3 - > 10.7 need these (thanks jya)
sIsCoreMediaAvailable = AppleCMLinker::Link();
sIsVDAAvailable = AppleVDALinker::Link();
sIsVTAvailable = AppleVTLinker::Link();

sInitialized = true;
if (RegisterSupplementalVP9Decoder()) {
sCanUseVP9Decoder = CanCreateHWDecoder(MediaCodec::VP9);
Expand All @@ -64,10 +77,10 @@ already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateVideoDecoder(
.isEmpty()) {
return nullptr;
}

RefPtr<MediaDataDecoder> decoder;

if(__builtin_available(macOS 10.8, *)) {
if(__builtin_available(macOS 10.7, *)) {
if (IsVideoSupported(aParams.VideoConfig(), aParams.mOptions)) {
decoder = new AppleVTDecoder(aParams.VideoConfig(), aParams.mImageContainer,
aParams.mOptions, aParams.mKnowsCompositor,
Expand Down Expand Up @@ -270,10 +283,10 @@ bool AppleDecoderModule::CanCreateHWDecoder(MediaCodec aCodec) {
}
// VT reports HW decode is supported -- verify by creating an actual decoder
if (vtReportsSupport) {
RefPtr<MediaDataDecoder> decoder;
RefPtr<MediaDataDecoder> decoder;//Dummy variable
MediaResult rv;
char *type;
if(__builtin_available(macOS 10.8, *)) {
if(__builtin_available(macOS 10.7, *)) {
RefPtr<AppleVTDecoder> decoder =
new AppleVTDecoder(info, nullptr, {}, nullptr, Nothing());
rv = decoder->InitializeSession();
Expand Down
3 changes: 3 additions & 0 deletions dom/media/platforms/apple/AppleDecoderModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class AppleDecoderModule : public PlatformDecoderModule {

static bool sCanUseVP9Decoder;
static bool sCanUseAV1Decoder;
static bool sIsCoreMediaAvailable;
static bool sIsVDAAvailable;
static bool sIsVTAvailable;

static constexpr int kCMVideoCodecType_H264{'avc1'};
static constexpr int kCMVideoCodecType_VP9{'vp09'};
Expand Down
30 changes: 16 additions & 14 deletions dom/media/platforms/apple/AppleVDADecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "AppleUtils.h"
#include "CallbackThreadRegistry.h"

#include "AppleVDADecoder.h"
#include "AppleVDALinker.h"
#include "MediaInfo.h"
#include "MP4Decoder.h"
#include "MediaData.h"
Expand Down Expand Up @@ -60,7 +62,6 @@ AppleVDADecoder::AppleVDADecoder(const VideoInfo& aConfig,
mTaskQueue(TaskQueue::Create(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
"AppleVDADecoder")),
mDecoder(nullptr),
mMaxRefFrames(
mStreamType != StreamType::H264 ||
aOptions.contains(CreateDecoderParams::Option::LowLatency)
Expand Down Expand Up @@ -102,7 +103,6 @@ AppleVDADecoder::~AppleVDADecoder()
RefPtr<MediaDataDecoder::InitPromise>
AppleVDADecoder::Init()
{
LOG("tryna call initsession\n");
MediaResult rv = InitializeSession();

if (NS_SUCCEEDED(rv)) {
Expand Down Expand Up @@ -531,12 +531,13 @@ AppleVDADecoder::InitializeSession()
this,
&mDecoder);

rv == 0 ? mIsHardwareAccelerated = 1 : mIsHardwareAccelerated = 0; //kVDADecoderNoErr = 0
mIsHardwareAccelerated = rv == 0 ? 1 : 0; //kVDADecoderNoErr = 0
if (rv != noErr) {
LOG("AppleVDADecoder: Couldn't create hardware VDA decoder, error %d", rv);
return NS_ERROR_FAILURE;
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Couldn't create format description!"));
}

LOG("AppleVDADecoder: %s hardware accelerated decoding",
mIsHardwareAccelerated ? "using" : "not using");

Expand All @@ -546,6 +547,8 @@ AppleVDADecoder::InitializeSession()
CFDictionaryRef
AppleVDADecoder::CreateDecoderSpecification()
{
const uint8_t* extradata = mExtraData->Elements();
int extrasize = mExtraData->Length();

OSType format = 'avc1';
AutoCFRelease<CFNumberRef> avc_width =
Expand All @@ -560,16 +563,15 @@ AppleVDADecoder::CreateDecoderSpecification()
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type,
&format);

AutoCFRelease<CFDataRef> avc_data =
CFDataCreate(kCFAllocatorDefault,
mExtraData->Elements(),
AssertedCast<CFIndex>(mExtraData->Length()));

const void* decoderKeys[] = { kVDADecoderConfiguration_Width,
kVDADecoderConfiguration_Height,
kVDADecoderConfiguration_SourceFormat,
kVDADecoderConfiguration_avcCData };
CFDataCreate(kCFAllocatorDefault,
extradata,
extrasize);

const void* decoderKeys[] = { AppleVDALinker::skPropWidth,
AppleVDALinker::skPropHeight,
AppleVDALinker::skPropSourceFormat,
AppleVDALinker::skPropAVCCData };
const void* decoderValue[] = { avc_width,
avc_height,
avc_format,
Expand Down
31 changes: 16 additions & 15 deletions dom/media/platforms/apple/AppleVDADecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include <CoreFoundation/CFDictionary.h> // For CFDictionaryRef
#include <CoreMedia/CoreMedia.h> // For CMVideoFormatDescriptionRef
#include <VideoDecodeAcceleration/VDADecoder.h>
#include <VideoToolbox/VideoToolbox.h> // For VTDecompressionSessionRef

#include "AppleDecoderModule.h"
#include "AppleVTDecoder.h"
Expand All @@ -22,6 +22,7 @@
#include "mozilla/ProfilerUtils.h"
#include "mozilla/gfx/Types.h"

#include "VideoDecodeAcceleration/VDADecoder.h"

namespace mozilla {

Expand Down Expand Up @@ -101,19 +102,6 @@ class AppleVDADecoder final : public MediaDataDecoder,

void SetSeekThreshold(const media::TimeUnit& aTime) override;


const RefPtr<MediaByteBuffer> mExtraData;
const uint32_t mPictureWidth;
const uint32_t mPictureHeight;
const uint32_t mDisplayWidth;
const uint32_t mDisplayHeight;
const gfx::YUVColorSpace mColorSpace;
const gfx::ColorSpace2 mColorPrimaries;
const gfx::TransferFunction mTransferFunction;
const gfx::ColorRange mColorRange;
const gfx::ColorDepth mColorDepth;


private:
friend class AppleDecoderModule; // To access InitializeSession.
virtual ~AppleVDADecoder();
Expand All @@ -131,13 +119,26 @@ class AppleVDADecoder final : public MediaDataDecoder,

AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample);
CFDictionaryRef CreateOutputConfiguration();

const RefPtr<MediaByteBuffer> mExtraData;
const uint32_t mPictureWidth;
const uint32_t mPictureHeight;
const uint32_t mDisplayWidth;
const uint32_t mDisplayHeight;
const gfx::YUVColorSpace mColorSpace;
const gfx::ColorSpace2 mColorPrimaries;
const gfx::TransferFunction mTransferFunction;
const gfx::ColorRange mColorRange;
const gfx::ColorDepth mColorDepth;

// Method to set up the decompression session.
MediaResult InitializeSession();
nsresult WaitForAsynchronousFrames();
CFDictionaryRef CreateDecoderSpecification();
CFDictionaryRef CreateDecoderExtensions();

MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(StreamType,
(Unknown, H264));
(Unknown, H264, VP9, AV1));

const StreamType mStreamType;
const RefPtr<TaskQueue> mTaskQueue;
Expand Down
12 changes: 12 additions & 0 deletions dom/media/platforms/apple/AppleVDAFunctions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Construct references to each of the VDA symbols we use.

LINK_FUNC(VDADecoderCreate)
LINK_FUNC(VDADecoderDecode)
LINK_FUNC(VDADecoderFlush)
LINK_FUNC(VDADecoderDestroy)
Loading

0 comments on commit a3d97e7

Please sign in to comment.