blob: 41803f754ac116a2ecf0d3e4e4f3a6138fe7a9f5 [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 Lundind67a2192015-08-03 12:54:37 +020016#include "webrtc/base/logging.h"
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000017#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000018
19namespace webrtc {
20
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000021DecoderDatabase::DecoderDatabase()
22 : active_decoder_(-1), active_cng_decoder_(-1) {}
23
24DecoderDatabase::~DecoderDatabase() {}
25
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000026DecoderDatabase::DecoderInfo::~DecoderInfo() {
27 if (!external) delete decoder;
28}
29
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000030bool DecoderDatabase::Empty() const { return decoders_.empty(); }
31
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000032int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000033
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000034void DecoderDatabase::Reset() {
35 decoders_.clear();
36 active_decoder_ = -1;
37 active_cng_decoder_ = -1;
38}
39
40int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
41 NetEqDecoder codec_type) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000042 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000043 return kInvalidRtpPayloadType;
44 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000045 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000046 return kCodecNotSupported;
47 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000048 int fs_hz = CodecSampleRateHz(codec_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000049 std::pair<DecoderMap::iterator, bool> ret;
50 DecoderInfo info(codec_type, fs_hz, NULL, false);
51 ret = decoders_.insert(std::make_pair(rtp_payload_type, info));
52 if (ret.second == false) {
53 // Database already contains a decoder with type |rtp_payload_type|.
54 return kDecoderExists;
55 }
56 return kOK;
57}
58
59int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
60 NetEqDecoder codec_type,
61 int fs_hz,
62 AudioDecoder* decoder) {
63 if (rtp_payload_type > 0x7F) {
64 return kInvalidRtpPayloadType;
65 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000066 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000067 return kCodecNotSupported;
68 }
69 if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
70 return kInvalidSampleRate;
71 }
72 if (!decoder) {
73 return kInvalidPointer;
74 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000075 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;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138 }
139 return info->decoder;
140}
141
142bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
143 NetEqDecoder codec_type) const {
144 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
145 if (it == decoders_.end()) {
146 // Decoder not found.
147 return false;
148 }
149 return ((*it).second.codec_type == codec_type);
150}
151
152bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700153 if (IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGnb) ||
154 IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGwb) ||
155 IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGswb32kHz) ||
156 IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGswb48kHz)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000157 return true;
158 } else {
159 return false;
160 }
161}
162
163bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700164 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000165}
166
167bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700168 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000169}
170
171int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
172 bool* new_decoder) {
173 // Check that |rtp_payload_type| exists in the database.
174 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
175 if (it == decoders_.end()) {
176 // Decoder not found.
177 return kDecoderNotFound;
178 }
179 assert(new_decoder);
180 *new_decoder = false;
181 if (active_decoder_ < 0) {
182 // This is the first active decoder.
183 *new_decoder = true;
184 } else if (active_decoder_ != rtp_payload_type) {
185 // Moving from one active decoder to another. Delete the first one.
186 DecoderMap::iterator it = decoders_.find(active_decoder_);
187 if (it == decoders_.end()) {
188 // Decoder not found. This should not be possible.
189 assert(false);
190 return kDecoderNotFound;
191 }
192 if (!(*it).second.external) {
193 // Delete the AudioDecoder object, unless it is an externally created
194 // decoder.
195 delete (*it).second.decoder;
196 (*it).second.decoder = NULL;
197 }
198 *new_decoder = true;
199 }
200 active_decoder_ = rtp_payload_type;
201 return kOK;
202}
203
204AudioDecoder* DecoderDatabase::GetActiveDecoder() {
205 if (active_decoder_ < 0) {
206 // No active decoder.
207 return NULL;
208 }
209 return GetDecoder(active_decoder_);
210}
211
212int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
213 // Check that |rtp_payload_type| exists in the database.
214 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
215 if (it == decoders_.end()) {
216 // Decoder not found.
217 return kDecoderNotFound;
218 }
219 if (active_cng_decoder_ >= 0 && active_cng_decoder_ != rtp_payload_type) {
220 // Moving from one active CNG decoder to another. Delete the first one.
221 DecoderMap::iterator it = decoders_.find(active_cng_decoder_);
222 if (it == decoders_.end()) {
223 // Decoder not found. This should not be possible.
224 assert(false);
225 return kDecoderNotFound;
226 }
227 if (!(*it).second.external) {
228 // Delete the AudioDecoder object, unless it is an externally created
229 // decoder.
230 delete (*it).second.decoder;
231 (*it).second.decoder = NULL;
232 }
233 }
234 active_cng_decoder_ = rtp_payload_type;
235 return kOK;
236}
237
238AudioDecoder* DecoderDatabase::GetActiveCngDecoder() {
239 if (active_cng_decoder_ < 0) {
240 // No active CNG decoder.
241 return NULL;
242 }
243 return GetDecoder(active_cng_decoder_);
244}
245
246int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
247 PacketList::const_iterator it;
248 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
249 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
250 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200251 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
252 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000253 return kDecoderNotFound;
254 }
255 }
256 return kOK;
257}
258
259
260} // namespace webrtc