ChromiumCDMVideoDecoder.cpp (6869B)
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 "ChromiumCDMVideoDecoder.h" 8 9 #include "ChromiumCDMProxy.h" 10 #include "GMPService.h" 11 #include "GMPVideoDecoder.h" 12 #include "MP4Decoder.h" 13 #include "VPXDecoder.h" 14 #include "content_decryption_module.h" 15 #ifdef MOZ_AV1 16 # include "AOMDecoder.h" 17 #endif 18 19 namespace mozilla { 20 21 ChromiumCDMVideoDecoder::ChromiumCDMVideoDecoder( 22 const GMPVideoDecoderParams& aParams, CDMProxy* aCDMProxy) 23 : mCDMParent(aCDMProxy->AsChromiumCDMProxy()->GetCDMParent()), 24 mConfig(aParams.mConfig), 25 mCrashHelper(aParams.mCrashHelper), 26 mGMPThread(GetGMPThread()), 27 mImageContainer(aParams.mImageContainer), 28 mKnowsCompositor(aParams.mKnowsCompositor) {} 29 30 ChromiumCDMVideoDecoder::~ChromiumCDMVideoDecoder() = default; 31 32 static uint32_t ToCDMH264Profile(uint8_t aProfile) { 33 switch (aProfile) { 34 case 66: 35 return cdm::VideoCodecProfile::kH264ProfileBaseline; 36 case 77: 37 return cdm::VideoCodecProfile::kH264ProfileMain; 38 case 88: 39 return cdm::VideoCodecProfile::kH264ProfileExtended; 40 case 100: 41 return cdm::VideoCodecProfile::kH264ProfileHigh; 42 case 110: 43 return cdm::VideoCodecProfile::kH264ProfileHigh10; 44 case 122: 45 return cdm::VideoCodecProfile::kH264ProfileHigh422; 46 case 144: 47 return cdm::VideoCodecProfile::kH264ProfileHigh444Predictive; 48 } 49 return cdm::VideoCodecProfile::kUnknownVideoCodecProfile; 50 } 51 52 #ifdef MOZ_AV1 53 static uint32_t ToCDMAV1Profile(uint8_t aProfile) { 54 switch (aProfile) { 55 case 0: 56 return cdm::VideoCodecProfile::kAv1ProfileMain; 57 case 1: 58 return cdm::VideoCodecProfile::kAv1ProfileHigh; 59 case 2: 60 return cdm::VideoCodecProfile::kAv1ProfilePro; 61 default: 62 return cdm::VideoCodecProfile::kUnknownVideoCodecProfile; 63 } 64 } 65 #endif 66 67 RefPtr<MediaDataDecoder::InitPromise> ChromiumCDMVideoDecoder::Init() { 68 if (!mCDMParent) { 69 // Must have failed to get the CDMParent from the ChromiumCDMProxy 70 // in our constructor; the MediaKeys must have shut down the CDM 71 // before we had a chance to start up the decoder. 72 return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); 73 } 74 75 gmp::CDMVideoDecoderConfig config; 76 if (MP4Decoder::IsH264(mConfig.mMimeType)) { 77 config.mCodec() = cdm::VideoCodec::kCodecH264; 78 config.mProfile() = 79 ToCDMH264Profile(mConfig.mExtraData->SafeElementAt(1, 0)); 80 config.mExtraData() = mConfig.mExtraData->Clone(); 81 mConvertToAnnexB = true; 82 #ifdef MOZ_AV1 83 } else if (AOMDecoder::IsAV1(mConfig.mMimeType)) { 84 AOMDecoder::AV1SequenceInfo seqInfo; 85 MediaResult seqHdrResult; 86 AOMDecoder::TryReadAV1CBox(mConfig.mExtraData, seqInfo, seqHdrResult); 87 config.mCodec() = cdm::VideoCodec::kCodecAv1; 88 config.mProfile() = NS_SUCCEEDED(seqHdrResult.Code()) 89 ? ToCDMAV1Profile(seqInfo.mProfile) 90 : cdm::VideoCodecProfile::kUnknownVideoCodecProfile; 91 #endif 92 } else if (VPXDecoder::IsVP8(mConfig.mMimeType)) { 93 config.mCodec() = cdm::VideoCodec::kCodecVp8; 94 config.mProfile() = cdm::VideoCodecProfile::kProfileNotNeeded; 95 } else if (VPXDecoder::IsVP9(mConfig.mMimeType)) { 96 config.mCodec() = cdm::VideoCodec::kCodecVp9; 97 config.mProfile() = cdm::VideoCodecProfile::kProfileNotNeeded; 98 } else { 99 return MediaDataDecoder::InitPromise::CreateAndReject( 100 NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); 101 } 102 config.mImageWidth() = mConfig.mImage.width; 103 config.mImageHeight() = mConfig.mImage.height; 104 config.mEncryptionScheme() = cdm::EncryptionScheme::kUnencrypted; 105 switch (mConfig.mCrypto.mCryptoScheme) { 106 case CryptoScheme::None: 107 break; 108 case CryptoScheme::Cenc: 109 config.mEncryptionScheme() = cdm::EncryptionScheme::kCenc; 110 break; 111 case CryptoScheme::Cbcs: 112 case CryptoScheme::Cbcs_1_9: 113 config.mEncryptionScheme() = cdm::EncryptionScheme::kCbcs; 114 break; 115 default: 116 MOZ_ASSERT_UNREACHABLE("Should not have unrecognized encryption type"); 117 break; 118 } 119 120 RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent; 121 VideoInfo info = mConfig; 122 RefPtr<layers::ImageContainer> imageContainer = mImageContainer; 123 RefPtr<layers::KnowsCompositor> knowsCompositor = mKnowsCompositor; 124 return InvokeAsync(mGMPThread, __func__, 125 [cdm, config, info, imageContainer, knowsCompositor]() { 126 return cdm->InitializeVideoDecoder( 127 config, info, imageContainer, knowsCompositor); 128 }); 129 } 130 131 nsCString ChromiumCDMVideoDecoder::GetDescriptionName() const { 132 return "chromium cdm video decoder"_ns; 133 } 134 135 nsCString ChromiumCDMVideoDecoder::GetCodecName() const { 136 if (MP4Decoder::IsH264(mConfig.mMimeType)) { 137 return "h264"_ns; 138 } 139 #ifdef MOZ_AV1 140 if (AOMDecoder::IsAV1(mConfig.mMimeType)) { 141 return "av1"_ns; 142 } 143 #endif 144 if (VPXDecoder::IsVP8(mConfig.mMimeType)) { 145 return "vp8"_ns; 146 } 147 if (VPXDecoder::IsVP9(mConfig.mMimeType)) { 148 return "vp9"_ns; 149 } 150 return "unknown"_ns; 151 } 152 153 MediaDataDecoder::ConversionRequired ChromiumCDMVideoDecoder::NeedsConversion() 154 const { 155 return mConvertToAnnexB ? ConversionRequired::kNeedAnnexB 156 : ConversionRequired::kNeedNone; 157 } 158 159 RefPtr<MediaDataDecoder::DecodePromise> ChromiumCDMVideoDecoder::Decode( 160 MediaRawData* aSample) { 161 RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent; 162 RefPtr<MediaRawData> sample = aSample; 163 return InvokeAsync(mGMPThread, __func__, [cdm, sample]() { 164 return cdm->DecryptAndDecodeFrame(sample); 165 }); 166 } 167 168 RefPtr<MediaDataDecoder::FlushPromise> ChromiumCDMVideoDecoder::Flush() { 169 MOZ_ASSERT(mCDMParent); 170 RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent; 171 return InvokeAsync(mGMPThread, __func__, 172 [cdm]() { return cdm->FlushVideoDecoder(); }); 173 } 174 175 RefPtr<MediaDataDecoder::DecodePromise> ChromiumCDMVideoDecoder::Drain() { 176 MOZ_ASSERT(mCDMParent); 177 RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent; 178 return InvokeAsync(mGMPThread, __func__, [cdm]() { return cdm->Drain(); }); 179 } 180 181 RefPtr<ShutdownPromise> ChromiumCDMVideoDecoder::Shutdown() { 182 if (!mCDMParent) { 183 // Must have failed to get the CDMParent from the ChromiumCDMProxy 184 // in our constructor; the MediaKeys must have shut down the CDM 185 // before we had a chance to start up the decoder. 186 return ShutdownPromise::CreateAndResolve(true, __func__); 187 } 188 RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent; 189 return InvokeAsync(mGMPThread, __func__, 190 [cdm]() { return cdm->ShutdownVideoDecoder(); }); 191 } 192 193 } // namespace mozilla