Home | History | Annotate | Download | only in neteq
      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 "webrtc/modules/audio_coding/neteq/decoder_database.h"
     12 
     13 #include <assert.h>
     14 #include <utility>  // pair
     15 
     16 #include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
     17 
     18 namespace webrtc {
     19 
     20 DecoderDatabase::DecoderDatabase()
     21     : active_decoder_(-1), active_cng_decoder_(-1) {}
     22 
     23 DecoderDatabase::~DecoderDatabase() {}
     24 
     25 DecoderDatabase::DecoderInfo::~DecoderInfo() {
     26   if (!external) delete decoder;
     27 }
     28 
     29 bool DecoderDatabase::Empty() const { return decoders_.empty(); }
     30 
     31 int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
     32 
     33 void DecoderDatabase::Reset() {
     34   decoders_.clear();
     35   active_decoder_ = -1;
     36   active_cng_decoder_ = -1;
     37 }
     38 
     39 int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
     40                                      NetEqDecoder codec_type) {
     41   if (rtp_payload_type > kMaxRtpPayloadType) {
     42     return kInvalidRtpPayloadType;
     43   }
     44   if (!AudioDecoder::CodecSupported(codec_type)) {
     45     return kCodecNotSupported;
     46   }
     47   int fs_hz = AudioDecoder::CodecSampleRateHz(codec_type);
     48   std::pair<DecoderMap::iterator, bool> ret;
     49   DecoderInfo info(codec_type, fs_hz, NULL, false);
     50   ret = decoders_.insert(std::make_pair(rtp_payload_type, info));
     51   if (ret.second == false) {
     52     // Database already contains a decoder with type |rtp_payload_type|.
     53     return kDecoderExists;
     54   }
     55   return kOK;
     56 }
     57 
     58 int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
     59                                     NetEqDecoder codec_type,
     60                                     int fs_hz,
     61                                     AudioDecoder* decoder) {
     62   if (rtp_payload_type > 0x7F) {
     63     return kInvalidRtpPayloadType;
     64   }
     65   if (!AudioDecoder::CodecSupported(codec_type)) {
     66     return kCodecNotSupported;
     67   }
     68   if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
     69     return kInvalidSampleRate;
     70   }
     71   if (!decoder) {
     72     return kInvalidPointer;
     73   }
     74   decoder->Init();
     75   std::pair<DecoderMap::iterator, bool> ret;
     76   DecoderInfo info(codec_type, fs_hz, decoder, true);
     77   ret = decoders_.insert(
     78       std::pair<uint8_t, DecoderInfo>(rtp_payload_type, info));
     79   if (ret.second == false) {
     80     // Database already contains a decoder with type |rtp_payload_type|.
     81     return kDecoderExists;
     82   }
     83   return kOK;
     84 }
     85 
     86 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
     87   if (decoders_.erase(rtp_payload_type) == 0) {
     88     // No decoder with that |rtp_payload_type|.
     89     return kDecoderNotFound;
     90   }
     91   if (active_decoder_ == rtp_payload_type) {
     92     active_decoder_ = -1;  // No active decoder.
     93   }
     94   if (active_cng_decoder_ == rtp_payload_type) {
     95     active_cng_decoder_ = -1;  // No active CNG decoder.
     96   }
     97   return kOK;
     98 }
     99 
    100 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
    101     uint8_t rtp_payload_type) const {
    102   DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
    103   if (it == decoders_.end()) {
    104     // Decoder not found.
    105     return NULL;
    106   }
    107   return &(*it).second;
    108 }
    109 
    110 uint8_t DecoderDatabase::GetRtpPayloadType(
    111     NetEqDecoder codec_type) const {
    112   DecoderMap::const_iterator it;
    113   for (it = decoders_.begin(); it != decoders_.end(); ++it) {
    114     if ((*it).second.codec_type == codec_type) {
    115       // Match found.
    116       return (*it).first;
    117     }
    118   }
    119   // No match.
    120   return kRtpPayloadTypeError;
    121 }
    122 
    123 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
    124   if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type)) {
    125     // These are not real decoders.
    126     return NULL;
    127   }
    128   DecoderMap::iterator it = decoders_.find(rtp_payload_type);
    129   if (it == decoders_.end()) {
    130     // Decoder not found.
    131     return NULL;
    132   }
    133   DecoderInfo* info = &(*it).second;
    134   if (!info->decoder) {
    135     // Create the decoder object.
    136     AudioDecoder* decoder = AudioDecoder::CreateAudioDecoder(info->codec_type);
    137     assert(decoder);  // Should not be able to have an unsupported codec here.
    138     info->decoder = decoder;
    139     info->decoder->Init();
    140   }
    141   return info->decoder;
    142 }
    143 
    144 bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
    145                              NetEqDecoder codec_type) const {
    146   DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
    147   if (it == decoders_.end()) {
    148     // Decoder not found.
    149     return false;
    150   }
    151   return ((*it).second.codec_type == codec_type);
    152 }
    153 
    154 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
    155   if (IsType(rtp_payload_type, kDecoderCNGnb) ||
    156       IsType(rtp_payload_type, kDecoderCNGwb) ||
    157       IsType(rtp_payload_type, kDecoderCNGswb32kHz) ||
    158       IsType(rtp_payload_type, kDecoderCNGswb48kHz)) {
    159     return true;
    160   } else {
    161     return false;
    162   }
    163 }
    164 
    165 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
    166   return IsType(rtp_payload_type, kDecoderAVT);
    167 }
    168 
    169 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
    170   return IsType(rtp_payload_type, kDecoderRED);
    171 }
    172 
    173 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
    174                                       bool* new_decoder) {
    175   // Check that |rtp_payload_type| exists in the database.
    176   DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
    177   if (it == decoders_.end()) {
    178     // Decoder not found.
    179     return kDecoderNotFound;
    180   }
    181   assert(new_decoder);
    182   *new_decoder = false;
    183   if (active_decoder_ < 0) {
    184     // This is the first active decoder.
    185     *new_decoder = true;
    186   } else if (active_decoder_ != rtp_payload_type) {
    187     // Moving from one active decoder to another. Delete the first one.
    188     DecoderMap::iterator it = decoders_.find(active_decoder_);
    189     if (it == decoders_.end()) {
    190       // Decoder not found. This should not be possible.
    191       assert(false);
    192       return kDecoderNotFound;
    193     }
    194     if (!(*it).second.external) {
    195       // Delete the AudioDecoder object, unless it is an externally created
    196       // decoder.
    197       delete (*it).second.decoder;
    198       (*it).second.decoder = NULL;
    199     }
    200     *new_decoder = true;
    201   }
    202   active_decoder_ = rtp_payload_type;
    203   return kOK;
    204 }
    205 
    206 AudioDecoder* DecoderDatabase::GetActiveDecoder() {
    207   if (active_decoder_ < 0) {
    208     // No active decoder.
    209     return NULL;
    210   }
    211   return GetDecoder(active_decoder_);
    212 }
    213 
    214 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
    215   // Check that |rtp_payload_type| exists in the database.
    216   DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
    217   if (it == decoders_.end()) {
    218     // Decoder not found.
    219     return kDecoderNotFound;
    220   }
    221   if (active_cng_decoder_ >= 0 && active_cng_decoder_ != rtp_payload_type) {
    222     // Moving from one active CNG decoder to another. Delete the first one.
    223     DecoderMap::iterator it = decoders_.find(active_cng_decoder_);
    224     if (it == decoders_.end()) {
    225       // Decoder not found. This should not be possible.
    226       assert(false);
    227       return kDecoderNotFound;
    228     }
    229     if (!(*it).second.external) {
    230       // Delete the AudioDecoder object, unless it is an externally created
    231       // decoder.
    232       delete (*it).second.decoder;
    233       (*it).second.decoder = NULL;
    234     }
    235   }
    236   active_cng_decoder_ = rtp_payload_type;
    237   return kOK;
    238 }
    239 
    240 AudioDecoder* DecoderDatabase::GetActiveCngDecoder() {
    241   if (active_cng_decoder_ < 0) {
    242     // No active CNG decoder.
    243     return NULL;
    244   }
    245   return GetDecoder(active_cng_decoder_);
    246 }
    247 
    248 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
    249   PacketList::const_iterator it;
    250   for (it = packet_list.begin(); it != packet_list.end(); ++it) {
    251     if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
    252       // Payload type is not found.
    253       return kDecoderNotFound;
    254     }
    255   }
    256   return kOK;
    257 }
    258 
    259 
    260 }  // namespace webrtc
    261