DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (56e7b9127e89)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
/* -*- 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 "ChromiumCDMVideoDecoder.h"
#include "ChromiumCDMProxy.h"
#include "content_decryption_module.h"
#include "GMPService.h"
#include "GMPVideoDecoder.h"
#include "MP4Decoder.h"
#include "VPXDecoder.h"

namespace mozilla {

ChromiumCDMVideoDecoder::ChromiumCDMVideoDecoder(
  const GMPVideoDecoderParams& aParams,
  CDMProxy* aCDMProxy)
  : mCDMParent(aCDMProxy->AsChromiumCDMProxy()->GetCDMParent())
  , mConfig(aParams.mConfig)
  , mCrashHelper(aParams.mCrashHelper)
  , mGMPThread(GetGMPAbstractThread())
  , mImageContainer(aParams.mImageContainer)
{
}

ChromiumCDMVideoDecoder::~ChromiumCDMVideoDecoder()
{
}

static uint32_t
ToCDMH264Profile(uint8_t aProfile)
{
  switch (aProfile) {
    case 66:
      return cdm::VideoDecoderConfig::kH264ProfileBaseline;
    case 77:
      return cdm::VideoDecoderConfig::kH264ProfileMain;
    case 88:
      return cdm::VideoDecoderConfig::kH264ProfileExtended;
    case 100:
      return cdm::VideoDecoderConfig::kH264ProfileHigh;
    case 110:
      return cdm::VideoDecoderConfig::kH264ProfileHigh10;
    case 122:
      return cdm::VideoDecoderConfig::kH264ProfileHigh422;
    case 144:
      return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
  }
  return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
}

RefPtr<MediaDataDecoder::InitPromise>
ChromiumCDMVideoDecoder::Init()
{
  if (!mCDMParent) {
    // Must have failed to get the CDMParent from the ChromiumCDMProxy
    // in our constructor; the MediaKeys must have shut down the CDM
    // before we had a chance to start up the decoder.
    return InitPromise::CreateAndReject(
      NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
  }

  gmp::CDMVideoDecoderConfig config;
  if (MP4Decoder::IsH264(mConfig.mMimeType)) {
    config.mCodec() = cdm::VideoDecoderConfig::kCodecH264;
    config.mProfile() =
      ToCDMH264Profile(mConfig.mExtraData->SafeElementAt(1, 0));
    config.mExtraData() = *mConfig.mExtraData;
    mConvertToAnnexB = true;
  } else if (VPXDecoder::IsVP8(mConfig.mMimeType)) {
    config.mCodec() = cdm::VideoDecoderConfig::kCodecVp8;
    config.mProfile() = cdm::VideoDecoderConfig::kProfileNotNeeded;
  } else if (VPXDecoder::IsVP9(mConfig.mMimeType)) {
    config.mCodec() = cdm::VideoDecoderConfig::kCodecVp9;
    config.mProfile() = cdm::VideoDecoderConfig::kProfileNotNeeded;
  } else {
    return MediaDataDecoder::InitPromise::CreateAndReject(
      NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
  }
  config.mImageWidth() = mConfig.mImage.width;
  config.mImageHeight() = mConfig.mImage.height;

  RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
  VideoInfo info = mConfig;
  RefPtr<layers::ImageContainer> imageContainer = mImageContainer;
  return InvokeAsync(
    mGMPThread, __func__, [cdm, config, info, imageContainer]() {
      return cdm->InitializeVideoDecoder(config, info, imageContainer);
    });
}

nsCString
ChromiumCDMVideoDecoder::GetDescriptionName() const
{
  return NS_LITERAL_CSTRING("chromium cdm video decoder");
}

MediaDataDecoder::ConversionRequired
ChromiumCDMVideoDecoder::NeedsConversion() const
{
  return mConvertToAnnexB ? ConversionRequired::kNeedAnnexB
                          : ConversionRequired::kNeedNone;
}

RefPtr<MediaDataDecoder::DecodePromise>
ChromiumCDMVideoDecoder::Decode(MediaRawData* aSample)
{
  RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
  RefPtr<MediaRawData> sample = aSample;
  return InvokeAsync(mGMPThread, __func__, [cdm, sample]() {
    return cdm->DecryptAndDecodeFrame(sample);
  });
}

RefPtr<MediaDataDecoder::FlushPromise>
ChromiumCDMVideoDecoder::Flush()
{
  MOZ_ASSERT(mCDMParent);
  RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
  return InvokeAsync(
    mGMPThread, __func__, [cdm]() { return cdm->FlushVideoDecoder(); });
}

RefPtr<MediaDataDecoder::DecodePromise>
ChromiumCDMVideoDecoder::Drain()
{
  MOZ_ASSERT(mCDMParent);
  RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
  return InvokeAsync(mGMPThread, __func__, [cdm]() { return cdm->Drain(); });
}

RefPtr<ShutdownPromise>
ChromiumCDMVideoDecoder::Shutdown()
{
  if (!mCDMParent) {
    // Must have failed to get the CDMParent from the ChromiumCDMProxy
    // in our constructor; the MediaKeys must have shut down the CDM
    // before we had a chance to start up the decoder.
    return ShutdownPromise::CreateAndResolve(true, __func__);
  }
  RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
  return InvokeAsync(
    mGMPThread, __func__, [cdm]() { return cdm->ShutdownVideoDecoder(); });
}

} // namespace mozilla