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