RemoteEncoderModule.cpp (5362B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "RemoteEncoderModule.h" 8 9 #include "RemoteDecodeUtils.h" 10 #include "RemoteMediaDataEncoderChild.h" 11 #include "RemoteMediaManagerChild.h" 12 13 #ifdef MOZ_APPLEMEDIA 14 # include "AppleUtils.h" 15 #endif 16 17 namespace mozilla { 18 19 extern LazyLogModule sPEMLog; 20 21 RemoteEncoderModule::RemoteEncoderModule(RemoteMediaIn aLocation) 22 : mLocation(aLocation) {} 23 24 /* static */ already_AddRefed<PlatformEncoderModule> 25 RemoteEncoderModule::Create(RemoteMediaIn aLocation) { 26 if (!XRE_IsContentProcess()) { 27 // For now, the RemoteEncoderModule is only available in the content 28 // process. 29 MOZ_ASSERT_UNREACHABLE("Should not be created outside content process."); 30 return nullptr; 31 } 32 33 RemoteMediaManagerChild::Init(); 34 return MakeAndAddRef<RemoteEncoderModule>(aLocation); 35 } 36 37 const char* RemoteEncoderModule::GetName() const { 38 switch (mLocation) { 39 case RemoteMediaIn::RddProcess: 40 return "Remote Encoder Module (RDD)"; 41 case RemoteMediaIn::GpuProcess: 42 return "Remote Encoder Module (GPU)"; 43 case RemoteMediaIn::UtilityProcess_Generic: 44 return "Remote Encoder Module (Utility)"; 45 case RemoteMediaIn::UtilityProcess_AppleMedia: 46 return "Remote Encoder Module (Utility AppleMedia)"; 47 case RemoteMediaIn::UtilityProcess_WMF: 48 return "Remote Encoder Module (Utility WMF)"; 49 default: 50 return "Remote Encoder Module"; 51 } 52 } 53 54 already_AddRefed<MediaDataEncoder> RemoteEncoderModule::CreateEncoder( 55 const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) const { 56 nsCOMPtr<nsISerialEventTarget> thread = 57 RemoteMediaManagerChild::GetManagerThread(); 58 if (!thread) { 59 // Shutdown has begun. 60 MOZ_LOG(sPEMLog, LogLevel::Debug, 61 ("Sandbox %s encoder requested codec %d after shutdown", 62 RemoteMediaInToStr(mLocation), static_cast<int>(aConfig.mCodec))); 63 return nullptr; 64 } 65 66 auto encoder = 67 MakeRefPtr<RemoteMediaDataEncoderChild>(std::move(thread), mLocation); 68 69 // This returns a promise, but we know that once it returns, the only 70 // interactions the caller can do will require a dispatch to the manager 71 // thread. The necessary IPDL constructor events are already queued so the 72 // order of events is preserved. 73 RemoteMediaManagerChild::InitializeEncoder(RefPtr{encoder}, aConfig); 74 75 return encoder.forget(); 76 } 77 78 RefPtr<PlatformEncoderModule::CreateEncoderPromise> 79 RemoteEncoderModule::AsyncCreateEncoder(const EncoderConfig& aEncoderConfig, 80 const RefPtr<TaskQueue>& aTaskQueue) { 81 nsCOMPtr<nsISerialEventTarget> thread = 82 RemoteMediaManagerChild::GetManagerThread(); 83 if (!thread) { 84 // Shutdown has begun. 85 MOZ_LOG(sPEMLog, LogLevel::Debug, 86 ("Sandbox %s encoder requested codec %d after shutdown", 87 RemoteMediaInToStr(mLocation), 88 static_cast<int>(aEncoderConfig.mCodec))); 89 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject( 90 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED, 91 "Remote manager not available"), 92 __func__); 93 } 94 95 auto encoder = 96 MakeRefPtr<RemoteMediaDataEncoderChild>(std::move(thread), mLocation); 97 return RemoteMediaManagerChild::InitializeEncoder(std::move(encoder), 98 aEncoderConfig); 99 } 100 101 media::EncodeSupportSet RemoteEncoderModule::Supports( 102 const EncoderConfig& aConfig) const { 103 if (!CanLikelyEncode(aConfig)) { 104 return media::EncodeSupportSet{}; 105 } 106 107 // TODO(aosmond): The platform specific criteria were copied from the various 108 // PEMs in order to pass the WebCodecs WPTs but should eventually be rewritten 109 // to generically support any PEM. 110 111 #ifdef MOZ_APPLEMEDIA 112 // Only two temporal layers supported, and only from 11.3 and more recent 113 if (aConfig.mCodec == CodecType::H264 && 114 (aConfig.mScalabilityMode == ScalabilityMode::L1T3 || 115 (aConfig.mScalabilityMode != ScalabilityMode::None && 116 !OSSupportsSVC()))) { 117 return media::EncodeSupportSet{}; 118 } 119 #endif 120 121 #ifdef XP_WIN 122 if (aConfig.mScalabilityMode != ScalabilityMode::None) { 123 switch (aConfig.mCodec) { 124 case CodecType::H264: 125 case CodecType::VP8: 126 case CodecType::VP9: 127 // The codec type support check is sufficient. 128 break; 129 case CodecType::AV1: 130 if (aConfig.mBitrateMode != BitrateMode::Constant) { 131 return media::EncodeSupportSet{}; 132 } 133 break; 134 default: 135 return media::EncodeSupportSet{}; 136 } 137 } 138 #endif 139 140 return SupportsCodec(aConfig.mCodec); 141 } 142 143 media::EncodeSupportSet RemoteEncoderModule::SupportsCodec( 144 CodecType aCodecType) const { 145 media::EncodeSupportSet supports = 146 RemoteMediaManagerChild::Supports(mLocation, aCodecType); 147 MOZ_LOG(sPEMLog, LogLevel::Debug, 148 ("Sandbox %s encoder %s requested codec %d", 149 RemoteMediaInToStr(mLocation), 150 supports.isEmpty() ? "supports" : "rejects", 151 static_cast<int>(aCodecType))); 152 return supports; 153 } 154 155 } // namespace mozilla