/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "webrtc/modules/audio_coding/neteq/decoder_database.h" #include #include // pair #include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h" namespace webrtc { DecoderDatabase::DecoderDatabase() : active_decoder_(-1), active_cng_decoder_(-1) {} DecoderDatabase::~DecoderDatabase() {} DecoderDatabase::DecoderInfo::~DecoderInfo() { if (!external) delete decoder; } bool DecoderDatabase::Empty() const { return decoders_.empty(); } int DecoderDatabase::Size() const { return static_cast(decoders_.size()); } void DecoderDatabase::Reset() { decoders_.clear(); active_decoder_ = -1; active_cng_decoder_ = -1; } int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type, NetEqDecoder codec_type) { if (rtp_payload_type > kMaxRtpPayloadType) { return kInvalidRtpPayloadType; } if (!AudioDecoder::CodecSupported(codec_type)) { return kCodecNotSupported; } int fs_hz = AudioDecoder::CodecSampleRateHz(codec_type); std::pair ret; DecoderInfo info(codec_type, fs_hz, NULL, false); ret = decoders_.insert(std::make_pair(rtp_payload_type, info)); if (ret.second == false) { // Database already contains a decoder with type |rtp_payload_type|. return kDecoderExists; } return kOK; } int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type, NetEqDecoder codec_type, int fs_hz, AudioDecoder* decoder) { if (rtp_payload_type > 0x7F) { return kInvalidRtpPayloadType; } if (!AudioDecoder::CodecSupported(codec_type)) { return kCodecNotSupported; } if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) { return kInvalidSampleRate; } if (!decoder) { return kInvalidPointer; } decoder->Init(); std::pair ret; DecoderInfo info(codec_type, fs_hz, decoder, true); ret = decoders_.insert( std::pair(rtp_payload_type, info)); if (ret.second == false) { // Database already contains a decoder with type |rtp_payload_type|. return kDecoderExists; } return kOK; } int DecoderDatabase::Remove(uint8_t rtp_payload_type) { if (decoders_.erase(rtp_payload_type) == 0) { // No decoder with that |rtp_payload_type|. return kDecoderNotFound; } if (active_decoder_ == rtp_payload_type) { active_decoder_ = -1; // No active decoder. } if (active_cng_decoder_ == rtp_payload_type) { active_cng_decoder_ = -1; // No active CNG decoder. } return kOK; } const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo( uint8_t rtp_payload_type) const { DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); if (it == decoders_.end()) { // Decoder not found. return NULL; } return &(*it).second; } uint8_t DecoderDatabase::GetRtpPayloadType( NetEqDecoder codec_type) const { DecoderMap::const_iterator it; for (it = decoders_.begin(); it != decoders_.end(); ++it) { if ((*it).second.codec_type == codec_type) { // Match found. return (*it).first; } } // No match. return kRtpPayloadTypeError; } AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) { if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type)) { // These are not real decoders. return NULL; } DecoderMap::iterator it = decoders_.find(rtp_payload_type); if (it == decoders_.end()) { // Decoder not found. return NULL; } DecoderInfo* info = &(*it).second; if (!info->decoder) { // Create the decoder object. AudioDecoder* decoder = AudioDecoder::CreateAudioDecoder(info->codec_type); assert(decoder); // Should not be able to have an unsupported codec here. info->decoder = decoder; info->decoder->Init(); } return info->decoder; } bool DecoderDatabase::IsType(uint8_t rtp_payload_type, NetEqDecoder codec_type) const { DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); if (it == decoders_.end()) { // Decoder not found. return false; } return ((*it).second.codec_type == codec_type); } bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const { if (IsType(rtp_payload_type, kDecoderCNGnb) || IsType(rtp_payload_type, kDecoderCNGwb) || IsType(rtp_payload_type, kDecoderCNGswb32kHz) || IsType(rtp_payload_type, kDecoderCNGswb48kHz)) { return true; } else { return false; } } bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const { return IsType(rtp_payload_type, kDecoderAVT); } bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const { return IsType(rtp_payload_type, kDecoderRED); } int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type, bool* new_decoder) { // Check that |rtp_payload_type| exists in the database. DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); if (it == decoders_.end()) { // Decoder not found. return kDecoderNotFound; } assert(new_decoder); *new_decoder = false; if (active_decoder_ < 0) { // This is the first active decoder. *new_decoder = true; } else if (active_decoder_ != rtp_payload_type) { // Moving from one active decoder to another. Delete the first one. DecoderMap::iterator it = decoders_.find(active_decoder_); if (it == decoders_.end()) { // Decoder not found. This should not be possible. assert(false); return kDecoderNotFound; } if (!(*it).second.external) { // Delete the AudioDecoder object, unless it is an externally created // decoder. delete (*it).second.decoder; (*it).second.decoder = NULL; } *new_decoder = true; } active_decoder_ = rtp_payload_type; return kOK; } AudioDecoder* DecoderDatabase::GetActiveDecoder() { if (active_decoder_ < 0) { // No active decoder. return NULL; } return GetDecoder(active_decoder_); } int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) { // Check that |rtp_payload_type| exists in the database. DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); if (it == decoders_.end()) { // Decoder not found. return kDecoderNotFound; } if (active_cng_decoder_ >= 0 && active_cng_decoder_ != rtp_payload_type) { // Moving from one active CNG decoder to another. Delete the first one. DecoderMap::iterator it = decoders_.find(active_cng_decoder_); if (it == decoders_.end()) { // Decoder not found. This should not be possible. assert(false); return kDecoderNotFound; } if (!(*it).second.external) { // Delete the AudioDecoder object, unless it is an externally created // decoder. delete (*it).second.decoder; (*it).second.decoder = NULL; } } active_cng_decoder_ = rtp_payload_type; return kOK; } AudioDecoder* DecoderDatabase::GetActiveCngDecoder() { if (active_cng_decoder_ < 0) { // No active CNG decoder. return NULL; } return GetDecoder(active_cng_decoder_); } int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const { PacketList::const_iterator it; for (it = packet_list.begin(); it != packet_list.end(); ++it) { if (decoders_.find((*it)->header.payloadType) == decoders_.end()) { // Payload type is not found. return kDecoderNotFound; } } return kOK; } } // namespace webrtc