From a3d97e7693f6dd635ef268b217f23b5f2641b5b6 Mon Sep 17 00:00:00 2001 From: broly Date: Sat, 14 Dec 2024 22:21:16 -0700 Subject: [PATCH] fix hw media decoding for < 10.8 systems (central) --- dom/media/platforms/apple/AppleCMFunctions.h | 12 ++ dom/media/platforms/apple/AppleCMLinker.cpp | 85 ++++++++ dom/media/platforms/apple/AppleCMLinker.h | 43 ++++ .../platforms/apple/AppleDecoderModule.cpp | 21 +- .../platforms/apple/AppleDecoderModule.h | 3 + dom/media/platforms/apple/AppleVDADecoder.cpp | 30 +-- dom/media/platforms/apple/AppleVDADecoder.h | 31 +-- dom/media/platforms/apple/AppleVDAFunctions.h | 12 ++ dom/media/platforms/apple/AppleVDALinker.cpp | 103 ++++++++++ dom/media/platforms/apple/AppleVDALinker.h | 49 +++++ dom/media/platforms/apple/AppleVTDecoder.cpp | 12 +- dom/media/platforms/apple/AppleVTDecoder.h | 1 + dom/media/platforms/apple/AppleVTEncoder.cpp | 38 ++-- dom/media/platforms/apple/AppleVTFunctions.h | 18 ++ dom/media/platforms/apple/AppleVTLinker.cpp | 188 ++++++++++++++++++ dom/media/platforms/apple/AppleVTLinker.h | 70 +++++++ dom/media/platforms/moz.build | 3 + .../certverifier/NSSCertDBTrustDomain.cpp | 10 + .../common/test/SandboxTestingChildTests.h | 10 +- 19 files changed, 682 insertions(+), 57 deletions(-) create mode 100644 dom/media/platforms/apple/AppleCMFunctions.h create mode 100644 dom/media/platforms/apple/AppleCMLinker.cpp create mode 100644 dom/media/platforms/apple/AppleCMLinker.h create mode 100644 dom/media/platforms/apple/AppleVDAFunctions.h create mode 100644 dom/media/platforms/apple/AppleVDALinker.cpp create mode 100644 dom/media/platforms/apple/AppleVDALinker.h create mode 100644 dom/media/platforms/apple/AppleVTFunctions.h create mode 100644 dom/media/platforms/apple/AppleVTLinker.cpp create mode 100644 dom/media/platforms/apple/AppleVTLinker.h diff --git a/dom/media/platforms/apple/AppleCMFunctions.h b/dom/media/platforms/apple/AppleCMFunctions.h new file mode 100644 index 0000000000000..f81ce09723634 --- /dev/null +++ b/dom/media/platforms/apple/AppleCMFunctions.h @@ -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) diff --git a/dom/media/platforms/apple/AppleCMLinker.cpp b/dom/media/platforms/apple/AppleCMLinker.cpp new file mode 100644 index 0000000000000..bde9819d6509b --- /dev/null +++ b/dom/media/platforms/apple/AppleCMLinker.cpp @@ -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 + +#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 diff --git a/dom/media/platforms/apple/AppleCMLinker.h b/dom/media/platforms/apple/AppleCMLinker.h new file mode 100644 index 0000000000000..9009d1c07295d --- /dev/null +++ b/dom/media/platforms/apple/AppleCMLinker.h @@ -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 +#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 diff --git a/dom/media/platforms/apple/AppleDecoderModule.cpp b/dom/media/platforms/apple/AppleDecoderModule.cpp index a3cbb562695d6..0117e5c6d2458 100644 --- a/dom/media/platforms/apple/AppleDecoderModule.cpp +++ b/dom/media/platforms/apple/AppleDecoderModule.cpp @@ -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" @@ -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); @@ -64,10 +77,10 @@ already_AddRefed AppleDecoderModule::CreateVideoDecoder( .isEmpty()) { return nullptr; } - + RefPtr 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, @@ -270,10 +283,10 @@ bool AppleDecoderModule::CanCreateHWDecoder(MediaCodec aCodec) { } // VT reports HW decode is supported -- verify by creating an actual decoder if (vtReportsSupport) { - RefPtr decoder; + RefPtr decoder;//Dummy variable MediaResult rv; char *type; - if(__builtin_available(macOS 10.8, *)) { + if(__builtin_available(macOS 10.7, *)) { RefPtr decoder = new AppleVTDecoder(info, nullptr, {}, nullptr, Nothing()); rv = decoder->InitializeSession(); diff --git a/dom/media/platforms/apple/AppleDecoderModule.h b/dom/media/platforms/apple/AppleDecoderModule.h index a4f8c71010070..92decf7278a59 100644 --- a/dom/media/platforms/apple/AppleDecoderModule.h +++ b/dom/media/platforms/apple/AppleDecoderModule.h @@ -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'}; diff --git a/dom/media/platforms/apple/AppleVDADecoder.cpp b/dom/media/platforms/apple/AppleVDADecoder.cpp index 3f0583e32882e..73a05c23df5e1 100644 --- a/dom/media/platforms/apple/AppleVDADecoder.cpp +++ b/dom/media/platforms/apple/AppleVDADecoder.cpp @@ -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" @@ -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) @@ -102,7 +103,6 @@ AppleVDADecoder::~AppleVDADecoder() RefPtr AppleVDADecoder::Init() { - LOG("tryna call initsession\n"); MediaResult rv = InitializeSession(); if (NS_SUCCEEDED(rv)) { @@ -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"); @@ -546,6 +547,8 @@ AppleVDADecoder::InitializeSession() CFDictionaryRef AppleVDADecoder::CreateDecoderSpecification() { + const uint8_t* extradata = mExtraData->Elements(); + int extrasize = mExtraData->Length(); OSType format = 'avc1'; AutoCFRelease avc_width = @@ -560,16 +563,15 @@ AppleVDADecoder::CreateDecoderSpecification() CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &format); - AutoCFRelease avc_data = - CFDataCreate(kCFAllocatorDefault, - mExtraData->Elements(), - AssertedCast(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, diff --git a/dom/media/platforms/apple/AppleVDADecoder.h b/dom/media/platforms/apple/AppleVDADecoder.h index 0bb0f359f2c0f..ec0b9c386bb22 100644 --- a/dom/media/platforms/apple/AppleVDADecoder.h +++ b/dom/media/platforms/apple/AppleVDADecoder.h @@ -9,7 +9,7 @@ #include // For CFDictionaryRef #include // For CMVideoFormatDescriptionRef -#include +#include // For VTDecompressionSessionRef #include "AppleDecoderModule.h" #include "AppleVTDecoder.h" @@ -22,6 +22,7 @@ #include "mozilla/ProfilerUtils.h" #include "mozilla/gfx/Types.h" +#include "VideoDecodeAcceleration/VDADecoder.h" namespace mozilla { @@ -101,19 +102,6 @@ class AppleVDADecoder final : public MediaDataDecoder, void SetSeekThreshold(const media::TimeUnit& aTime) override; - - const RefPtr 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(); @@ -131,13 +119,26 @@ class AppleVDADecoder final : public MediaDataDecoder, AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample); CFDictionaryRef CreateOutputConfiguration(); + + const RefPtr 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 mTaskQueue; diff --git a/dom/media/platforms/apple/AppleVDAFunctions.h b/dom/media/platforms/apple/AppleVDAFunctions.h new file mode 100644 index 0000000000000..98f1710dc7bec --- /dev/null +++ b/dom/media/platforms/apple/AppleVDAFunctions.h @@ -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) diff --git a/dom/media/platforms/apple/AppleVDALinker.cpp b/dom/media/platforms/apple/AppleVDALinker.cpp new file mode 100644 index 0000000000000..ec245c71dba33 --- /dev/null +++ b/dom/media/platforms/apple/AppleVDALinker.cpp @@ -0,0 +1,103 @@ +/* -*- 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 + +#include "AppleVDALinker.h" +#include "nsDebug.h" + +#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) + +namespace mozilla { + +AppleVDALinker::LinkStatus +AppleVDALinker::sLinkStatus = LinkStatus_INIT; + +void* AppleVDALinker::sLink = nullptr; +CFStringRef AppleVDALinker::skPropWidth = nullptr; +CFStringRef AppleVDALinker::skPropHeight = nullptr; +CFStringRef AppleVDALinker::skPropSourceFormat = nullptr; +CFStringRef AppleVDALinker::skPropAVCCData = nullptr; + +#define LINK_FUNC(func) typeof(func) func; +#include "AppleVDAFunctions.h" +#undef LINK_FUNC + +/* static */ bool +AppleVDALinker::Link() +{ + if (sLinkStatus) { + return sLinkStatus == LinkStatus_SUCCEEDED; + } + + const char* dlname = + "/System/Library/Frameworks/VideoDecodeAcceleration.framework/VideoDecodeAcceleration"; + + if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) { + NS_WARNING("Couldn't load VideoDecodeAcceleration framework"); + goto fail; + } + +#define LINK_FUNC(func) \ + func = (typeof(func))dlsym(sLink, #func); \ + if (!func) { \ + NS_WARNING("Couldn't load VideoDecodeAcceleration function " #func ); \ + goto fail; \ + } +#include "AppleVDAFunctions.h" +#undef LINK_FUNC + + skPropWidth = GetIOConst("kVDADecoderConfiguration_Width"); + skPropHeight = GetIOConst("kVDADecoderConfiguration_Height"); + skPropSourceFormat = GetIOConst("kVDADecoderConfiguration_SourceFormat"); + skPropAVCCData = GetIOConst("kVDADecoderConfiguration_avcCData"); + + if (!skPropWidth || !skPropHeight || !skPropSourceFormat || !skPropAVCCData) { + goto fail; + } + + LOG("Loaded VideoDecodeAcceleration framework."); + sLinkStatus = LinkStatus_SUCCEEDED; + return true; + +fail: + Unlink(); + + sLinkStatus = LinkStatus_FAILED; + return false; +} + +/* static */ void +AppleVDALinker::Unlink() +{ + if (sLink) { + LOG("Unlinking VideoDecodeAcceleration framework."); +#define LINK_FUNC(func) \ + func = nullptr; +#include "AppleVDAFunctions.h" +#undef LINK_FUNC + dlclose(sLink); + sLink = nullptr; + skPropWidth = nullptr; + skPropHeight = nullptr; + skPropSourceFormat = nullptr; + skPropAVCCData = nullptr; + sLinkStatus = LinkStatus_INIT; + } +} + +/* static */ CFStringRef +AppleVDALinker::GetIOConst(const char* symbol) +{ + CFStringRef* address = (CFStringRef*)dlsym(sLink, symbol); + if (!address) { + return nullptr; + } + + return *address; +} +} // namespace mozilla +#undef LOG diff --git a/dom/media/platforms/apple/AppleVDALinker.h b/dom/media/platforms/apple/AppleVDALinker.h new file mode 100644 index 0000000000000..0a204a3c8b203 --- /dev/null +++ b/dom/media/platforms/apple/AppleVDALinker.h @@ -0,0 +1,49 @@ +/* -*- 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 AppleVDALinker_h +#define AppleVDALinker_h + +extern "C" { +#pragma GCC visibility push(default) +#include "VideoDecodeAcceleration/VDADecoder.h" +#pragma GCC visibility pop +} + +#include "nscore.h" + +namespace mozilla { + +class AppleVDALinker +{ +public: + static bool Link(); + static void Unlink(); + static CFStringRef skPropWidth; + static CFStringRef skPropHeight; + static CFStringRef skPropSourceFormat; + static CFStringRef skPropAVCCData; + +private: + static void* sLink; + static nsrefcnt sRefCount; + + static enum LinkStatus { + LinkStatus_INIT = 0, + LinkStatus_FAILED, + LinkStatus_SUCCEEDED + } sLinkStatus; + + static CFStringRef GetIOConst(const char* symbol); +}; + +#define LINK_FUNC(func) extern typeof(func)* func; +#include "AppleVDAFunctions.h" +#undef LINK_FUNC + +} // namespace mozilla + +#endif // AppleVDALinker_h diff --git a/dom/media/platforms/apple/AppleVTDecoder.cpp b/dom/media/platforms/apple/AppleVTDecoder.cpp index 6c937eace9c1e..80f0716059e2e 100644 --- a/dom/media/platforms/apple/AppleVTDecoder.cpp +++ b/dom/media/platforms/apple/AppleVTDecoder.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AppleVTDecoder.h" +#include "AppleVTLinker.h" #include #include @@ -227,8 +228,7 @@ void AppleVTDecoder::ProcessDecode(MediaRawData* aSample) { return; } - VTDecodeFrameFlags decodeFlags = - kVTDecodeFrame_EnableAsynchronousDecompression; + VTDecodeFrameFlags decodeFlags = kVTDecodeFrame_EnableAsynchronousDecompression; rv = VTDecompressionSessionDecodeFrame( mSession, sample, decodeFlags, CreateAppleFrameRef(aSample), &infoFlags); if (infoFlags & kVTDecodeInfo_FrameDropped) { @@ -638,7 +638,7 @@ MediaResult AppleVTDecoder::InitializeSession() { CFBooleanRef isUsingHW = nullptr; rv = VTSessionCopyProperty( mSession, - kVTDecompressionPropertyKey_UsingHardwareAcceleratedVideoDecoder, + AppleVTLinker::skPropUsingHWAccel_Decode, kCFAllocatorDefault, &isUsingHW); if (rv == noErr) { mIsHardwareAccelerated = isUsingHW == kCFBooleanTrue; @@ -690,8 +690,12 @@ CFDictionaryRef AppleVTDecoder::CreateDecoderExtensions() { } CFDictionaryRef AppleVTDecoder::CreateDecoderSpecification() { + if (!AppleVTLinker::skPropEnableHWAccel_Decode) { + return nullptr; + } + const void* specKeys[] = { - kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder}; + AppleVTLinker::skPropEnableHWAccel_Decode}; const void* specValues[1]; if (gfx::gfxVars::CanUseHardwareVideoDecoding()) { specValues[0] = kCFBooleanTrue; diff --git a/dom/media/platforms/apple/AppleVTDecoder.h b/dom/media/platforms/apple/AppleVTDecoder.h index 970f71d4c707f..5cf72f8520f72 100644 --- a/dom/media/platforms/apple/AppleVTDecoder.h +++ b/dom/media/platforms/apple/AppleVTDecoder.h @@ -11,6 +11,7 @@ #include // For CMVideoFormatDescriptionRef #include // For VTDecompressionSessionRef +#include "AppleVDADecoder.h" #include "AppleDecoderModule.h" #include "PerformanceRecorder.h" #include "PlatformDecoderModule.h" diff --git a/dom/media/platforms/apple/AppleVTEncoder.cpp b/dom/media/platforms/apple/AppleVTEncoder.cpp index 22585c60ba7f4..a24daf5b195be 100644 --- a/dom/media/platforms/apple/AppleVTEncoder.cpp +++ b/dom/media/platforms/apple/AppleVTEncoder.cpp @@ -4,7 +4,7 @@ * 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 "AppleVTEncoder.h" +#include "AppleVTLinker.h" #include #include @@ -40,8 +40,8 @@ static CFDictionaryRef BuildEncoderSpec(const bool aHardwareNotAllowed, if (aLowLatencyRateControl) { // If doing low-latency rate control, the hardware encoder is required. const void* keys[] = { - kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, - kVTVideoEncoderSpecification_EnableLowLatencyRateControl}; + AppleVTLinker::skPropEnableHWAccel_Encode, + AppleVTLinker::skPropUsingLowLat_Encode}; const void* values[] = {kCFBooleanTrue, kCFBooleanTrue}; static_assert(std::size(keys) == std::size(values), @@ -52,7 +52,7 @@ static CFDictionaryRef BuildEncoderSpec(const bool aHardwareNotAllowed, } } const void* keys[] = { - kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder}; + AppleVTLinker::skPropRequireHWAccel_Encode}; const void* values[] = {aHardwareNotAllowed ? kCFBooleanFalse : kCFBooleanTrue}; @@ -76,7 +76,7 @@ static bool SetAverageBitrate(VTCompressionSessionRef& aSession, AutoCFRelease bitrate( CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &bps)); return VTSessionSetProperty(aSession, - kVTCompressionPropertyKey_AverageBitRate, + AppleVTLinker::skPropAvgBitRate, bitrate) == noErr; } @@ -88,7 +88,7 @@ static bool SetConstantBitrate(VTCompressionSessionRef& aSession, if (__builtin_available(macos 13.0, *)) { int rv = VTSessionSetProperty(aSession, - kVTCompressionPropertyKey_ConstantBitRate, + AppleVTLinker::skPropConstBitRate, bitrate) == noErr; if (rv == kVTPropertyNotSupportedErr) { LOGE("Constant bitrate not supported."); @@ -109,7 +109,7 @@ static bool SetFrameRate(VTCompressionSessionRef& aSession, int64_t aFPS) { AutoCFRelease framerate( CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &aFPS)); return VTSessionSetProperty(aSession, - kVTCompressionPropertyKey_ExpectedFrameRate, + AppleVTLinker::skPropExpFrameRate, framerate) == noErr; } @@ -118,7 +118,7 @@ static bool SetRealtime(VTCompressionSessionRef& aSession, bool aEnabled) { CFBooleanRef enabled = aEnabled ? kCFBooleanTrue : kCFBooleanFalse; OSStatus status = VTSessionSetProperty( - aSession, kVTCompressionPropertyKey_RealTime, enabled); + aSession, AppleVTLinker::skPropCompRealTime, enabled); LOGD("%s real time, status: %d", aEnabled ? "Enable" : "Disable", status); if (status != noErr) { return false; @@ -126,7 +126,7 @@ static bool SetRealtime(VTCompressionSessionRef& aSession, bool aEnabled) { if (__builtin_available(macos 11.0, *)) { status = VTSessionSetProperty( - aSession, kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality, + aSession, AppleVTLinker::skPropSpeedOverQuality, enabled); LOGD("%s PrioritizeEncodingSpeedOverQuality, status: %d", aEnabled ? "Enable" : "Disable", status); @@ -139,7 +139,7 @@ static bool SetRealtime(VTCompressionSessionRef& aSession, bool aEnabled) { AutoCFRelease cf(CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &maxFrameDelayCount)); status = VTSessionSetProperty( - aSession, kVTCompressionPropertyKey_MaxFrameDelayCount, cf); + aSession, AppleVTLinker::skPropMaxFrameDelayCount, cf); LOGD("Set max frame delay count to %d, status: %d", maxFrameDelayCount, status); if (status != noErr && status != kVTPropertyNotSupportedErr) { @@ -154,20 +154,20 @@ static bool SetProfileLevel(VTCompressionSessionRef& aSession, CFStringRef profileLevel = nullptr; switch (aValue) { case H264_PROFILE::H264_PROFILE_BASE: - profileLevel = kVTProfileLevel_H264_Baseline_AutoLevel; + profileLevel = AppleVTLinker::skPropH264_Baseline; break; case H264_PROFILE::H264_PROFILE_MAIN: - profileLevel = kVTProfileLevel_H264_Main_AutoLevel; + profileLevel = AppleVTLinker::skPropH264_Main; break; case H264_PROFILE::H264_PROFILE_HIGH: - profileLevel = kVTProfileLevel_H264_High_AutoLevel; + profileLevel = AppleVTLinker::skPropH264_High; break; default: LOGE("Profile %d not handled", static_cast(aValue)); } return profileLevel ? VTSessionSetProperty( - aSession, kVTCompressionPropertyKey_ProfileLevel, + aSession, AppleVTLinker::skPropCompProfileLevel, profileLevel) == noErr : false; } @@ -220,7 +220,7 @@ RefPtr AppleVTEncoder::Init() { } if (VTSessionSetProperty(mSession, - kVTCompressionPropertyKey_AllowFrameReordering, + AppleVTLinker::skPropAllowFrameReordering, kCFBooleanFalse) != noErr) { LOGE("Couldn't disable bframes"); return InitPromise::CreateAndReject( @@ -277,7 +277,7 @@ RefPtr AppleVTEncoder::Init() { AutoCFRelease cf(CFNumberCreate( kCFAllocatorDefault, kCFNumberFloatType, &baseLayerFPSRatio)); if (VTSessionSetProperty( - mSession, kVTCompressionPropertyKey_BaseLayerFrameRateFraction, + mSession, AppleVTLinker::skPropBaseLayerFRFraction, cf)) { LOGE("Failed to set base layer framerate fraction to %f", baseLayerFPSRatio); @@ -303,7 +303,7 @@ RefPtr AppleVTEncoder::Init() { AutoCFRelease cf( CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &interval)); if (VTSessionSetProperty(mSession, - kVTCompressionPropertyKey_MaxKeyFrameInterval, + AppleVTLinker::skPropMaxKeyFrameInterval, cf) != noErr) { LOGE("Failed to set max keyframe interval"); return InitPromise::CreateAndReject( @@ -328,7 +328,7 @@ RefPtr AppleVTEncoder::Init() { AutoCFRelease isUsingHW = nullptr; status = VTSessionCopyProperty( - mSession, kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder, + mSession, AppleVTLinker::skPropUsingHWAccel_Encode, kCFAllocatorDefault, isUsingHW.receive()); mIsHardwareAccelerated = status == noErr && isUsingHW == kCFBooleanTrue; LOGD("Using hw acceleration: %s", mIsHardwareAccelerated ? "yes" : "no"); @@ -708,7 +708,7 @@ void AppleVTEncoder::ProcessEncode(const RefPtr& aSample) { CFDictionaryRef frameProps = nullptr; if (aSample->mKeyframe) { - CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame}; + CFTypeRef keys[] = {AppleVTLinker::skPropCompKeyForceFrame}; CFTypeRef values[] = {kCFBooleanTrue}; MOZ_ASSERT(std::size(keys) == std::size(values)); frameProps = CFDictionaryCreate( diff --git a/dom/media/platforms/apple/AppleVTFunctions.h b/dom/media/platforms/apple/AppleVTFunctions.h new file mode 100644 index 0000000000000..ccc9833348509 --- /dev/null +++ b/dom/media/platforms/apple/AppleVTFunctions.h @@ -0,0 +1,18 @@ +/* -*- 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 VideoToolbox symbols we use. +LINK_FUNC(VTDecompressionSessionCreate) +LINK_FUNC(VTDecompressionSessionDecodeFrame) +LINK_FUNC(VTDecompressionSessionInvalidate) +LINK_FUNC(VTDecompressionSessionWaitForAsynchronousFrames) +LINK_FUNC(VTSessionCopyProperty) +LINK_FUNC(VTSessionCopySupportedPropertyDictionary) +LINK_FUNC(VTSessionSetProperty) +LINK_FUNC(VTCompressionSessionEncodeFrame) +LINK_FUNC(VTCompressionSessionCreate) +LINK_FUNC(VTCompressionSessionInvalidate) +LINK_FUNC(VTCompressionSessionCompleteFrames) diff --git a/dom/media/platforms/apple/AppleVTLinker.cpp b/dom/media/platforms/apple/AppleVTLinker.cpp new file mode 100644 index 0000000000000..7cd592d1fa359 --- /dev/null +++ b/dom/media/platforms/apple/AppleVTLinker.cpp @@ -0,0 +1,188 @@ +/* -*- 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 + +#include "AppleVTLinker.h" +#include "mozilla/ArrayUtils.h" +#include "nsDebug.h" + +#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) + +namespace mozilla { + +AppleVTLinker::LinkStatus +AppleVTLinker::sLinkStatus = LinkStatus_INIT; + +void* AppleVTLinker::sLink = nullptr; +CFStringRef AppleVTLinker::skPropEnableHWAccel_Decode = nullptr; +CFStringRef AppleVTLinker::skPropUsingHWAccel_Decode = nullptr; +CFStringRef AppleVTLinker::skPropUsingAsyncComp_Decode = nullptr; + +CFStringRef AppleVTLinker::skPropRequireHWAccel_Encode = nullptr; +CFStringRef AppleVTLinker::skPropUsingLowLat_Encode = nullptr; +CFStringRef AppleVTLinker::skPropEnableHWAccel_Encode = nullptr; +CFStringRef AppleVTLinker::skPropUsingHWAccel_Encode = nullptr; +CFStringRef AppleVTLinker::skPropAvgBitRate = nullptr; +CFStringRef AppleVTLinker::skPropConstBitRate = nullptr; +CFStringRef AppleVTLinker::skPropH264_Baseline = nullptr; +CFStringRef AppleVTLinker::skPropH264_Main = nullptr; +CFStringRef AppleVTLinker::skPropH264_High = nullptr; +CFStringRef AppleVTLinker::skPropAllowFrameReordering = nullptr; +CFStringRef AppleVTLinker::skPropBaseLayerFRFraction = nullptr; +CFStringRef AppleVTLinker::skPropMaxKeyFrameInterval = nullptr; +CFStringRef AppleVTLinker::skPropSpeedOverQuality = nullptr; +CFStringRef AppleVTLinker::skPropExpFrameRate = nullptr; +CFStringRef AppleVTLinker::skPropMaxFrameDelayCount = nullptr; +CFStringRef AppleVTLinker::skPropCompRealTime = nullptr; +CFStringRef AppleVTLinker::skPropCompKeyForceFrame = nullptr; +CFStringRef AppleVTLinker::skPropCompProfileLevel = nullptr; + +#define LINK_FUNC(func) typeof(func) func; +#include "AppleVTFunctions.h" +#undef LINK_FUNC + +/* static */ bool +AppleVTLinker::Link() +{ + if (sLinkStatus) { + return sLinkStatus == LinkStatus_SUCCEEDED; + } + + const char* dlnames[] = + { "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox", + "/System/Library/PrivateFrameworks/VideoToolbox.framework/VideoToolbox" }; + bool dlfound = false; + for (size_t i = 0;i < std::size(dlnames);i++) { + if ((sLink = dlopen(dlnames[i], RTLD_NOW | RTLD_LOCAL))) { + dlfound = true; + break; + } + } + if (!dlfound) { + NS_WARNING("Couldn't load VideoToolbox framework"); + goto fail; + } + +#define LINK_FUNC(func) \ + func = (typeof(func))dlsym(sLink, #func); \ + if (!func) { \ + NS_WARNING("Couldn't load VideoToolbox function " #func ); \ + goto fail; \ + } +#include "AppleVTFunctions.h" +#undef LINK_FUNC + + // Will only resolve in 10.9 and later. + skPropEnableHWAccel_Decode = + GetIOConst("kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder"); + skPropUsingHWAccel_Decode = + GetIOConst("kVTDecompressionPropertyKey_UsingHardwareAcceleratedVideoDecoder"); + skPropUsingAsyncComp_Decode = + GetIOConst("kVTDecodeFrame_EnableAsynchronousDecompression"); + + skPropRequireHWAccel_Encode = + GetIOConst("kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder"); + skPropUsingLowLat_Encode = + GetIOConst("kVTVideoEncoderSpecification_EnableLowLatencyRateControl"); + skPropEnableHWAccel_Encode = + GetIOConst("kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder"); + skPropUsingHWAccel_Encode = + GetIOConst("kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder"); + + skPropAvgBitRate = + GetIOConst("kVTCompressionPropertyKey_AverageBitRate"); + skPropConstBitRate = + GetIOConst("kVTCompressionPropertyKey_ConstantBitRate"); + + skPropH264_Baseline = + GetIOConst("kVTProfileLevel_H264_Baseline_AutoLevel"); + skPropH264_Main = + GetIOConst("kVTProfileLevel_H264_Main_AutoLevel"); + skPropH264_High = + GetIOConst("kVTProfileLevel_H264_High_AutoLevel"); + + skPropAllowFrameReordering = + GetIOConst("kVTCompressionPropertyKey_AllowFrameReordering"); + skPropBaseLayerFRFraction = + GetIOConst("kVTCompressionPropertyKey_BaseLayerFrameRateFraction"); + skPropMaxKeyFrameInterval = + GetIOConst("kVTCompressionPropertyKey_MaxKeyFrameInterval"); + skPropSpeedOverQuality = + GetIOConst("kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality"); + + skPropExpFrameRate = + GetIOConst("kVTCompressionPropertyKey_ExpectedFrameRate"); + skPropMaxFrameDelayCount = + GetIOConst("kVTCompressionPropertyKey_MaxFrameDelayCount"); + skPropCompRealTime = + GetIOConst("kVTCompressionPropertyKey_RealTime"); + skPropCompKeyForceFrame = + GetIOConst("kVTEncodeFrameOptionKey_ForceKeyFrame"); + + skPropCompProfileLevel = + GetIOConst("kVTCompressionPropertyKey_ProfileLevel"); + + LOG("Loaded VideoToolbox framework."); + sLinkStatus = LinkStatus_SUCCEEDED; + return true; + +fail: + Unlink(); + + sLinkStatus = LinkStatus_FAILED; + return false; +} + +/* static */ void +AppleVTLinker::Unlink() +{ + if (sLink) { + LOG("Unlinking VideoToolbox framework."); +#define LINK_FUNC(func) \ + func = nullptr; +#include "AppleVTFunctions.h" +#undef LINK_FUNC + dlclose(sLink); + sLink = nullptr; + skPropEnableHWAccel_Decode = nullptr; + skPropUsingHWAccel_Decode = nullptr; + skPropUsingAsyncComp_Decode = nullptr; + skPropRequireHWAccel_Encode = nullptr; + skPropUsingLowLat_Encode = nullptr; + skPropEnableHWAccel_Encode = nullptr; + skPropUsingHWAccel_Encode = nullptr; + skPropAvgBitRate = nullptr; + skPropConstBitRate = nullptr; + skPropH264_Baseline = nullptr; + skPropH264_Main = nullptr; + skPropH264_High = nullptr; + skPropAllowFrameReordering = nullptr; + skPropBaseLayerFRFraction = nullptr; + skPropMaxKeyFrameInterval = nullptr; + skPropSpeedOverQuality = nullptr; + skPropExpFrameRate = nullptr; + skPropMaxFrameDelayCount = nullptr; + skPropCompRealTime = nullptr; + skPropCompKeyForceFrame = nullptr; + skPropCompProfileLevel = nullptr; + sLinkStatus = LinkStatus_INIT; + } +} + +/* static */ CFStringRef +AppleVTLinker::GetIOConst(const char* symbol) +{ + CFStringRef* address = (CFStringRef*)dlsym(sLink, symbol); + if (!address) { + return nullptr; + } + + return *address; +} + +} // namespace mozilla +#undef LOG diff --git a/dom/media/platforms/apple/AppleVTLinker.h b/dom/media/platforms/apple/AppleVTLinker.h new file mode 100644 index 0000000000000..78a109cb37f11 --- /dev/null +++ b/dom/media/platforms/apple/AppleVTLinker.h @@ -0,0 +1,70 @@ +/* -*- 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 AppleVTLinker_h +#define AppleVTLinker_h + +extern "C" { +#pragma GCC visibility push(default) +#include +#pragma GCC visibility pop +} + +#include "nscore.h" + +namespace mozilla { + +class AppleVTLinker +{ +public: + static bool Link(); + static void Unlink(); + static CFStringRef skPropEnableHWAccel_Decode; + static CFStringRef skPropUsingHWAccel_Decode; + static CFStringRef skPropUsingAsyncComp_Decode; + + static CFStringRef skPropEnableHWAccel_Encode; + static CFStringRef skPropUsingLowLat_Encode; + static CFStringRef skPropUsingHWAccel_Encode; + static CFStringRef skPropRequireHWAccel_Encode; + static CFStringRef skPropCompKeyForceFrame; + + static CFStringRef skPropAvgBitRate; + static CFStringRef skPropConstBitRate; + + static CFStringRef skPropH264_Baseline; + static CFStringRef skPropH264_Main; + static CFStringRef skPropH264_High; + + static CFStringRef skPropAllowFrameReordering; + static CFStringRef skPropBaseLayerFRFraction; + static CFStringRef skPropMaxKeyFrameInterval; + + static CFStringRef skPropMaxFrameDelayCount; + static CFStringRef skPropSpeedOverQuality; + static CFStringRef skPropExpFrameRate; + static CFStringRef skPropCompRealTime; + + static CFStringRef skPropCompProfileLevel; +private: + static void* sLink; + + static enum LinkStatus { + LinkStatus_INIT = 0, + LinkStatus_FAILED, + LinkStatus_SUCCEEDED + } sLinkStatus; + + static CFStringRef GetIOConst(const char* symbol); +}; + +#define LINK_FUNC(func) extern typeof(func)* func; +#include "AppleVTFunctions.h" +#undef LINK_FUNC + +} // namespace mozilla + +#endif // AppleVTLinker_h diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build index a6e2b42879082..8b40df284c287 100644 --- a/dom/media/platforms/moz.build +++ b/dom/media/platforms/moz.build @@ -87,11 +87,14 @@ if CONFIG["MOZ_APPLEMEDIA"]: ] UNIFIED_SOURCES += [ "apple/AppleATDecoder.cpp", + "apple/AppleCMLinker.cpp", "apple/AppleDecoderModule.cpp", "apple/AppleEncoderModule.cpp", 'apple/AppleVDADecoder.cpp', + 'apple/AppleVDALinker.cpp', "apple/AppleVTDecoder.cpp", "apple/AppleVTEncoder.cpp", + "apple/AppleVTLinker.cpp", ] LOCAL_INCLUDES += [ "/media/libyuv/libyuv/include", diff --git a/security/certverifier/NSSCertDBTrustDomain.cpp b/security/certverifier/NSSCertDBTrustDomain.cpp index c373396ccd5de..7b5e872d81d40 100644 --- a/security/certverifier/NSSCertDBTrustDomain.cpp +++ b/security/certverifier/NSSCertDBTrustDomain.cpp @@ -51,6 +51,10 @@ #include "secder.h" #include "secerr.h" +#ifdef MOZ_WIDGET_COCOA +# include "nsCocoaFeatures.h" +#endif + #include "TrustOverrideUtils.h" #include "TrustOverride-AppleGoogleDigiCertData.inc" #include "TrustOverride-SymantecData.inc" @@ -1813,6 +1817,12 @@ bool LoadIPCClientCertsModule(const nsCString& dir) { } bool LoadOSClientCertsModule(const nsCString& dir) { +#ifdef MOZ_WIDGET_COCOA + // osclientcerts requires macOS 10.14 or later + if (!nsCocoaFeatures::OnMojaveOrLater()) { + return false; + } +#endif nsLiteralCString params = StaticPrefs::security_osclientcerts_assume_rsa_pss_support() ? "RSA-PSS"_ns diff --git a/security/sandbox/common/test/SandboxTestingChildTests.h b/security/sandbox/common/test/SandboxTestingChildTests.h index 8be48789f1560..fb521a711133f 100644 --- a/security/sandbox/common/test/SandboxTestingChildTests.h +++ b/security/sandbox/common/test/SandboxTestingChildTests.h @@ -8,6 +8,9 @@ #include "mozilla/StaticPrefs_security.h" #include "mozilla/ipc/UtilityProcessSandboxing.h" +#ifdef XP_MACOSX +# include "nsCocoaFeatures.h" +#endif #include "nsXULAppAPI.h" #ifdef XP_UNIX @@ -248,7 +251,12 @@ void RunMacTestLaunchProcess(SandboxTestingChild* child, }); // Test that launching an application using LSOpenCFURLRef fails - char* uri = const_cast("/System/Applications/Utilities/Console.app"); + char* uri; + if (nsCocoaFeatures::OnCatalinaOrLater()) { + uri = const_cast("/System/Applications/Utilities/Console.app"); + } else { + uri = const_cast("/Applications/Utilities/Console.app"); + } CFStringRef filePath = ::CFStringCreateWithCString(kCFAllocatorDefault, uri, kCFStringEncodingUTF8); CFURLRef urlRef = ::CFURLCreateWithFileSystemPath(