blob: d501f3e588d601092b1c43ae156d3ed68a32a7a0 [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
kwiberg0fa0a972016-04-19 05:03:45 -070027DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
28 const std::string& nm,
29 int fs,
30 AudioDecoder* ext_dec)
31 : codec_type(ct),
32 name(nm),
33 fs_hz(fs),
kwiberg0fa0a972016-04-19 05:03:45 -070034 external_decoder(ext_dec) {}
35
36DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
37DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
38
39AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() {
40 if (external_decoder) {
41 RTC_DCHECK(!decoder_);
42 return external_decoder;
43 }
44 if (!decoder_) {
45 decoder_.reset(CreateAudioDecoder(codec_type));
46 }
47 RTC_DCHECK(decoder_);
48 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000049}
50
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000051bool DecoderDatabase::Empty() const { return decoders_.empty(); }
52
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000053int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000054
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000055void DecoderDatabase::Reset() {
56 decoders_.clear();
57 active_decoder_ = -1;
58 active_cng_decoder_ = -1;
59}
60
61int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080062 NetEqDecoder codec_type,
63 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000064 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000065 return kInvalidRtpPayloadType;
66 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000067 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000068 return kCodecNotSupported;
69 }
henrik.lundin4cf61dd2015-12-09 06:20:58 -080070 const int fs_hz = CodecSampleRateHz(codec_type);
kwiberg0fa0a972016-04-19 05:03:45 -070071 DecoderInfo info(codec_type, name, fs_hz, nullptr);
72 auto ret =
73 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000074 if (ret.second == false) {
75 // Database already contains a decoder with type |rtp_payload_type|.
76 return kDecoderExists;
77 }
78 return kOK;
79}
80
81int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
82 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080083 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000084 int fs_hz,
85 AudioDecoder* decoder) {
86 if (rtp_payload_type > 0x7F) {
87 return kInvalidRtpPayloadType;
88 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000089 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090 return kCodecNotSupported;
91 }
92 if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
93 return kInvalidSampleRate;
94 }
95 if (!decoder) {
96 return kInvalidPointer;
97 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000098 std::pair<DecoderMap::iterator, bool> ret;
kwiberg0fa0a972016-04-19 05:03:45 -070099 DecoderInfo info(codec_type, codec_name, fs_hz, decoder);
100 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000101 if (ret.second == false) {
102 // Database already contains a decoder with type |rtp_payload_type|.
103 return kDecoderExists;
104 }
105 return kOK;
106}
107
108int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
109 if (decoders_.erase(rtp_payload_type) == 0) {
110 // No decoder with that |rtp_payload_type|.
111 return kDecoderNotFound;
112 }
113 if (active_decoder_ == rtp_payload_type) {
114 active_decoder_ = -1; // No active decoder.
115 }
116 if (active_cng_decoder_ == rtp_payload_type) {
117 active_cng_decoder_ = -1; // No active CNG decoder.
118 }
119 return kOK;
120}
121
122const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
123 uint8_t rtp_payload_type) const {
124 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
125 if (it == decoders_.end()) {
126 // Decoder not found.
127 return NULL;
128 }
129 return &(*it).second;
130}
131
132uint8_t DecoderDatabase::GetRtpPayloadType(
133 NetEqDecoder codec_type) const {
134 DecoderMap::const_iterator it;
135 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
136 if ((*it).second.codec_type == codec_type) {
137 // Match found.
138 return (*it).first;
139 }
140 }
141 // No match.
142 return kRtpPayloadTypeError;
143}
144
145AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
146 if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type)) {
147 // These are not real decoders.
148 return NULL;
149 }
150 DecoderMap::iterator it = decoders_.find(rtp_payload_type);
151 if (it == decoders_.end()) {
152 // Decoder not found.
153 return NULL;
154 }
155 DecoderInfo* info = &(*it).second;
kwiberg0fa0a972016-04-19 05:03:45 -0700156 return info->GetDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000157}
158
159bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
160 NetEqDecoder codec_type) const {
161 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
162 if (it == decoders_.end()) {
163 // Decoder not found.
164 return false;
165 }
166 return ((*it).second.codec_type == codec_type);
167}
168
169bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700170 if (IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGnb) ||
171 IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGwb) ||
172 IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGswb32kHz) ||
173 IsType(rtp_payload_type, NetEqDecoder::kDecoderCNGswb48kHz)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000174 return true;
175 } else {
176 return false;
177 }
178}
179
180bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700181 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000182}
183
184bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700185 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000186}
187
188int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
189 bool* new_decoder) {
190 // Check that |rtp_payload_type| exists in the database.
191 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
192 if (it == decoders_.end()) {
193 // Decoder not found.
194 return kDecoderNotFound;
195 }
196 assert(new_decoder);
197 *new_decoder = false;
198 if (active_decoder_ < 0) {
199 // This is the first active decoder.
200 *new_decoder = true;
201 } else if (active_decoder_ != rtp_payload_type) {
202 // Moving from one active decoder to another. Delete the first one.
203 DecoderMap::iterator it = decoders_.find(active_decoder_);
204 if (it == decoders_.end()) {
205 // Decoder not found. This should not be possible.
206 assert(false);
207 return kDecoderNotFound;
208 }
kwiberg0fa0a972016-04-19 05:03:45 -0700209 it->second.DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000210 *new_decoder = true;
211 }
212 active_decoder_ = rtp_payload_type;
213 return kOK;
214}
215
216AudioDecoder* DecoderDatabase::GetActiveDecoder() {
217 if (active_decoder_ < 0) {
218 // No active decoder.
219 return NULL;
220 }
221 return GetDecoder(active_decoder_);
222}
223
224int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
225 // Check that |rtp_payload_type| exists in the database.
226 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
227 if (it == decoders_.end()) {
228 // Decoder not found.
229 return kDecoderNotFound;
230 }
231 if (active_cng_decoder_ >= 0 && active_cng_decoder_ != rtp_payload_type) {
232 // Moving from one active CNG decoder to another. Delete the first one.
233 DecoderMap::iterator it = decoders_.find(active_cng_decoder_);
234 if (it == decoders_.end()) {
235 // Decoder not found. This should not be possible.
236 assert(false);
237 return kDecoderNotFound;
238 }
kwiberg0fa0a972016-04-19 05:03:45 -0700239 it->second.DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 }
241 active_cng_decoder_ = rtp_payload_type;
242 return kOK;
243}
244
245AudioDecoder* DecoderDatabase::GetActiveCngDecoder() {
246 if (active_cng_decoder_ < 0) {
247 // No active CNG decoder.
248 return NULL;
249 }
250 return GetDecoder(active_cng_decoder_);
251}
252
253int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
254 PacketList::const_iterator it;
255 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
256 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
257 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200258 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
259 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000260 return kDecoderNotFound;
261 }
262 }
263 return kOK;
264}
265
266
267} // namespace webrtc