tor-browser

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

WebrtcVideoCodecFactory.cpp (7367B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "WebrtcVideoCodecFactory.h"
      7 
      8 #include "GmpVideoCodec.h"
      9 #include "MediaDataCodec.h"
     10 #include "VideoConduit.h"
     11 #include "mozilla/StaticPrefs_media.h"
     12 
     13 // libwebrtc includes
     14 #include "api/rtp_headers.h"
     15 #include "api/video_codecs/video_codec.h"
     16 #include "api/video_codecs/video_encoder_software_fallback_wrapper.h"
     17 #include "media/engine/simulcast_encoder_adapter.h"
     18 #include "modules/video_coding/codecs/av1/dav1d_decoder.h"
     19 #include "modules/video_coding/codecs/av1/libaom_av1_encoder.h"
     20 #include "modules/video_coding/codecs/vp8/include/vp8.h"
     21 #include "modules/video_coding/codecs/vp9/include/vp9.h"
     22 
     23 namespace mozilla {
     24 
     25 std::unique_ptr<webrtc::VideoDecoder> WebrtcVideoDecoderFactory::Create(
     26    const webrtc::Environment& aEnv, const webrtc::SdpVideoFormat& aFormat) {
     27  std::unique_ptr<webrtc::VideoDecoder> decoder;
     28  auto type = webrtc::PayloadStringToCodecType(aFormat.name);
     29 
     30  // Attempt to create a decoder using MediaDataDecoder.
     31  decoder.reset(MediaDataCodec::CreateDecoder(type, mTrackingId));
     32  if (decoder) {
     33    return decoder;
     34  }
     35 
     36  switch (type) {
     37    case webrtc::VideoCodecType::kVideoCodecH264: {
     38      // Get an external decoder
     39      auto gmpDecoder =
     40          WrapUnique(GmpVideoCodec::CreateDecoder(mPCHandle, mTrackingId));
     41      mCreatedGmpPluginEvent.Forward(*gmpDecoder->InitPluginEvent());
     42      mReleasedGmpPluginEvent.Forward(*gmpDecoder->ReleasePluginEvent());
     43      decoder.reset(gmpDecoder.release());
     44      break;
     45    }
     46 
     47    // Use libvpx decoders as fallbacks.
     48    case webrtc::VideoCodecType::kVideoCodecVP8:
     49      if (!decoder) {
     50        decoder = webrtc::CreateVp8Decoder(aEnv);
     51      }
     52      break;
     53    case webrtc::VideoCodecType::kVideoCodecVP9:
     54      decoder = webrtc::VP9Decoder::Create();
     55      break;
     56    case webrtc::VideoCodecType::kVideoCodecAV1:
     57      decoder = webrtc::CreateDav1dDecoder();
     58      break;
     59    default:
     60      break;
     61  }
     62 
     63  return decoder;
     64 }
     65 
     66 std::unique_ptr<webrtc::VideoEncoder> WebrtcVideoEncoderFactory::Create(
     67    const webrtc::Environment& aEnv, const webrtc::SdpVideoFormat& aFormat) {
     68  if (!mInternalFactory->Supports(aFormat)) {
     69    return nullptr;
     70  }
     71  auto type = webrtc::PayloadStringToCodecType(aFormat.name);
     72  switch (type) {
     73    case webrtc::VideoCodecType::kVideoCodecGeneric:
     74    case webrtc::VideoCodecType::kVideoCodecH265:
     75      MOZ_CRASH("Unimplemented codec");
     76    case webrtc::VideoCodecType::kVideoCodecAV1:
     77      if (StaticPrefs::media_webrtc_simulcast_av1_enabled()) {
     78        return std::make_unique<webrtc::SimulcastEncoderAdapter>(
     79            aEnv, mInternalFactory.get(), nullptr, aFormat);
     80      }
     81      break;
     82    case webrtc::VideoCodecType::kVideoCodecH264:
     83      if (StaticPrefs::media_webrtc_simulcast_h264_enabled()) {
     84        return std::make_unique<webrtc::SimulcastEncoderAdapter>(
     85            aEnv, mInternalFactory.get(), nullptr, aFormat);
     86      }
     87      break;
     88    case webrtc::VideoCodecType::kVideoCodecVP8:
     89      return std::make_unique<webrtc::SimulcastEncoderAdapter>(
     90          aEnv, mInternalFactory.get(), nullptr, aFormat);
     91    case webrtc::VideoCodecType::kVideoCodecVP9:
     92      if (StaticPrefs::media_webrtc_simulcast_vp9_enabled()) {
     93        return std::make_unique<webrtc::SimulcastEncoderAdapter>(
     94            aEnv, mInternalFactory.get(), nullptr, aFormat);
     95      }
     96      break;
     97  }
     98  return mInternalFactory->Create(aEnv, aFormat);
     99 }
    100 
    101 bool WebrtcVideoEncoderFactory::InternalFactory::Supports(
    102    const webrtc::SdpVideoFormat& aFormat) {
    103  switch (webrtc::PayloadStringToCodecType(aFormat.name)) {
    104    case webrtc::VideoCodecType::kVideoCodecVP8:
    105    case webrtc::VideoCodecType::kVideoCodecVP9:
    106    case webrtc::VideoCodecType::kVideoCodecH264:
    107    case webrtc::VideoCodecType::kVideoCodecAV1:
    108      return true;
    109    default:
    110      return false;
    111  }
    112 }
    113 
    114 std::unique_ptr<webrtc::VideoEncoder>
    115 WebrtcVideoEncoderFactory::InternalFactory::Create(
    116    const webrtc::Environment& aEnv, const webrtc::SdpVideoFormat& aFormat) {
    117  MOZ_ASSERT(Supports(aFormat));
    118 
    119  std::unique_ptr<webrtc::VideoEncoder> platformEncoder;
    120 
    121  auto createPlatformEncoder = [&]() -> std::unique_ptr<webrtc::VideoEncoder> {
    122    std::unique_ptr<webrtc::VideoEncoder> platformEncoder;
    123    platformEncoder.reset(MediaDataCodec::CreateEncoder(aFormat));
    124    return platformEncoder;
    125  };
    126 
    127  auto createWebRTCEncoder =
    128      [this, &aEnv, &aFormat]() -> std::unique_ptr<webrtc::VideoEncoder> {
    129    std::unique_ptr<webrtc::VideoEncoder> encoder;
    130    switch (webrtc::PayloadStringToCodecType(aFormat.name)) {
    131      case webrtc::VideoCodecType::kVideoCodecH264: {
    132        // get an external encoder
    133        auto gmpEncoder =
    134            WrapUnique(GmpVideoCodec::CreateEncoder(aFormat, mPCHandle));
    135        mCreatedGmpPluginEvent.Forward(*gmpEncoder->InitPluginEvent());
    136        mReleasedGmpPluginEvent.Forward(*gmpEncoder->ReleasePluginEvent());
    137        encoder.reset(gmpEncoder.release());
    138        break;
    139      }
    140      // libvpx fallbacks.
    141      case webrtc::VideoCodecType::kVideoCodecVP8:
    142        encoder = webrtc::CreateVp8Encoder(aEnv);
    143        break;
    144      case webrtc::VideoCodecType::kVideoCodecVP9:
    145        encoder = webrtc::CreateVp9Encoder(aEnv);
    146        break;
    147      case webrtc::VideoCodecType::kVideoCodecAV1:
    148        encoder = webrtc::CreateLibaomAv1Encoder(aEnv);
    149        break;
    150      default:
    151        break;
    152    }
    153    return encoder;
    154  };
    155 
    156  // This is to be synced with the doc for the pref in StaticPrefs.yaml
    157  enum EncoderCreationStrategy {
    158    PreferWebRTCEncoder = 0,
    159    PreferPlatformEncoder = 1
    160  };
    161 
    162  std::unique_ptr<webrtc::VideoEncoder> encoder = nullptr;
    163  EncoderCreationStrategy strategy = static_cast<EncoderCreationStrategy>(
    164      StaticPrefs::media_webrtc_encoder_creation_strategy());
    165  switch (strategy) {
    166    case EncoderCreationStrategy::PreferWebRTCEncoder: {
    167      encoder = createWebRTCEncoder();
    168      // In a single case this happens: H264 is requested and OpenH264 isn't
    169      // available yet (e.g. first run). Attempt to use a platform encoder in
    170      // this case. They are not entirely ready yet but it's better than
    171      // erroring out.
    172      if (!encoder) {
    173        NS_WARNING(
    174            "Failed creating libwebrtc video encoder, falling back on platform "
    175            "encoder");
    176        return createPlatformEncoder();
    177      }
    178      return encoder;
    179    }
    180    case EncoderCreationStrategy::PreferPlatformEncoder:
    181      platformEncoder = createPlatformEncoder();
    182      encoder = createWebRTCEncoder();
    183      if (encoder && platformEncoder) {
    184        return webrtc::CreateVideoEncoderSoftwareFallbackWrapper(
    185            aEnv, std::move(encoder), std::move(platformEncoder), false);
    186      }
    187      if (platformEncoder) {
    188        NS_WARNING(nsPrintfCString("No WebRTC encoder to fall back to for "
    189                                   "codec %s, only using platform encoder",
    190                                   aFormat.name.c_str())
    191                       .get());
    192        return platformEncoder;
    193      }
    194      return encoder;
    195  };
    196 
    197  MOZ_ASSERT_UNREACHABLE("Bad enum value");
    198 
    199  return nullptr;
    200 }
    201 
    202 }  // namespace mozilla