tor-browser

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

fake_webrtc_video_engine.cc (9693B)


      1 /*
      2 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "media/engine/fake_webrtc_video_engine.h"
     12 
     13 #include <cstdint>
     14 #include <memory>
     15 #include <optional>
     16 #include <string>
     17 #include <vector>
     18 
     19 #include "absl/strings/match.h"
     20 #include "api/environment/environment.h"
     21 #include "api/fec_controller_override.h"
     22 #include "api/units/time_delta.h"
     23 #include "api/video/encoded_image.h"
     24 #include "api/video/video_frame.h"
     25 #include "api/video/video_frame_type.h"
     26 #include "api/video_codecs/scalability_mode.h"
     27 #include "api/video_codecs/sdp_video_format.h"
     28 #include "api/video_codecs/video_codec.h"
     29 #include "api/video_codecs/video_decoder.h"
     30 #include "api/video_codecs/video_encoder.h"
     31 #include "api/video_codecs/video_encoder_factory.h"
     32 #include "media/base/codec.h"
     33 #include "media/base/media_constants.h"
     34 #include "media/engine/simulcast_encoder_adapter.h"
     35 #include "modules/video_coding/include/video_error_codes.h"
     36 #include "rtc_base/logging.h"
     37 #include "rtc_base/synchronization/mutex.h"
     38 #include "rtc_base/time_utils.h"
     39 
     40 namespace webrtc {
     41 
     42 namespace {
     43 
     44 constexpr TimeDelta kEventTimeout = TimeDelta::Seconds(10);
     45 
     46 bool IsScalabilityModeSupported(const std::vector<SdpVideoFormat>& formats,
     47                                std::optional<std::string> scalability_mode) {
     48  if (!scalability_mode.has_value()) {
     49    return true;
     50  }
     51  for (const auto& format : formats) {
     52    for (const auto& mode : format.scalability_modes) {
     53      if (ScalabilityModeToString(mode) == scalability_mode)
     54        return true;
     55    }
     56  }
     57  return false;
     58 }
     59 
     60 }  // namespace
     61 
     62 // Decoder.
     63 FakeWebRtcVideoDecoder::FakeWebRtcVideoDecoder(
     64    FakeWebRtcVideoDecoderFactory* factory)
     65    : num_frames_received_(0), factory_(factory) {}
     66 
     67 FakeWebRtcVideoDecoder::~FakeWebRtcVideoDecoder() {
     68  if (factory_) {
     69    factory_->DecoderDestroyed(this);
     70  }
     71 }
     72 
     73 bool FakeWebRtcVideoDecoder::Configure(const Settings& /* settings */) {
     74  return true;
     75 }
     76 
     77 int32_t FakeWebRtcVideoDecoder::Decode(const EncodedImage&, int64_t) {
     78  num_frames_received_++;
     79  return WEBRTC_VIDEO_CODEC_OK;
     80 }
     81 
     82 int32_t FakeWebRtcVideoDecoder::RegisterDecodeCompleteCallback(
     83    DecodedImageCallback*) {
     84  return WEBRTC_VIDEO_CODEC_OK;
     85 }
     86 
     87 int32_t FakeWebRtcVideoDecoder::Release() {
     88  return WEBRTC_VIDEO_CODEC_OK;
     89 }
     90 
     91 int FakeWebRtcVideoDecoder::GetNumFramesReceived() const {
     92  return num_frames_received_;
     93 }
     94 
     95 // Decoder factory.
     96 FakeWebRtcVideoDecoderFactory::FakeWebRtcVideoDecoderFactory()
     97    : num_created_decoders_(0) {}
     98 
     99 std::vector<SdpVideoFormat> FakeWebRtcVideoDecoderFactory::GetSupportedFormats()
    100    const {
    101  std::vector<SdpVideoFormat> formats;
    102 
    103  for (const SdpVideoFormat& format : supported_codec_formats_) {
    104    // We need to test erroneous scenarios, so just warn if there's
    105    // a duplicate.
    106    if (format.IsCodecInList(formats)) {
    107      RTC_LOG(LS_WARNING) << "GetSupportedFormats found a duplicate format: "
    108                          << format << ", check that this is expected.";
    109    }
    110    formats.push_back(format);
    111  }
    112 
    113  return formats;
    114 }
    115 
    116 std::unique_ptr<VideoDecoder> FakeWebRtcVideoDecoderFactory::Create(
    117    const Environment& /* env */,
    118    const SdpVideoFormat& format) {
    119  if (format.IsCodecInList(supported_codec_formats_)) {
    120    num_created_decoders_++;
    121    std::unique_ptr<FakeWebRtcVideoDecoder> decoder =
    122        std::make_unique<FakeWebRtcVideoDecoder>(this);
    123    decoders_.push_back(decoder.get());
    124    return decoder;
    125  }
    126 
    127  return nullptr;
    128 }
    129 
    130 void FakeWebRtcVideoDecoderFactory::DecoderDestroyed(
    131    FakeWebRtcVideoDecoder* decoder) {
    132  std::erase(decoders_, decoder);
    133 }
    134 
    135 void FakeWebRtcVideoDecoderFactory::AddSupportedVideoCodec(
    136    const SdpVideoFormat& format) {
    137  supported_codec_formats_.push_back(format);
    138 }
    139 
    140 void FakeWebRtcVideoDecoderFactory::AddSupportedVideoCodecType(
    141    const std::string& name) {
    142  // This is to match the default H264 params of Codec.
    143  Codec video_codec = CreateVideoCodec(name);
    144  supported_codec_formats_.push_back(
    145      SdpVideoFormat(video_codec.name, video_codec.params));
    146 }
    147 
    148 int FakeWebRtcVideoDecoderFactory::GetNumCreatedDecoders() {
    149  return num_created_decoders_;
    150 }
    151 
    152 const std::vector<FakeWebRtcVideoDecoder*>&
    153 FakeWebRtcVideoDecoderFactory::decoders() {
    154  return decoders_;
    155 }
    156 
    157 // Encoder.
    158 FakeWebRtcVideoEncoder::FakeWebRtcVideoEncoder(
    159    FakeWebRtcVideoEncoderFactory* factory)
    160    : num_frames_encoded_(0), factory_(factory) {}
    161 
    162 FakeWebRtcVideoEncoder::~FakeWebRtcVideoEncoder() {
    163  if (factory_) {
    164    factory_->EncoderDestroyed(this);
    165  }
    166 }
    167 
    168 void FakeWebRtcVideoEncoder::SetFecControllerOverride(
    169    FecControllerOverride* /* fec_controller_override */) {
    170  // Ignored.
    171 }
    172 
    173 int32_t FakeWebRtcVideoEncoder::InitEncode(
    174    const VideoCodec* codecSettings,
    175    const VideoEncoder::Settings& /* settings */) {
    176  MutexLock lock(&mutex_);
    177  codec_settings_ = *codecSettings;
    178  init_encode_event_.Set();
    179  return WEBRTC_VIDEO_CODEC_OK;
    180 }
    181 
    182 int32_t FakeWebRtcVideoEncoder::Encode(
    183    const VideoFrame& /* inputImage */,
    184    const std::vector<VideoFrameType>* /* frame_types */) {
    185  MutexLock lock(&mutex_);
    186  ++num_frames_encoded_;
    187  init_encode_event_.Set();
    188  return WEBRTC_VIDEO_CODEC_OK;
    189 }
    190 
    191 int32_t FakeWebRtcVideoEncoder::RegisterEncodeCompleteCallback(
    192    EncodedImageCallback* /* callback */) {
    193  return WEBRTC_VIDEO_CODEC_OK;
    194 }
    195 
    196 int32_t FakeWebRtcVideoEncoder::Release() {
    197  return WEBRTC_VIDEO_CODEC_OK;
    198 }
    199 
    200 void FakeWebRtcVideoEncoder::SetRates(
    201    const RateControlParameters& /* parameters */) {}
    202 
    203 VideoEncoder::EncoderInfo FakeWebRtcVideoEncoder::GetEncoderInfo() const {
    204  EncoderInfo info;
    205  info.is_hardware_accelerated = true;
    206  return info;
    207 }
    208 
    209 bool FakeWebRtcVideoEncoder::WaitForInitEncode() {
    210  return init_encode_event_.Wait(kEventTimeout);
    211 }
    212 
    213 VideoCodec FakeWebRtcVideoEncoder::GetCodecSettings() {
    214  MutexLock lock(&mutex_);
    215  return codec_settings_;
    216 }
    217 
    218 int FakeWebRtcVideoEncoder::GetNumEncodedFrames() {
    219  MutexLock lock(&mutex_);
    220  return num_frames_encoded_;
    221 }
    222 
    223 // Video encoder factory.
    224 FakeWebRtcVideoEncoderFactory::FakeWebRtcVideoEncoderFactory()
    225    : num_created_encoders_(0), vp8_factory_mode_(false) {}
    226 
    227 std::vector<SdpVideoFormat> FakeWebRtcVideoEncoderFactory::GetSupportedFormats()
    228    const {
    229  std::vector<SdpVideoFormat> formats;
    230 
    231  for (const SdpVideoFormat& format : formats_) {
    232    // Don't add same codec twice.
    233    if (!format.IsCodecInList(formats))
    234      formats.push_back(format);
    235  }
    236 
    237  return formats;
    238 }
    239 
    240 VideoEncoderFactory::CodecSupport
    241 FakeWebRtcVideoEncoderFactory::QueryCodecSupport(
    242    const SdpVideoFormat& format,
    243    std::optional<std::string> scalability_mode) const {
    244  std::vector<SdpVideoFormat> supported_formats;
    245  for (const auto& f : formats_) {
    246    if (format.IsSameCodec(f))
    247      supported_formats.push_back(f);
    248  }
    249  if (format.IsCodecInList(formats_)) {
    250    return {.is_supported = IsScalabilityModeSupported(supported_formats,
    251                                                       scalability_mode)};
    252  }
    253  return {.is_supported = false};
    254 }
    255 
    256 std::unique_ptr<VideoEncoder> FakeWebRtcVideoEncoderFactory::Create(
    257    const Environment& env,
    258    const SdpVideoFormat& format) {
    259  MutexLock lock(&mutex_);
    260  std::unique_ptr<VideoEncoder> encoder;
    261  if (format.IsCodecInList(formats_)) {
    262    if (absl::EqualsIgnoreCase(format.name, kVp8CodecName) &&
    263        !vp8_factory_mode_) {
    264      // The simulcast adapter will ask this factory for multiple VP8
    265      // encoders. Enter vp8_factory_mode so that we now create these encoders
    266      // instead of more adapters.
    267      vp8_factory_mode_ = true;
    268      encoder = std::make_unique<SimulcastEncoderAdapter>(
    269          env, /*primary_factory=*/this, /*fallback_factory=*/nullptr, format);
    270    } else {
    271      num_created_encoders_++;
    272      created_video_encoder_event_.Set();
    273      encoder = std::make_unique<FakeWebRtcVideoEncoder>(this);
    274      encoders_.push_back(static_cast<FakeWebRtcVideoEncoder*>(encoder.get()));
    275    }
    276  }
    277  return encoder;
    278 }
    279 
    280 bool FakeWebRtcVideoEncoderFactory::WaitForCreatedVideoEncoders(
    281    int num_encoders) {
    282  int64_t start_offset_ms = TimeMillis();
    283  int64_t wait_time = kEventTimeout.ms();
    284  do {
    285    if (GetNumCreatedEncoders() >= num_encoders)
    286      return true;
    287    wait_time = kEventTimeout.ms() - (TimeMillis() - start_offset_ms);
    288  } while (wait_time > 0 &&
    289           created_video_encoder_event_.Wait(TimeDelta::Millis(wait_time)));
    290  return false;
    291 }
    292 
    293 void FakeWebRtcVideoEncoderFactory::EncoderDestroyed(
    294    FakeWebRtcVideoEncoder* encoder) {
    295  MutexLock lock(&mutex_);
    296  std::erase(encoders_, encoder);
    297 }
    298 
    299 void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodec(
    300    const SdpVideoFormat& format) {
    301  formats_.push_back(format);
    302 }
    303 
    304 void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodecType(
    305    const std::string& name,
    306    const std::vector<ScalabilityMode>& scalability_modes) {
    307  // This is to match the default H264 params of Codec.
    308  Codec video_codec = CreateVideoCodec(name);
    309  formats_.push_back(
    310      SdpVideoFormat(video_codec.name, video_codec.params,
    311                     {scalability_modes.begin(), scalability_modes.end()}));
    312 }
    313 
    314 int FakeWebRtcVideoEncoderFactory::GetNumCreatedEncoders() {
    315  MutexLock lock(&mutex_);
    316  return num_created_encoders_;
    317 }
    318 
    319 const std::vector<FakeWebRtcVideoEncoder*>
    320 FakeWebRtcVideoEncoderFactory::encoders() {
    321  MutexLock lock(&mutex_);
    322  return encoders_;
    323 }
    324 
    325 }  // namespace webrtc