• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/checks.h"
17 #include "webrtc/base/logging.h"
18 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
19 
20 namespace webrtc {
21 
DecoderDatabase()22 DecoderDatabase::DecoderDatabase()
23     : active_decoder_(-1), active_cng_decoder_(-1) {}
24 
~DecoderDatabase()25 DecoderDatabase::~DecoderDatabase() {}
26 
~DecoderInfo()27 DecoderDatabase::DecoderInfo::~DecoderInfo() {
28   if (!external) delete decoder;
29 }
30 
Empty() const31 bool DecoderDatabase::Empty() const { return decoders_.empty(); }
32 
Size() const33 int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
34 
Reset()35 void DecoderDatabase::Reset() {
36   decoders_.clear();
37   active_decoder_ = -1;
38   active_cng_decoder_ = -1;
39 }
40 
RegisterPayload(uint8_t rtp_payload_type,NetEqDecoder codec_type,const std::string & name)41 int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
42                                      NetEqDecoder codec_type,
43                                      const std::string& name) {
44   if (rtp_payload_type > 0x7F) {
45     return kInvalidRtpPayloadType;
46   }
47   if (!CodecSupported(codec_type)) {
48     return kCodecNotSupported;
49   }
50   const int fs_hz = CodecSampleRateHz(codec_type);
51   DecoderInfo info(codec_type, name, fs_hz, NULL, false);
52   auto ret = decoders_.insert(std::make_pair(rtp_payload_type, info));
53   if (ret.second == false) {
54     // Database already contains a decoder with type |rtp_payload_type|.
55     return kDecoderExists;
56   }
57   return kOK;
58 }
59 
InsertExternal(uint8_t rtp_payload_type,NetEqDecoder codec_type,const std::string & codec_name,int fs_hz,AudioDecoder * decoder)60 int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
61                                     NetEqDecoder codec_type,
62                                     const std::string& codec_name,
63                                     int fs_hz,
64                                     AudioDecoder* decoder) {
65   if (rtp_payload_type > 0x7F) {
66     return kInvalidRtpPayloadType;
67   }
68   if (!CodecSupported(codec_type)) {
69     return kCodecNotSupported;
70   }
71   if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
72     return kInvalidSampleRate;
73   }
74   if (!decoder) {
75     return kInvalidPointer;
76   }
77   std::pair<DecoderMap::iterator, bool> ret;
78   DecoderInfo info(codec_type, codec_name, fs_hz, decoder, true);
79   ret = decoders_.insert(std::make_pair(rtp_payload_type, info));
80   if (ret.second == false) {
81     // Database already contains a decoder with type |rtp_payload_type|.
82     return kDecoderExists;
83   }
84   return kOK;
85 }
86 
Remove(uint8_t rtp_payload_type)87 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
88   if (decoders_.erase(rtp_payload_type) == 0) {
89     // No decoder with that |rtp_payload_type|.
90     return kDecoderNotFound;
91   }
92   if (active_decoder_ == rtp_payload_type) {
93     active_decoder_ = -1;  // No active decoder.
94   }
95   if (active_cng_decoder_ == rtp_payload_type) {
96     active_cng_decoder_ = -1;  // No active CNG decoder.
97   }
98   return kOK;
99 }
100 
GetDecoderInfo(uint8_t rtp_payload_type) const101 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
102     uint8_t rtp_payload_type) const {
103   DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
104   if (it == decoders_.end()) {
105     // Decoder not found.
106     return NULL;
107   }
108   return &(*it).second;
109 }
110 
GetRtpPayloadType(NetEqDecoder codec_type) const111 uint8_t DecoderDatabase::GetRtpPayloadType(
112     NetEqDecoder codec_type) const {
113   DecoderMap::const_iterator it;
114   for (it = decoders_.begin(); it != decoders_.end(); ++it) {
115     if ((*it).second.codec_type == codec_type) {
116       // Match found.
117       return (*it).first;
118     }
119   }
120   // No match.
121   return kRtpPayloadTypeError;
122 }
123 
GetDecoder(uint8_t rtp_payload_type)124 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
125   if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type)) {
126     // These are not real decoders.
127     return NULL;
128   }
129   DecoderMap::iterator it = decoders_.find(rtp_payload_type);
130   if (it == decoders_.end()) {
131     // Decoder not found.
132     return NULL;
133   }
134   DecoderInfo* info = &(*it).second;
135   if (!info->decoder) {
136     // Create the decoder object.
137     AudioDecoder* decoder = CreateAudioDecoder(info->codec_type);
138     assert(decoder);  // Should not be able to have an unsupported codec here.
139     info->decoder = decoder;
140   }
141   return info->decoder;
142 }
143 
IsType(uint8_t rtp_payload_type,NetEqDecoder codec_type) const144 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 
IsComfortNoise(uint8_t rtp_payload_type) const154 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
155   if (IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGnb) ||
156       IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGwb) ||
157       IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGswb32kHz) ||
158       IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGswb48kHz)) {
159     return true;
160   } else {
161     return false;
162   }
163 }
164 
IsDtmf(uint8_t rtp_payload_type) const165 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
166   return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
167 }
168 
IsRed(uint8_t rtp_payload_type) const169 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
170   return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
171 }
172 
SetActiveDecoder(uint8_t rtp_payload_type,bool * new_decoder)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 
GetActiveDecoder()206 AudioDecoder* DecoderDatabase::GetActiveDecoder() {
207   if (active_decoder_ < 0) {
208     // No active decoder.
209     return NULL;
210   }
211   return GetDecoder(active_decoder_);
212 }
213 
SetActiveCngDecoder(uint8_t rtp_payload_type)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 
GetActiveCngDecoder()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 
CheckPayloadTypes(const PacketList & packet_list) const248 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       LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
254                       << static_cast<int>((*it)->header.payloadType);
255       return kDecoderNotFound;
256     }
257   }
258   return kOK;
259 }
260 
261 
262 }  // namespace webrtc
263