blob: b9097b0873a339368a6a0aa55620a092acfa4dfc [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-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
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000011#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
13#include <assert.h>
14#include <utility> // pair
15
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000016#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000017
18namespace webrtc {
19
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000020DecoderDatabase::DecoderDatabase()
21 : active_decoder_(-1), active_cng_decoder_(-1) {}
22
23DecoderDatabase::~DecoderDatabase() {}
24
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000025DecoderDatabase::DecoderInfo::~DecoderInfo() {
26 if (!external) delete decoder;
27}
28
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000029bool DecoderDatabase::Empty() const { return decoders_.empty(); }
30
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000031int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000032
henrik.lundin@webrtc.orgd94659d2013-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) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000041 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000042 return kInvalidRtpPayloadType;
43 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000044 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000045 return kCodecNotSupported;
46 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000047 int fs_hz = CodecSampleRateHz(codec_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000048 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 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000065 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000066 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);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000077 ret = decoders_.insert(std::make_pair(rtp_payload_type, info));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000078 if (ret.second == false) {
79 // Database already contains a decoder with type |rtp_payload_type|.
80 return kDecoderExists;
81 }
82 return kOK;
83}
84
85int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
86 if (decoders_.erase(rtp_payload_type) == 0) {
87 // No decoder with that |rtp_payload_type|.
88 return kDecoderNotFound;
89 }
90 if (active_decoder_ == rtp_payload_type) {
91 active_decoder_ = -1; // No active decoder.
92 }
93 if (active_cng_decoder_ == rtp_payload_type) {
94 active_cng_decoder_ = -1; // No active CNG decoder.
95 }
96 return kOK;
97}
98
99const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
100 uint8_t rtp_payload_type) const {
101 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
102 if (it == decoders_.end()) {
103 // Decoder not found.
104 return NULL;
105 }
106 return &(*it).second;
107}
108
109uint8_t DecoderDatabase::GetRtpPayloadType(
110 NetEqDecoder codec_type) const {
111 DecoderMap::const_iterator it;
112 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
113 if ((*it).second.codec_type == codec_type) {
114 // Match found.
115 return (*it).first;
116 }
117 }
118 // No match.
119 return kRtpPayloadTypeError;
120}
121
122AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
123 if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type)) {
124 // These are not real decoders.
125 return NULL;
126 }
127 DecoderMap::iterator it = decoders_.find(rtp_payload_type);
128 if (it == decoders_.end()) {
129 // Decoder not found.
130 return NULL;
131 }
132 DecoderInfo* info = &(*it).second;
133 if (!info->decoder) {
134 // Create the decoder object.
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +0000135 AudioDecoder* decoder = CreateAudioDecoder(info->codec_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000136 assert(decoder); // Should not be able to have an unsupported codec here.
137 info->decoder = decoder;
138 info->decoder->Init();
139 }
140 return info->decoder;
141}
142
143bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
144 NetEqDecoder codec_type) const {
145 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
146 if (it == decoders_.end()) {
147 // Decoder not found.
148 return false;
149 }
150 return ((*it).second.codec_type == codec_type);
151}
152
153bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
154 if (IsType(rtp_payload_type, kDecoderCNGnb) ||
155 IsType(rtp_payload_type, kDecoderCNGwb) ||
156 IsType(rtp_payload_type, kDecoderCNGswb32kHz) ||
157 IsType(rtp_payload_type, kDecoderCNGswb48kHz)) {
158 return true;
159 } else {
160 return false;
161 }
162}
163
164bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
165 return IsType(rtp_payload_type, kDecoderAVT);
166}
167
168bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
169 return IsType(rtp_payload_type, kDecoderRED);
170}
171
172int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
173 bool* new_decoder) {
174 // Check that |rtp_payload_type| exists in the database.
175 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
176 if (it == decoders_.end()) {
177 // Decoder not found.
178 return kDecoderNotFound;
179 }
180 assert(new_decoder);
181 *new_decoder = false;
182 if (active_decoder_ < 0) {
183 // This is the first active decoder.
184 *new_decoder = true;
185 } else if (active_decoder_ != rtp_payload_type) {
186 // Moving from one active decoder to another. Delete the first one.
187 DecoderMap::iterator it = decoders_.find(active_decoder_);
188 if (it == decoders_.end()) {
189 // Decoder not found. This should not be possible.
190 assert(false);
191 return kDecoderNotFound;
192 }
193 if (!(*it).second.external) {
194 // Delete the AudioDecoder object, unless it is an externally created
195 // decoder.
196 delete (*it).second.decoder;
197 (*it).second.decoder = NULL;
198 }
199 *new_decoder = true;
200 }
201 active_decoder_ = rtp_payload_type;
202 return kOK;
203}
204
205AudioDecoder* DecoderDatabase::GetActiveDecoder() {
206 if (active_decoder_ < 0) {
207 // No active decoder.
208 return NULL;
209 }
210 return GetDecoder(active_decoder_);
211}
212
213int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
214 // Check that |rtp_payload_type| exists in the database.
215 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
216 if (it == decoders_.end()) {
217 // Decoder not found.
218 return kDecoderNotFound;
219 }
220 if (active_cng_decoder_ >= 0 && active_cng_decoder_ != rtp_payload_type) {
221 // Moving from one active CNG decoder to another. Delete the first one.
222 DecoderMap::iterator it = decoders_.find(active_cng_decoder_);
223 if (it == decoders_.end()) {
224 // Decoder not found. This should not be possible.
225 assert(false);
226 return kDecoderNotFound;
227 }
228 if (!(*it).second.external) {
229 // Delete the AudioDecoder object, unless it is an externally created
230 // decoder.
231 delete (*it).second.decoder;
232 (*it).second.decoder = NULL;
233 }
234 }
235 active_cng_decoder_ = rtp_payload_type;
236 return kOK;
237}
238
239AudioDecoder* DecoderDatabase::GetActiveCngDecoder() {
240 if (active_cng_decoder_ < 0) {
241 // No active CNG decoder.
242 return NULL;
243 }
244 return GetDecoder(active_cng_decoder_);
245}
246
247int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
248 PacketList::const_iterator it;
249 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
250 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
251 // Payload type is not found.
252 return kDecoderNotFound;
253 }
254 }
255 return kOK;
256}
257
258
259} // namespace webrtc