blob: bb4575f393a4aae0123ba98da4a5d6e7948a7fd5 [file] [log] [blame]
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +00001/*
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/neteq4/decoder_database.h"
12
13#include <assert.h>
14#include <utility> // pair
15
16#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
17
18namespace webrtc {
19
pbos@webrtc.orgdd1b19d2013-07-31 15:54:00 +000020DecoderDatabase::DecoderDatabase()
21 : active_decoder_(-1), active_cng_decoder_(-1) {}
22
23DecoderDatabase::~DecoderDatabase() {}
24
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000025DecoderDatabase::DecoderInfo::~DecoderInfo() {
26 if (!external) delete decoder;
27}
28
pbos@webrtc.orgdd1b19d2013-07-31 15:54:00 +000029bool DecoderDatabase::Empty() const { return decoders_.empty(); }
30
31int DecoderDatabase::Size() const { return decoders_.size(); }
32
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000033void DecoderDatabase::Reset() {
34 decoders_.clear();
35 active_decoder_ = -1;
36 active_cng_decoder_ = -1;
37}
38
39int 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
58int 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
86int 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
100const 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
110uint8_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
123AudioDecoder* 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
144bool 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
154bool 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
165bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
166 return IsType(rtp_payload_type, kDecoderAVT);
167}
168
169bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
170 return IsType(rtp_payload_type, kDecoderRED);
171}
172
173int 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
206AudioDecoder* DecoderDatabase::GetActiveDecoder() {
207 if (active_decoder_ < 0) {
208 // No active decoder.
209 return NULL;
210 }
211 return GetDecoder(active_decoder_);
212}
213
214int 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
240AudioDecoder* 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
248int 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