tor-browser

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

decoder_database.cc (5563B)


      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 "modules/video_coding/decoder_database.h"
     12 
     13 #include <cstdint>
     14 #include <memory>
     15 #include <optional>
     16 #include <utility>
     17 
     18 #include "api/sequence_checker.h"
     19 #include "api/video/encoded_frame.h"
     20 #include "api/video/render_resolution.h"
     21 #include "api/video_codecs/video_decoder.h"
     22 #include "modules/video_coding/generic_decoder.h"
     23 #include "modules/video_coding/include/video_coding_defines.h"
     24 #include "rtc_base/checks.h"
     25 #include "rtc_base/logging.h"
     26 
     27 namespace webrtc {
     28 
     29 VCMDecoderDatabase::VCMDecoderDatabase() {
     30  decoder_sequence_checker_.Detach();
     31 }
     32 
     33 void VCMDecoderDatabase::DeregisterExternalDecoder(uint8_t payload_type) {
     34  RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
     35  auto it = decoders_.find(payload_type);
     36  if (it == decoders_.end()) {
     37    return;
     38  }
     39 
     40  // We can't use payload_type to check if the decoder is currently in use,
     41  // because payload type may be out of date (e.g. before we decode the first
     42  // frame after RegisterReceiveCodec).
     43  if (current_decoder_ && current_decoder_->IsSameDecoder(it->second.get())) {
     44    // Release it if it was registered and in use.
     45    current_decoder_ = std::nullopt;
     46  }
     47  decoders_.erase(it);
     48 }
     49 
     50 // Add the external decoder object to the list of external decoders.
     51 // Won't be registered as a receive codec until RegisterReceiveCodec is called.
     52 void VCMDecoderDatabase::RegisterExternalDecoder(
     53    uint8_t payload_type,
     54    std::unique_ptr<VideoDecoder> external_decoder) {
     55  RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
     56  // If payload value already exists, erase old and insert new.
     57  DeregisterExternalDecoder(payload_type);
     58  if (external_decoder) {
     59    decoders_.emplace(
     60        std::make_pair(payload_type, std::move(external_decoder)));
     61  }
     62 }
     63 
     64 bool VCMDecoderDatabase::IsExternalDecoderRegistered(
     65    uint8_t payload_type) const {
     66  RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
     67  return decoders_.find(payload_type) != decoders_.end();
     68 }
     69 
     70 void VCMDecoderDatabase::RegisterReceiveCodec(
     71    uint8_t payload_type,
     72    const VideoDecoder::Settings& settings) {
     73  // If payload value already exists, erase old and insert new.
     74  if (payload_type == current_payload_type_) {
     75    current_payload_type_ = std::nullopt;
     76  }
     77  decoder_settings_[payload_type] = settings;
     78 }
     79 
     80 bool VCMDecoderDatabase::DeregisterReceiveCodec(uint8_t payload_type) {
     81  if (decoder_settings_.erase(payload_type) == 0) {
     82    return false;
     83  }
     84  if (payload_type == current_payload_type_) {
     85    // This codec is currently in use.
     86    current_payload_type_ = std::nullopt;
     87  }
     88  return true;
     89 }
     90 
     91 void VCMDecoderDatabase::DeregisterReceiveCodecs() {
     92  current_payload_type_ = std::nullopt;
     93  decoder_settings_.clear();
     94 }
     95 
     96 VCMGenericDecoder* VCMDecoderDatabase::GetDecoder(
     97    const EncodedFrame& frame,
     98    VCMDecodedFrameCallback* decoded_frame_callback) {
     99  RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
    100  RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
    101  uint8_t payload_type = frame.PayloadType();
    102  if (payload_type == current_payload_type_ || payload_type == 0) {
    103    return current_decoder_.has_value() ? &*current_decoder_ : nullptr;
    104  }
    105  // If decoder exists - delete.
    106  if (current_decoder_.has_value()) {
    107    current_decoder_ = std::nullopt;
    108    current_payload_type_ = std::nullopt;
    109  }
    110 
    111  CreateAndInitDecoder(frame);
    112  if (current_decoder_ == std::nullopt) {
    113    return nullptr;
    114  }
    115 
    116  VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
    117  callback->OnIncomingPayloadType(payload_type);
    118  if (current_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
    119      0) {
    120    current_decoder_ = std::nullopt;
    121    return nullptr;
    122  }
    123 
    124  current_payload_type_ = payload_type;
    125  return &*current_decoder_;
    126 }
    127 
    128 void VCMDecoderDatabase::CreateAndInitDecoder(const EncodedFrame& frame) {
    129  uint8_t payload_type = frame.PayloadType();
    130  RTC_DLOG(LS_INFO) << "Initializing decoder with payload type '"
    131                    << int{payload_type} << "'.";
    132  auto decoder_item = decoder_settings_.find(payload_type);
    133  if (decoder_item == decoder_settings_.end()) {
    134    RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
    135                      << int{payload_type};
    136    return;
    137  }
    138  auto external_dec_item = decoders_.find(payload_type);
    139  if (external_dec_item == decoders_.end()) {
    140    RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
    141    return;
    142  }
    143  current_decoder_.emplace(external_dec_item->second.get());
    144 
    145  // Copy over input resolutions to prevent codec reinitialization due to
    146  // the first frame being of a different resolution than the database values.
    147  // This is best effort, since there's no guarantee that width/height have been
    148  // parsed yet (and may be zero).
    149  RenderResolution frame_resolution(frame.EncodedImage()._encodedWidth,
    150                                    frame.EncodedImage()._encodedHeight);
    151  if (frame_resolution.Valid()) {
    152    decoder_item->second.set_max_render_resolution(frame_resolution);
    153  }
    154  if (!current_decoder_->Configure(decoder_item->second)) {
    155    current_decoder_ = std::nullopt;
    156    RTC_LOG(LS_ERROR) << "Failed to initialize decoder.";
    157  }
    158 }
    159 
    160 }  // namespace webrtc