AcmReceiver: use std::map instead of an array to keep the list of decoders
R=kwiberg@webrtc.org Review URL: https://webrtc-codereview.appspot.com/50419004 Cr-Commit-Position: refs/heads/master@{#8824} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8824 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
3335a4ffc8
commit
a4bef3e6c0
@ -15,6 +15,7 @@
|
||||
#include <algorithm> // sort
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/format_macros.h"
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "webrtc/common_types.h"
|
||||
@ -136,9 +137,6 @@ AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
|
||||
missing_packets_sync_stream_(),
|
||||
late_packets_sync_stream_() {
|
||||
assert(clock_);
|
||||
for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
|
||||
decoders_[n].registered = false;
|
||||
}
|
||||
|
||||
// Make sure we are on the same page as NetEq. Post-decode VAD is disabled by
|
||||
// default in NetEq4, however, Audio Conference Mixer relies on VAD decision
|
||||
@ -279,7 +277,6 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
|
||||
<< " is not registered.";
|
||||
return -1;
|
||||
}
|
||||
assert(codec_id < ACMCodecDB::kMaxNumCodecs);
|
||||
const int sample_rate_hz = ACMCodecDB::CodecFreq(codec_id);
|
||||
receive_timestamp = NowInTimestamp(sample_rate_hz);
|
||||
|
||||
@ -483,7 +480,7 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
|
||||
uint8_t payload_type,
|
||||
int channels,
|
||||
AudioDecoder* audio_decoder) {
|
||||
assert(acm_codec_id >= 0 && acm_codec_id < ACMCodecDB::kMaxNumCodecs);
|
||||
CHECK_GE(acm_codec_id, 0);
|
||||
NetEqDecoder neteq_decoder = ACMCodecDB::neteq_decoders_[acm_codec_id];
|
||||
|
||||
// Make sure the right decoder is registered for Opus.
|
||||
@ -494,10 +491,12 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
|
||||
CriticalSectionScoped lock(crit_sect_.get());
|
||||
|
||||
// The corresponding NetEq decoder ID.
|
||||
// If this coder has been registered before.
|
||||
if (decoders_[acm_codec_id].registered) {
|
||||
if (decoders_[acm_codec_id].payload_type == payload_type &&
|
||||
decoders_[acm_codec_id].channels == channels) {
|
||||
// If this codec has been registered before.
|
||||
auto it = decoders_.find(acm_codec_id);
|
||||
if (it != decoders_.end()) {
|
||||
const Decoder& decoder = it->second;
|
||||
if (decoder.payload_type == payload_type &&
|
||||
decoder.channels == channels) {
|
||||
// Re-registering the same codec with the same payload-type. Do nothing
|
||||
// and return.
|
||||
return 0;
|
||||
@ -505,12 +504,14 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
|
||||
|
||||
// Changing the payload-type or number of channels for this codec.
|
||||
// First unregister. Then register with new payload-type/channels.
|
||||
if (neteq_->RemovePayloadType(decoders_[acm_codec_id].payload_type) !=
|
||||
if (neteq_->RemovePayloadType(decoder.payload_type) !=
|
||||
NetEq::kOK) {
|
||||
LOG_F(LS_ERROR) << "Cannot remove payload "
|
||||
<< static_cast<int>(decoders_[acm_codec_id].payload_type);
|
||||
<< static_cast<int>(decoder.payload_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
decoders_.erase(it);
|
||||
}
|
||||
|
||||
int ret_val;
|
||||
@ -523,15 +524,14 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
|
||||
if (ret_val != NetEq::kOK) {
|
||||
LOG_FERR3(LS_ERROR, "AcmReceiver::AddCodec", acm_codec_id,
|
||||
static_cast<int>(payload_type), channels);
|
||||
// Registration failed, delete the allocated space and set the pointer to
|
||||
// NULL, for the record.
|
||||
decoders_[acm_codec_id].registered = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
decoders_[acm_codec_id].registered = true;
|
||||
decoders_[acm_codec_id].payload_type = payload_type;
|
||||
decoders_[acm_codec_id].channels = channels;
|
||||
Decoder decoder;
|
||||
decoder.acm_codec_id = acm_codec_id;
|
||||
decoder.payload_type = payload_type;
|
||||
decoder.channels = channels;
|
||||
decoders_[acm_codec_id] = decoder;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -556,23 +556,25 @@ void AcmReceiver::FlushBuffers() {
|
||||
int AcmReceiver::RemoveAllCodecs() {
|
||||
int ret_val = 0;
|
||||
CriticalSectionScoped lock(crit_sect_.get());
|
||||
for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
|
||||
if (decoders_[n].registered) {
|
||||
if (neteq_->RemovePayloadType(decoders_[n].payload_type) == 0) {
|
||||
decoders_[n].registered = false;
|
||||
} else {
|
||||
LOG_F(LS_ERROR) << "Cannot remove payload "
|
||||
<< static_cast<int>(decoders_[n].payload_type);
|
||||
ret_val = -1;
|
||||
}
|
||||
for (auto it = decoders_.begin(); it != decoders_.end(); ) {
|
||||
auto cur = it;
|
||||
++it; // it will be valid even if we erase cur
|
||||
if (neteq_->RemovePayloadType(cur->second.payload_type) == 0) {
|
||||
decoders_.erase(cur);
|
||||
} else {
|
||||
LOG_F(LS_ERROR) << "Cannot remove payload "
|
||||
<< static_cast<int>(cur->second.payload_type);
|
||||
ret_val = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// No codec is registered, invalidate last audio decoder.
|
||||
last_audio_decoder_ = -1;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int AcmReceiver::RemoveCodec(uint8_t payload_type) {
|
||||
CriticalSectionScoped lock(crit_sect_.get());
|
||||
int codec_index = PayloadType2CodecIndex(payload_type);
|
||||
if (codec_index < 0) { // Such a payload-type is not registered.
|
||||
return 0;
|
||||
@ -582,8 +584,7 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) {
|
||||
static_cast<int>(payload_type));
|
||||
return -1;
|
||||
}
|
||||
CriticalSectionScoped lock(crit_sect_.get());
|
||||
decoders_[codec_index].registered = false;
|
||||
decoders_.erase(codec_index);
|
||||
if (last_audio_decoder_ == codec_index)
|
||||
last_audio_decoder_ = -1; // Codec is removed, invalidate last decoder.
|
||||
return 0;
|
||||
@ -611,12 +612,12 @@ int AcmReceiver::last_audio_codec_id() const {
|
||||
|
||||
int AcmReceiver::RedPayloadType() const {
|
||||
CriticalSectionScoped lock(crit_sect_.get());
|
||||
if (ACMCodecDB::kRED < 0 ||
|
||||
!decoders_[ACMCodecDB::kRED].registered) {
|
||||
auto it = decoders_.find(ACMCodecDB::kRED);
|
||||
if (ACMCodecDB::kRED < 0 || it == decoders_.end()) {
|
||||
LOG_F(LS_WARNING) << "RED is not registered.";
|
||||
return -1;
|
||||
}
|
||||
return decoders_[ACMCodecDB::kRED].payload_type;
|
||||
return it->second.payload_type;
|
||||
}
|
||||
|
||||
int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
|
||||
@ -624,10 +625,11 @@ int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
|
||||
if (last_audio_decoder_ < 0) {
|
||||
return -1;
|
||||
}
|
||||
assert(decoders_[last_audio_decoder_].registered);
|
||||
auto it = decoders_.find(last_audio_decoder_);
|
||||
CHECK(it != decoders_.end());
|
||||
memcpy(codec, &ACMCodecDB::database_[last_audio_decoder_], sizeof(CodecInst));
|
||||
codec->pltype = decoders_[last_audio_decoder_].payload_type;
|
||||
codec->channels = decoders_[last_audio_decoder_].channels;
|
||||
codec->pltype = it->second.payload_type;
|
||||
codec->channels = it->second.channels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -685,16 +687,18 @@ int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
|
||||
return -1;
|
||||
}
|
||||
memcpy(codec, &ACMCodecDB::database_[codec_index], sizeof(CodecInst));
|
||||
codec->pltype = decoders_[codec_index].payload_type;
|
||||
codec->channels = decoders_[codec_index].channels;
|
||||
// Safe not to check the iterator
|
||||
const Decoder& decoder = decoders_.find(codec_index)->second;
|
||||
codec->pltype = decoder.payload_type;
|
||||
codec->channels = decoder.channels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AcmReceiver::PayloadType2CodecIndex(uint8_t payload_type) const {
|
||||
for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
|
||||
if (decoders_[n].registered && decoders_[n].payload_type == payload_type) {
|
||||
return n;
|
||||
}
|
||||
for (const auto& decoder_pair : decoders_) {
|
||||
const Decoder& decoder = decoder_pair.second;
|
||||
if (decoder.payload_type == payload_type)
|
||||
return decoder.acm_codec_id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -801,9 +805,10 @@ bool AcmReceiver::GetSilence(int desired_sample_rate_hz, AudioFrame* frame) {
|
||||
int AcmReceiver::RtpHeaderToCodecIndex(
|
||||
const RTPHeader &rtp_header, const uint8_t* payload) const {
|
||||
uint8_t payload_type = rtp_header.payloadType;
|
||||
auto it = decoders_.find(ACMCodecDB::kRED);
|
||||
if (ACMCodecDB::kRED >= 0 && // This ensures that RED is defined in WebRTC.
|
||||
decoders_[ACMCodecDB::kRED].registered &&
|
||||
payload_type == decoders_[ACMCodecDB::kRED].payload_type) {
|
||||
it != decoders_.end() &&
|
||||
payload_type == it->second.payload_type) {
|
||||
// This is a RED packet, get the payload of the audio codec.
|
||||
payload_type = payload[0] & 0x7F;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_RECEIVER_H_
|
||||
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_RECEIVER_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
@ -39,7 +40,7 @@ class Nack;
|
||||
class AcmReceiver {
|
||||
public:
|
||||
struct Decoder {
|
||||
bool registered;
|
||||
int acm_codec_id;
|
||||
uint8_t payload_type;
|
||||
// This field is meaningful for codecs where both mono and
|
||||
// stereo versions are registered under the same ID.
|
||||
@ -334,7 +335,7 @@ class AcmReceiver {
|
||||
bool nack_enabled_ GUARDED_BY(crit_sect_);
|
||||
CallStatistics call_stats_ GUARDED_BY(crit_sect_);
|
||||
NetEq* neteq_;
|
||||
Decoder decoders_[ACMCodecDB::kMaxNumCodecs];
|
||||
std::map<int, Decoder> decoders_; // keyed by ACM codec ID
|
||||
bool vad_enabled_;
|
||||
Clock* clock_; // TODO(henrik.lundin) Make const if possible.
|
||||
bool resampled_last_output_frame_ GUARDED_BY(crit_sect_);
|
||||
|
Loading…
Reference in New Issue
Block a user