blob: 92d4bab1e4a573fb3c84ef53fa724ebfeabe860c [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
henrik.lundin4cf61dd2015-12-09 06:20:58 -080016#include "webrtc/base/checks.h"
Henrik Lundind67a2192015-08-03 12:54:37 +020017#include "webrtc/base/logging.h"
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000018#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000019
20namespace webrtc {
21
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000022DecoderDatabase::DecoderDatabase()
23 : active_decoder_(-1), active_cng_decoder_(-1) {}
24
25DecoderDatabase::~DecoderDatabase() {}
26
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000027DecoderDatabase::DecoderInfo::~DecoderInfo() {
28 if (!external) delete decoder;
29}
30
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000031bool DecoderDatabase::Empty() const { return decoders_.empty(); }
32
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000033int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000034
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000035void DecoderDatabase::Reset() {
36 decoders_.clear();
37 active_decoder_ = -1;
38 active_cng_decoder_ = -1;
39}
40
41int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080042 NetEqDecoder codec_type,
43 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000044 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000045 return kInvalidRtpPayloadType;
46 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000047 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000048 return kCodecNotSupported;
49 }
henrik.lundin4cf61dd2015-12-09 06:20:58 -080050 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));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000053 if (ret.second == false) {
54 // Database already contains a decoder with type |rtp_payload_type|.
55 return kDecoderExists;
56 }
57 return kOK;
58}
59
60int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
61 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080062 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000063 int fs_hz,
64 AudioDecoder* decoder) {
65 if (rtp_payload_type > 0x7F) {
66 return kInvalidRtpPayloadType;
67 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000068 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000069 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 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000077 std::pair<DecoderMap::iterator, bool> ret;
henrik.lundin4cf61dd2015-12-09 06:20:58 -080078 DecoderInfo info(codec_type, codec_name, fs_hz, decoder, true);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000079 ret = decoders_.insert(std::make_pair(rtp_payload_type, info));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000080 if (ret.second == false) {
81 // Database already contains a decoder with type |rtp_payload_type|.
82 return kDecoderExists;
83 }
84 return kOK;
85}
86
87int 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
101const 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
111uint8_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
124AudioDecoder* 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.
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +0000137 AudioDecoder* decoder = CreateAudioDecoder(info->codec_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138 assert(decoder); // Should not be able to have an unsupported codec here.
139 info->decoder = decoder;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000140 }
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 {
kwibergee1879c2015-10-29 06:20:28 -0700155 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)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000159 return true;
160 } else {
161 return false;
162 }
163}
164
165bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700166 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000167}
168
169bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700170 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000171}
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.
Henrik Lundind67a2192015-08-03 12:54:37 +0200253 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
254 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 return kDecoderNotFound;
256 }
257 }
258 return kOK;
259}
260
261
262} // namespace webrtc