/* 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 "RemoteEncoderModule.h" #include "RemoteDecodeUtils.h" #include "RemoteMediaDataEncoder.h" #include "RemoteMediaManagerChild.h" #ifdef MOZ_APPLEMEDIA # include "AppleUtils.h" #endif namespace mozilla { extern LazyLogModule sPEMLog; RemoteEncoderModule::RemoteEncoderModule(RemoteMediaIn aLocation) : mLocation(aLocation) {} /* static */ already_AddRefed RemoteEncoderModule::Create(RemoteMediaIn aLocation) { if (!XRE_IsContentProcess()) { // For now, the RemoteEncoderModule is only available in the content // process. MOZ_ASSERT_UNREACHABLE("Should not be created outside content process."); return nullptr; } RemoteMediaManagerChild::Init(); return MakeAndAddRef(aLocation); } const char* RemoteEncoderModule::GetName() const { switch (mLocation) { case RemoteMediaIn::RddProcess: return "Remote Encoder Module (RDD)"; case RemoteMediaIn::GpuProcess: return "Remote Encoder Module (GPU)"; case RemoteMediaIn::UtilityProcess_Generic: return "Remote Encoder Module (Utility)"; case RemoteMediaIn::UtilityProcess_AppleMedia: return "Remote Encoder Module (Utility AppleMedia)"; case RemoteMediaIn::UtilityProcess_WMF: return "Remote Encoder Module (Utility WMF)"; default: return "Remote Encoder Module"; } } already_AddRefed RemoteEncoderModule::CreateEncoder( const EncoderConfig& aConfig, const RefPtr& aTaskQueue) const { nsCOMPtr thread = RemoteMediaManagerChild::GetManagerThread(); if (!thread) { // Shutdown has begun. MOZ_LOG(sPEMLog, LogLevel::Debug, ("Sandbox %s encoder requested codec %d after shutdown", RemoteMediaInToStr(mLocation), static_cast(aConfig.mCodec))); return nullptr; } auto encoder = MakeRefPtr(std::move(thread), mLocation); // This returns a promise, but we know that once it returns, the only // interactions the caller can do will require a dispatch to the manager // thread. The necessary IPDL constructor events are already queued so the // order of events is preserved. RemoteMediaManagerChild::InitializeEncoder(RefPtr{encoder}, aConfig); return encoder.forget(); } RefPtr RemoteEncoderModule::AsyncCreateEncoder(const EncoderConfig& aEncoderConfig, const RefPtr& aTaskQueue) { nsCOMPtr thread = RemoteMediaManagerChild::GetManagerThread(); if (!thread) { // Shutdown has begun. MOZ_LOG(sPEMLog, LogLevel::Debug, ("Sandbox %s encoder requested codec %d after shutdown", RemoteMediaInToStr(mLocation), static_cast(aEncoderConfig.mCodec))); return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject( MediaResult(NS_ERROR_DOM_MEDIA_CANCELED, "Remote manager not available"), __func__); } auto encoder = MakeRefPtr(std::move(thread), mLocation); return RemoteMediaManagerChild::InitializeEncoder(std::move(encoder), aEncoderConfig); } media::EncodeSupportSet RemoteEncoderModule::Supports( const EncoderConfig& aConfig) const { if (!CanLikelyEncode(aConfig)) { return media::EncodeSupportSet{}; } // TODO(aosmond): The platform specific criteria were copied from the various // PEMs in order to pass the WebCodecs WPTs but should eventually be rewritten // to generically support any PEM. #ifdef MOZ_APPLEMEDIA // Only two temporal layers supported, and only from 11.3 and more recent if (aConfig.mCodec == CodecType::H264 && (aConfig.mScalabilityMode == ScalabilityMode::L1T3 || (aConfig.mScalabilityMode != ScalabilityMode::None && !OSSupportsSVC()))) { return media::EncodeSupportSet{}; } #endif #ifdef XP_WIN if (aConfig.mScalabilityMode != ScalabilityMode::None) { switch (aConfig.mCodec) { case CodecType::H264: case CodecType::VP8: case CodecType::VP9: // The codec type support check is sufficient. break; case CodecType::AV1: if (aConfig.mBitrateMode != BitrateMode::Constant) { return media::EncodeSupportSet{}; } break; default: return media::EncodeSupportSet{}; } } #endif return SupportsCodec(aConfig.mCodec); } media::EncodeSupportSet RemoteEncoderModule::SupportsCodec( CodecType aCodecType) const { media::EncodeSupportSet supports = RemoteMediaManagerChild::Supports(mLocation, aCodecType); MOZ_LOG(sPEMLog, LogLevel::Debug, ("Sandbox %s encoder %s requested codec %d", RemoteMediaInToStr(mLocation), supports.isEmpty() ? "supports" : "rejects", static_cast(aCodecType))); return supports; } } // namespace mozilla