tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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