summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc')
-rw-r--r--chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc142
1 files changed, 81 insertions, 61 deletions
diff --git a/chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc b/chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
index ac92198f92b..cb7c4184079 100644
--- a/chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
+++ b/chromium/third_party/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
@@ -21,8 +21,9 @@
#include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
#include "webrtc/modules/audio_coding/main/acm2/nack.h"
-#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
-#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
+#include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
+#include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
+#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
@@ -35,7 +36,6 @@ namespace acm2 {
namespace {
-const int kNeteqInitSampleRateHz = 16000;
const int kNackThresholdPackets = 2;
// |vad_activity_| field of |audio_frame| is set to |previous_audio_activity_|
@@ -117,21 +117,23 @@ bool IsCng(int codec_id) {
} // namespace
-AcmReceiver::AcmReceiver()
- : id_(0),
- neteq_(NetEq::Create(kNeteqInitSampleRateHz)),
+AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
+ : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+ id_(config.id),
last_audio_decoder_(-1), // Invalid value.
- decode_lock_(RWLockWrapper::CreateRWLock()),
- neteq_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
- vad_enabled_(true),
- previous_audio_activity_(AudioFrame::kVadUnknown),
- current_sample_rate_hz_(kNeteqInitSampleRateHz),
+ previous_audio_activity_(AudioFrame::kVadPassive),
+ current_sample_rate_hz_(config.neteq_config.sample_rate_hz),
nack_(),
nack_enabled_(false),
+ neteq_(NetEq::Create(config.neteq_config)),
+ decode_lock_(RWLockWrapper::CreateRWLock()),
+ vad_enabled_(true),
+ clock_(config.clock),
av_sync_(false),
initial_delay_manager_(),
missing_packets_sync_stream_(),
late_packets_sync_stream_() {
+ assert(clock_);
for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
decoders_[n].registered = false;
}
@@ -148,7 +150,6 @@ AcmReceiver::AcmReceiver()
AcmReceiver::~AcmReceiver() {
delete neteq_;
delete decode_lock_;
- delete neteq_crit_sect_;
}
int AcmReceiver::SetMinimumDelay(int delay_ms) {
@@ -162,7 +163,7 @@ int AcmReceiver::SetInitialDelay(int delay_ms) {
if (delay_ms < 0 || delay_ms > 10000) {
return -1;
}
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (delay_ms == 0) {
av_sync_ = false;
@@ -206,7 +207,7 @@ int AcmReceiver::LeastRequiredDelayMs() const {
}
int AcmReceiver::current_sample_rate_hz() const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
return current_sample_rate_hz_;
}
@@ -269,7 +270,7 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
const RTPHeader* header = &rtp_header.header; // Just a shorthand.
{
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
int codec_id = RtpHeaderToCodecIndex(*header, incoming_payload);
if (codec_id < 0) {
@@ -328,7 +329,7 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
rtp_header, receive_timestamp, packet_type, new_codec, sample_rate_hz,
missing_packets_sync_stream_.get());
}
- }
+ } // |crit_sect_| is released.
{
WriteLockScoped lock_codecs(*decode_lock_); // Lock to prevent an encoding.
@@ -359,7 +360,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
{
// Accessing members, take the lock.
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (av_sync_) {
assert(initial_delay_manager_.get());
@@ -404,7 +405,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
}
// Accessing members, take the lock.
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
// Update NACK.
int decoded_sequence_num = 0;
@@ -426,9 +427,13 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
if (ptr_audio_buffer == audio_buffer_) {
// Data is written to local buffer.
if (need_resampling) {
- samples_per_channel = resampler_.Resample10Msec(
- audio_buffer_, current_sample_rate_hz_, desired_freq_hz,
- num_channels, audio_frame->data_);
+ samples_per_channel =
+ resampler_.Resample10Msec(audio_buffer_,
+ current_sample_rate_hz_,
+ desired_freq_hz,
+ num_channels,
+ AudioFrame::kMaxDataSizeSamples,
+ audio_frame->data_);
if (samples_per_channel < 0) {
LOG_FERR0(LS_ERROR, "AcmReceiver::GetAudio") << "Resampler Failed.";
return -1;
@@ -442,9 +447,13 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
// Data is written into |audio_frame|.
if (need_resampling) {
// We might end up here ONLY if codec is changed.
- samples_per_channel = resampler_.Resample10Msec(
- audio_frame->data_, current_sample_rate_hz_, desired_freq_hz,
- num_channels, audio_buffer_);
+ samples_per_channel =
+ resampler_.Resample10Msec(audio_frame->data_,
+ current_sample_rate_hz_,
+ desired_freq_hz,
+ num_channels,
+ AudioFrame::kMaxDataSizeSamples,
+ audio_buffer_);
if (samples_per_channel < 0) {
LOG_FERR0(LS_ERROR, "AcmReceiver::GetAudio") << "Resampler Failed.";
return -1;
@@ -463,6 +472,19 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
SetAudioFrameActivityAndType(vad_enabled_, type, audio_frame);
previous_audio_activity_ = audio_frame->vad_activity_;
call_stats_.DecodedByNetEq(audio_frame->speech_type_);
+
+ // Computes the RTP timestamp of the first sample in |audio_frame| from
+ // |GetPlayoutTimestamp|, which is the timestamp of the last sample of
+ // |audio_frame|.
+ uint32_t playout_timestamp = 0;
+ if (GetPlayoutTimestamp(&playout_timestamp)) {
+ audio_frame->timestamp_ =
+ playout_timestamp - audio_frame->samples_per_channel_;
+ } else {
+ // Remain 0 until we have a valid |playout_timestamp|.
+ audio_frame->timestamp_ = 0;
+ }
+
return 0;
}
@@ -473,19 +495,25 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
assert(acm_codec_id >= 0 && acm_codec_id < ACMCodecDB::kMaxNumCodecs);
NetEqDecoder neteq_decoder = ACMCodecDB::neteq_decoders_[acm_codec_id];
- CriticalSectionScoped lock(neteq_crit_sect_);
+ // Make sure the right decoder is registered for Opus.
+ if (neteq_decoder == kDecoderOpus && channels == 2) {
+ neteq_decoder = kDecoderOpus_2ch;
+ }
+
+ 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) {
+ if (decoders_[acm_codec_id].payload_type == payload_type &&
+ decoders_[acm_codec_id].channels == channels) {
// Re-registering the same codec with the same payload-type. Do nothing
// and return.
return 0;
}
- // Changing the payload-type of this codec. First unregister. Then register
- // with new payload-type.
+ // 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) !=
NetEq::kOK) {
LOG_F(LS_ERROR) << "Cannot remover payload "
@@ -499,8 +527,7 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
ret_val = neteq_->RegisterPayloadType(neteq_decoder, payload_type);
} else {
ret_val = neteq_->RegisterExternalDecoder(
- audio_decoder, neteq_decoder,
- ACMCodecDB::database_[acm_codec_id].plfreq, payload_type);
+ audio_decoder, neteq_decoder, payload_type);
}
if (ret_val != NetEq::kOK) {
LOG_FERR3(LS_ERROR, "AcmReceiver::AddCodec", acm_codec_id, payload_type,
@@ -519,13 +546,13 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
void AcmReceiver::EnableVad() {
neteq_->EnableVad();
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
vad_enabled_ = true;
}
void AcmReceiver::DisableVad() {
neteq_->DisableVad();
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
vad_enabled_ = false;
}
@@ -537,7 +564,7 @@ void AcmReceiver::FlushBuffers() {
// many as it can.
int AcmReceiver::RemoveAllCodecs() {
int ret_val = 0;
- CriticalSectionScoped lock(neteq_crit_sect_);
+ 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) {
@@ -557,15 +584,13 @@ int AcmReceiver::RemoveAllCodecs() {
int AcmReceiver::RemoveCodec(uint8_t payload_type) {
int codec_index = PayloadType2CodecIndex(payload_type);
if (codec_index < 0) { // Such a payload-type is not registered.
- LOG(LS_WARNING) << "payload_type " << payload_type << " is not registered,"
- " no action is taken.";
return 0;
}
if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) {
LOG_FERR1(LS_ERROR, "AcmReceiver::RemoveCodec", payload_type);
return -1;
}
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
decoders_[codec_index].registered = false;
if (last_audio_decoder_ == codec_index)
last_audio_decoder_ = -1; // Codec is removed, invalidate last decoder.
@@ -573,26 +598,27 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) {
}
void AcmReceiver::set_id(int id) {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
id_ = id;
}
-uint32_t AcmReceiver::PlayoutTimestamp() {
+bool AcmReceiver::GetPlayoutTimestamp(uint32_t* timestamp) {
if (av_sync_) {
assert(initial_delay_manager_.get());
- if (initial_delay_manager_->buffering())
- return initial_delay_manager_->playout_timestamp();
+ if (initial_delay_manager_->buffering()) {
+ return initial_delay_manager_->GetPlayoutTimestamp(timestamp);
+ }
}
- return neteq_->PlayoutTimestamp();
+ return neteq_->GetPlayoutTimestamp(timestamp);
}
int AcmReceiver::last_audio_codec_id() const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
return last_audio_decoder_;
}
int AcmReceiver::last_audio_payload_type() const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (last_audio_decoder_ < 0)
return -1;
assert(decoders_[last_audio_decoder_].registered);
@@ -600,7 +626,7 @@ int AcmReceiver::last_audio_payload_type() const {
}
int AcmReceiver::RedPayloadType() const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (ACMCodecDB::kRED < 0 ||
!decoders_[ACMCodecDB::kRED].registered) {
LOG_F(LS_WARNING) << "RED is not registered.";
@@ -610,9 +636,8 @@ int AcmReceiver::RedPayloadType() const {
}
int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (last_audio_decoder_ < 0) {
- LOG_F(LS_WARNING) << "No audio payload is received, yet.";
return -1;
}
assert(decoders_[last_audio_decoder_].registered);
@@ -636,6 +661,7 @@ void AcmReceiver::NetworkStatistics(ACMNetworkStatistics* acm_stat) {
acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm;
+ acm_stat->addedSamples = neteq_stat.added_zero_samples;
std::vector<int> waiting_times;
neteq_->WaitingTimes(&waiting_times);
@@ -665,7 +691,7 @@ void AcmReceiver::NetworkStatistics(ACMNetworkStatistics* acm_stat) {
int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
CodecInst* codec) const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
int codec_index = PayloadType2CodecIndex(payload_type);
if (codec_index < 0) {
LOG_FERR1(LS_ERROR, "AcmReceiver::DecoderByPayloadType", payload_type);
@@ -691,7 +717,7 @@ int AcmReceiver::EnableNack(size_t max_nack_list_size) {
if (max_nack_list_size == 0 || max_nack_list_size > Nack::kNackListSizeLimit)
return -1;
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (!nack_enabled_) {
nack_.reset(Nack::Create(kNackThresholdPackets));
nack_enabled_ = true;
@@ -707,14 +733,14 @@ int AcmReceiver::EnableNack(size_t max_nack_list_size) {
}
void AcmReceiver::DisableNack() {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
nack_.reset(); // Memory is released.
nack_enabled_ = false;
}
std::vector<uint16_t> AcmReceiver::GetNackList(
int round_trip_time_ms) const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
if (round_trip_time_ms < 0) {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
"GetNackList: round trip time cannot be negative."
@@ -730,7 +756,7 @@ std::vector<uint16_t> AcmReceiver::GetNackList(
void AcmReceiver::ResetInitialDelay() {
{
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
av_sync_ = false;
initial_delay_manager_.reset(NULL);
missing_packets_sync_stream_.reset(NULL);
@@ -752,13 +778,9 @@ bool AcmReceiver::GetSilence(int desired_sample_rate_hz, AudioFrame* frame) {
// exceeds a threshold.
int num_packets;
int max_num_packets;
- int buffer_size_byte;
- int max_buffer_size_byte;
const float kBufferingThresholdScale = 0.9f;
- neteq_->PacketBufferStatistics(&num_packets, &max_num_packets,
- &buffer_size_byte, &max_buffer_size_byte);
- if (num_packets > max_num_packets * kBufferingThresholdScale ||
- buffer_size_byte > max_buffer_size_byte * kBufferingThresholdScale) {
+ neteq_->PacketBufferStatistics(&num_packets, &max_num_packets);
+ if (num_packets > max_num_packets * kBufferingThresholdScale) {
initial_delay_manager_->DisableBuffering();
return false;
}
@@ -771,7 +793,6 @@ bool AcmReceiver::GetSilence(int desired_sample_rate_hz, AudioFrame* frame) {
current_sample_rate_hz_ = ACMCodecDB::database_[last_audio_decoder_].plfreq;
frame->num_channels_ = decoders_[last_audio_decoder_].channels;
} else {
- current_sample_rate_hz_ = kNeteqInitSampleRateHz;
frame->num_channels_ = 1;
}
@@ -785,7 +806,6 @@ bool AcmReceiver::GetSilence(int desired_sample_rate_hz, AudioFrame* frame) {
frame->samples_per_channel_ = frame->sample_rate_hz_ / 100; // Always 10 ms.
frame->speech_type_ = AudioFrame::kCNG;
frame->vad_activity_ = AudioFrame::kVadPassive;
- frame->energy_ = 0;
int samples = frame->samples_per_channel_ * frame->num_channels_;
memset(frame->data_, 0, samples * sizeof(int16_t));
return true;
@@ -815,7 +835,7 @@ uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const {
// We masked 6 most significant bits of 32-bit so there is no overflow in
// the conversion from milliseconds to timestamp.
const uint32_t now_in_ms = static_cast<uint32_t>(
- TickTime::MillisecondTimestamp() & 0x03ffffff);
+ clock_->TimeInMilliseconds() & 0x03ffffff);
return static_cast<uint32_t>(
(decoder_sampling_rate / 1000) * now_in_ms);
}
@@ -839,7 +859,7 @@ void AcmReceiver::InsertStreamOfSyncPackets(
void AcmReceiver::GetDecodingCallStatistics(
AudioDecodingCallStats* stats) const {
- CriticalSectionScoped lock(neteq_crit_sect_);
+ CriticalSectionScoped lock(crit_sect_.get());
*stats = call_stats_.GetDecodingStatistics();
}