tor-browser

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

decoder_database.cc (9556B)


      1 /*
      2 *  Copyright (c) 2012 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/audio_coding/neteq/decoder_database.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <list>
     16 #include <map>
     17 #include <optional>
     18 #include <utility>
     19 #include <vector>
     20 
     21 #include "absl/strings/match.h"
     22 #include "absl/strings/str_cat.h"
     23 #include "absl/strings/string_view.h"
     24 #include "api/audio_codecs/audio_codec_pair_id.h"
     25 #include "api/audio_codecs/audio_decoder.h"
     26 #include "api/audio_codecs/audio_decoder_factory.h"
     27 #include "api/audio_codecs/audio_format.h"
     28 #include "api/environment/environment.h"
     29 #include "api/scoped_refptr.h"
     30 #include "modules/audio_coding/codecs/cng/webrtc_cng.h"
     31 #include "modules/audio_coding/neteq/packet.h"
     32 #include "rtc_base/checks.h"
     33 #include "rtc_base/logging.h"
     34 
     35 namespace webrtc {
     36 
     37 DecoderDatabase::DecoderDatabase(
     38    const Environment& env,
     39    scoped_refptr<AudioDecoderFactory> decoder_factory,
     40    std::optional<AudioCodecPairId> codec_pair_id)
     41    : env_(env),
     42      active_decoder_type_(-1),
     43      active_cng_decoder_type_(-1),
     44      decoder_factory_(std::move(decoder_factory)),
     45      codec_pair_id_(codec_pair_id) {}
     46 
     47 DecoderDatabase::~DecoderDatabase() = default;
     48 
     49 DecoderDatabase::DecoderInfo::DecoderInfo(
     50    const Environment& env,
     51    const SdpAudioFormat& audio_format,
     52    std::optional<AudioCodecPairId> codec_pair_id,
     53    AudioDecoderFactory* factory)
     54    : env_(env),
     55      audio_format_(audio_format),
     56      codec_pair_id_(codec_pair_id),
     57      factory_(factory),
     58      cng_decoder_(CngDecoder::Create(audio_format)),
     59      subtype_(SubtypeFromFormat(audio_format)) {}
     60 
     61 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
     62 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
     63 
     64 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
     65  if (subtype_ != Subtype::kNormal) {
     66    // These are handled internally, so they have no AudioDecoder objects.
     67    return nullptr;
     68  }
     69  if (!decoder_) {
     70    // TODO(ossu): Keep a check here for now, since a number of tests create
     71    // DecoderInfos without factories.
     72    RTC_DCHECK(factory_);
     73    decoder_ = factory_->Create(env_, audio_format_, codec_pair_id_);
     74  }
     75  RTC_DCHECK(decoder_) << "Failed to create: " << absl::StrCat(audio_format_);
     76  return decoder_.get();
     77 }
     78 
     79 bool DecoderDatabase::DecoderInfo::IsType(absl::string_view name) const {
     80  return absl::EqualsIgnoreCase(audio_format_.name, name);
     81 }
     82 
     83 std::optional<DecoderDatabase::DecoderInfo::CngDecoder>
     84 DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
     85  if (absl::EqualsIgnoreCase(format.name, "CN")) {
     86    // CN has a 1:1 RTP clock rate to sample rate ratio.
     87    const int sample_rate_hz = format.clockrate_hz;
     88    RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
     89               sample_rate_hz == 32000 || sample_rate_hz == 48000);
     90    return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
     91  } else {
     92    return std::nullopt;
     93  }
     94 }
     95 
     96 DecoderDatabase::DecoderInfo::Subtype
     97 DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
     98  if (absl::EqualsIgnoreCase(format.name, "CN")) {
     99    return Subtype::kComfortNoise;
    100  } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) {
    101    return Subtype::kDtmf;
    102  } else if (absl::EqualsIgnoreCase(format.name, "red")) {
    103    return Subtype::kRed;
    104  }
    105 
    106  return Subtype::kNormal;
    107 }
    108 
    109 bool DecoderDatabase::Empty() const {
    110  return decoders_.empty();
    111 }
    112 
    113 int DecoderDatabase::Size() const {
    114  return static_cast<int>(decoders_.size());
    115 }
    116 
    117 std::vector<int> DecoderDatabase::SetCodecs(
    118    const std::map<int, SdpAudioFormat>& codecs) {
    119  // First collect all payload types that we'll remove or reassign, then remove
    120  // them from the database.
    121  std::vector<int> changed_payload_types;
    122  for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
    123    auto i = codecs.find(kv.first);
    124    if (i == codecs.end() || i->second != kv.second.GetFormat()) {
    125      changed_payload_types.push_back(kv.first);
    126    }
    127  }
    128  for (int pl_type : changed_payload_types) {
    129    Remove(pl_type);
    130  }
    131 
    132  // Enter the new and changed payload type mappings into the database.
    133  for (const auto& kv : codecs) {
    134    const int& rtp_payload_type = kv.first;
    135    const SdpAudioFormat& audio_format = kv.second;
    136    RTC_DCHECK_GE(rtp_payload_type, 0);
    137    RTC_DCHECK_LE(rtp_payload_type, 0x7f);
    138    if (decoders_.count(rtp_payload_type) == 0) {
    139      decoders_.insert(std::make_pair(
    140          rtp_payload_type, DecoderInfo(env_, audio_format, codec_pair_id_,
    141                                        decoder_factory_.get())));
    142    } else {
    143      // The mapping for this payload type hasn't changed.
    144    }
    145  }
    146 
    147  return changed_payload_types;
    148 }
    149 
    150 int DecoderDatabase::RegisterPayload(int rtp_payload_type,
    151                                     const SdpAudioFormat& audio_format) {
    152  if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
    153    return kInvalidRtpPayloadType;
    154  }
    155  const auto ret = decoders_.insert(std::make_pair(
    156      rtp_payload_type,
    157      DecoderInfo(env_, audio_format, codec_pair_id_, decoder_factory_.get())));
    158  if (ret.second == false) {
    159    // Database already contains a decoder with type `rtp_payload_type`.
    160    return kDecoderExists;
    161  }
    162  return kOK;
    163 }
    164 
    165 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
    166  if (decoders_.erase(rtp_payload_type) == 0) {
    167    // No decoder with that `rtp_payload_type`.
    168    return kDecoderNotFound;
    169  }
    170  if (active_decoder_type_ == rtp_payload_type) {
    171    active_decoder_type_ = -1;  // No active decoder.
    172  }
    173  if (active_cng_decoder_type_ == rtp_payload_type) {
    174    active_cng_decoder_type_ = -1;  // No active CNG decoder.
    175  }
    176  return kOK;
    177 }
    178 
    179 void DecoderDatabase::RemoveAll() {
    180  decoders_.clear();
    181  active_decoder_type_ = -1;      // No active decoder.
    182  active_cng_decoder_type_ = -1;  // No active CNG decoder.
    183 }
    184 
    185 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
    186    uint8_t rtp_payload_type) const {
    187  DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
    188  if (it == decoders_.end()) {
    189    // Decoder not found.
    190    return nullptr;
    191  }
    192  return &it->second;
    193 }
    194 
    195 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
    196                                      bool* new_decoder) {
    197  // Check that `rtp_payload_type` exists in the database.
    198  const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
    199  if (!info) {
    200    // Decoder not found.
    201    return kDecoderNotFound;
    202  }
    203  RTC_CHECK(!info->IsComfortNoise());
    204  RTC_DCHECK(new_decoder);
    205  *new_decoder = false;
    206  if (active_decoder_type_ < 0) {
    207    // This is the first active decoder.
    208    *new_decoder = true;
    209  } else if (active_decoder_type_ != rtp_payload_type) {
    210    // Moving from one active decoder to another. Delete the first one.
    211    const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
    212    RTC_DCHECK(old_info);
    213    old_info->DropDecoder();
    214    *new_decoder = true;
    215  }
    216  active_decoder_type_ = rtp_payload_type;
    217  return kOK;
    218 }
    219 
    220 AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
    221  if (active_decoder_type_ < 0) {
    222    // No active decoder.
    223    return nullptr;
    224  }
    225  return GetDecoder(active_decoder_type_);
    226 }
    227 
    228 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
    229  // Check that `rtp_payload_type` exists in the database.
    230  const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
    231  if (!info) {
    232    // Decoder not found.
    233    return kDecoderNotFound;
    234  }
    235  if (active_cng_decoder_type_ >= 0 &&
    236      active_cng_decoder_type_ != rtp_payload_type) {
    237    // Moving from one active CNG decoder to another. Delete the first one.
    238    RTC_DCHECK(active_cng_decoder_);
    239    active_cng_decoder_.reset();
    240  }
    241  active_cng_decoder_type_ = rtp_payload_type;
    242  return kOK;
    243 }
    244 
    245 ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
    246  if (active_cng_decoder_type_ < 0) {
    247    // No active CNG decoder.
    248    return nullptr;
    249  }
    250  if (!active_cng_decoder_) {
    251    active_cng_decoder_.reset(new ComfortNoiseDecoder);
    252  }
    253  return active_cng_decoder_.get();
    254 }
    255 
    256 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
    257  const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
    258  return info ? info->GetDecoder() : nullptr;
    259 }
    260 
    261 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
    262  const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
    263  return info && info->IsComfortNoise();
    264 }
    265 
    266 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
    267  const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
    268  return info && info->IsDtmf();
    269 }
    270 
    271 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
    272  const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
    273  return info && info->IsRed();
    274 }
    275 
    276 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
    277  PacketList::const_iterator it;
    278  for (it = packet_list.begin(); it != packet_list.end(); ++it) {
    279    if (!GetDecoderInfo(it->payload_type)) {
    280      // Payload type is not found.
    281      RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
    282                          << static_cast<int>(it->payload_type);
    283      return kDecoderNotFound;
    284    }
    285  }
    286  return kOK;
    287 }
    288 
    289 }  // namespace webrtc