Add thread annotations to AcmReceiver

This change adds thread annotations to AcmReceiver. These are the
annotations that could be added without changing acquiring the locks in
more locations, or changing the lock structure.

BUG=3401
R=kwiberg@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/17649004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6376 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2014-06-09 18:35:11 +00:00
parent 190a32fd55
commit a90abdef62
2 changed files with 43 additions and 42 deletions

View File

@ -118,16 +118,16 @@ bool IsCng(int codec_id) {
} // namespace } // namespace
AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
: id_(config.id), : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
neteq_(NetEq::Create(config.neteq_config)), id_(config.id),
last_audio_decoder_(-1), // Invalid value. last_audio_decoder_(-1), // Invalid value.
decode_lock_(RWLockWrapper::CreateRWLock()),
neteq_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
vad_enabled_(true),
previous_audio_activity_(AudioFrame::kVadPassive), previous_audio_activity_(AudioFrame::kVadPassive),
current_sample_rate_hz_(config.neteq_config.sample_rate_hz), current_sample_rate_hz_(config.neteq_config.sample_rate_hz),
nack_(), nack_(),
nack_enabled_(false), nack_enabled_(false),
neteq_(NetEq::Create(config.neteq_config)),
decode_lock_(RWLockWrapper::CreateRWLock()),
vad_enabled_(true),
clock_(config.clock), clock_(config.clock),
av_sync_(false), av_sync_(false),
initial_delay_manager_(), initial_delay_manager_(),
@ -150,7 +150,6 @@ AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
AcmReceiver::~AcmReceiver() { AcmReceiver::~AcmReceiver() {
delete neteq_; delete neteq_;
delete decode_lock_; delete decode_lock_;
delete neteq_crit_sect_;
} }
int AcmReceiver::SetMinimumDelay(int delay_ms) { int AcmReceiver::SetMinimumDelay(int delay_ms) {
@ -164,7 +163,7 @@ int AcmReceiver::SetInitialDelay(int delay_ms) {
if (delay_ms < 0 || delay_ms > 10000) { if (delay_ms < 0 || delay_ms > 10000) {
return -1; return -1;
} }
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (delay_ms == 0) { if (delay_ms == 0) {
av_sync_ = false; av_sync_ = false;
@ -208,7 +207,7 @@ int AcmReceiver::LeastRequiredDelayMs() const {
} }
int AcmReceiver::current_sample_rate_hz() const { int AcmReceiver::current_sample_rate_hz() const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
return current_sample_rate_hz_; return current_sample_rate_hz_;
} }
@ -271,7 +270,7 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
const RTPHeader* header = &rtp_header.header; // Just a shorthand. 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); int codec_id = RtpHeaderToCodecIndex(*header, incoming_payload);
if (codec_id < 0) { if (codec_id < 0) {
@ -330,7 +329,7 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
rtp_header, receive_timestamp, packet_type, new_codec, sample_rate_hz, rtp_header, receive_timestamp, packet_type, new_codec, sample_rate_hz,
missing_packets_sync_stream_.get()); missing_packets_sync_stream_.get());
} }
} } // |crit_sect_| is released.
{ {
WriteLockScoped lock_codecs(*decode_lock_); // Lock to prevent an encoding. WriteLockScoped lock_codecs(*decode_lock_); // Lock to prevent an encoding.
@ -361,7 +360,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
{ {
// Accessing members, take the lock. // Accessing members, take the lock.
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (av_sync_) { if (av_sync_) {
assert(initial_delay_manager_.get()); assert(initial_delay_manager_.get());
@ -406,7 +405,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
} }
// Accessing members, take the lock. // Accessing members, take the lock.
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
// Update NACK. // Update NACK.
int decoded_sequence_num = 0; int decoded_sequence_num = 0;
@ -501,7 +500,7 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
neteq_decoder = kDecoderOpus_2ch; neteq_decoder = kDecoderOpus_2ch;
} }
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
// The corresponding NetEq decoder ID. // The corresponding NetEq decoder ID.
// If this coder has been registered before. // If this coder has been registered before.
@ -547,13 +546,13 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id,
void AcmReceiver::EnableVad() { void AcmReceiver::EnableVad() {
neteq_->EnableVad(); neteq_->EnableVad();
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
vad_enabled_ = true; vad_enabled_ = true;
} }
void AcmReceiver::DisableVad() { void AcmReceiver::DisableVad() {
neteq_->DisableVad(); neteq_->DisableVad();
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
vad_enabled_ = false; vad_enabled_ = false;
} }
@ -565,7 +564,7 @@ void AcmReceiver::FlushBuffers() {
// many as it can. // many as it can.
int AcmReceiver::RemoveAllCodecs() { int AcmReceiver::RemoveAllCodecs() {
int ret_val = 0; int ret_val = 0;
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) { for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
if (decoders_[n].registered) { if (decoders_[n].registered) {
if (neteq_->RemovePayloadType(decoders_[n].payload_type) == 0) { if (neteq_->RemovePayloadType(decoders_[n].payload_type) == 0) {
@ -591,7 +590,7 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) {
LOG_FERR1(LS_ERROR, "AcmReceiver::RemoveCodec", payload_type); LOG_FERR1(LS_ERROR, "AcmReceiver::RemoveCodec", payload_type);
return -1; return -1;
} }
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
decoders_[codec_index].registered = false; decoders_[codec_index].registered = false;
if (last_audio_decoder_ == codec_index) if (last_audio_decoder_ == codec_index)
last_audio_decoder_ = -1; // Codec is removed, invalidate last decoder. last_audio_decoder_ = -1; // Codec is removed, invalidate last decoder.
@ -599,7 +598,7 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) {
} }
void AcmReceiver::set_id(int id) { void AcmReceiver::set_id(int id) {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
id_ = id; id_ = id;
} }
@ -614,12 +613,12 @@ bool AcmReceiver::GetPlayoutTimestamp(uint32_t* timestamp) {
} }
int AcmReceiver::last_audio_codec_id() const { int AcmReceiver::last_audio_codec_id() const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
return last_audio_decoder_; return last_audio_decoder_;
} }
int AcmReceiver::last_audio_payload_type() const { int AcmReceiver::last_audio_payload_type() const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (last_audio_decoder_ < 0) if (last_audio_decoder_ < 0)
return -1; return -1;
assert(decoders_[last_audio_decoder_].registered); assert(decoders_[last_audio_decoder_].registered);
@ -627,7 +626,7 @@ int AcmReceiver::last_audio_payload_type() const {
} }
int AcmReceiver::RedPayloadType() const { int AcmReceiver::RedPayloadType() const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (ACMCodecDB::kRED < 0 || if (ACMCodecDB::kRED < 0 ||
!decoders_[ACMCodecDB::kRED].registered) { !decoders_[ACMCodecDB::kRED].registered) {
LOG_F(LS_WARNING) << "RED is not registered."; LOG_F(LS_WARNING) << "RED is not registered.";
@ -637,7 +636,7 @@ int AcmReceiver::RedPayloadType() const {
} }
int AcmReceiver::LastAudioCodec(CodecInst* codec) const { int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (last_audio_decoder_ < 0) { if (last_audio_decoder_ < 0) {
return -1; return -1;
} }
@ -692,7 +691,7 @@ void AcmReceiver::NetworkStatistics(ACMNetworkStatistics* acm_stat) {
int AcmReceiver::DecoderByPayloadType(uint8_t payload_type, int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
CodecInst* codec) const { CodecInst* codec) const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
int codec_index = PayloadType2CodecIndex(payload_type); int codec_index = PayloadType2CodecIndex(payload_type);
if (codec_index < 0) { if (codec_index < 0) {
LOG_FERR1(LS_ERROR, "AcmReceiver::DecoderByPayloadType", payload_type); LOG_FERR1(LS_ERROR, "AcmReceiver::DecoderByPayloadType", payload_type);
@ -718,7 +717,7 @@ int AcmReceiver::EnableNack(size_t max_nack_list_size) {
if (max_nack_list_size == 0 || max_nack_list_size > Nack::kNackListSizeLimit) if (max_nack_list_size == 0 || max_nack_list_size > Nack::kNackListSizeLimit)
return -1; return -1;
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (!nack_enabled_) { if (!nack_enabled_) {
nack_.reset(Nack::Create(kNackThresholdPackets)); nack_.reset(Nack::Create(kNackThresholdPackets));
nack_enabled_ = true; nack_enabled_ = true;
@ -734,14 +733,14 @@ int AcmReceiver::EnableNack(size_t max_nack_list_size) {
} }
void AcmReceiver::DisableNack() { void AcmReceiver::DisableNack() {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
nack_.reset(); // Memory is released. nack_.reset(); // Memory is released.
nack_enabled_ = false; nack_enabled_ = false;
} }
std::vector<uint16_t> AcmReceiver::GetNackList( std::vector<uint16_t> AcmReceiver::GetNackList(
int round_trip_time_ms) const { int round_trip_time_ms) const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
if (round_trip_time_ms < 0) { if (round_trip_time_ms < 0) {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_, WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
"GetNackList: round trip time cannot be negative." "GetNackList: round trip time cannot be negative."
@ -757,7 +756,7 @@ std::vector<uint16_t> AcmReceiver::GetNackList(
void AcmReceiver::ResetInitialDelay() { void AcmReceiver::ResetInitialDelay() {
{ {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
av_sync_ = false; av_sync_ = false;
initial_delay_manager_.reset(NULL); initial_delay_manager_.reset(NULL);
missing_packets_sync_stream_.reset(NULL); missing_packets_sync_stream_.reset(NULL);
@ -860,7 +859,7 @@ void AcmReceiver::InsertStreamOfSyncPackets(
void AcmReceiver::GetDecodingCallStatistics( void AcmReceiver::GetDecodingCallStatistics(
AudioDecodingCallStats* stats) const { AudioDecodingCallStats* stats) const {
CriticalSectionScoped lock(neteq_crit_sect_); CriticalSectionScoped lock(crit_sect_.get());
*stats = call_stats_.GetDecodingStatistics(); *stats = call_stats_.GetDecodingStatistics();
} }

View File

@ -23,6 +23,7 @@
#include "webrtc/modules/audio_coding/neteq/interface/neteq.h" #include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
#include "webrtc/modules/interface/module_common_types.h" #include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/thread_annotations.h"
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
namespace webrtc { namespace webrtc {
@ -327,7 +328,8 @@ class AcmReceiver {
private: private:
int PayloadType2CodecIndex(uint8_t payload_type) const; int PayloadType2CodecIndex(uint8_t payload_type) const;
bool GetSilence(int desired_sample_rate_hz, AudioFrame* frame); bool GetSilence(int desired_sample_rate_hz, AudioFrame* frame)
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
int GetNumSyncPacketToInsert(uint16_t received_squence_number); int GetNumSyncPacketToInsert(uint16_t received_squence_number);
@ -338,21 +340,23 @@ class AcmReceiver {
void InsertStreamOfSyncPackets(InitialDelayManager::SyncStream* sync_stream); void InsertStreamOfSyncPackets(InitialDelayManager::SyncStream* sync_stream);
int id_; scoped_ptr<CriticalSectionWrapper> crit_sect_;
int id_; // TODO(henrik.lundin) Make const.
int last_audio_decoder_ GUARDED_BY(crit_sect_);
AudioFrame::VADActivity previous_audio_activity_ GUARDED_BY(crit_sect_);
int current_sample_rate_hz_ GUARDED_BY(crit_sect_);
ACMResampler resampler_ GUARDED_BY(crit_sect_);
// Used in GetAudio, declared as member to avoid allocating every 10ms.
// TODO(henrik.lundin) Stack-allocate in GetAudio instead?
int16_t audio_buffer_[AudioFrame::kMaxDataSizeSamples] GUARDED_BY(crit_sect_);
scoped_ptr<Nack> nack_ GUARDED_BY(crit_sect_);
bool nack_enabled_ GUARDED_BY(crit_sect_);
CallStatistics call_stats_ GUARDED_BY(crit_sect_);
NetEq* neteq_; NetEq* neteq_;
Decoder decoders_[ACMCodecDB::kMaxNumCodecs]; Decoder decoders_[ACMCodecDB::kMaxNumCodecs];
int last_audio_decoder_;
RWLockWrapper* decode_lock_; RWLockWrapper* decode_lock_;
CriticalSectionWrapper* neteq_crit_sect_;
bool vad_enabled_; bool vad_enabled_;
AudioFrame::VADActivity previous_audio_activity_; Clock* clock_; // TODO(henrik.lundin) Make const if possible.
int current_sample_rate_hz_;
ACMResampler resampler_;
// Used in GetAudio, declared as member to avoid allocating every 10ms.
int16_t audio_buffer_[AudioFrame::kMaxDataSizeSamples];
scoped_ptr<Nack> nack_;
bool nack_enabled_;
Clock* clock_;
// Indicates if a non-zero initial delay is set, and the receiver is in // Indicates if a non-zero initial delay is set, and the receiver is in
// AV-sync mode. // AV-sync mode.
@ -366,8 +370,6 @@ class AcmReceiver {
// initial delay is set. // initial delay is set.
scoped_ptr<InitialDelayManager::SyncStream> missing_packets_sync_stream_; scoped_ptr<InitialDelayManager::SyncStream> missing_packets_sync_stream_;
scoped_ptr<InitialDelayManager::SyncStream> late_packets_sync_stream_; scoped_ptr<InitialDelayManager::SyncStream> late_packets_sync_stream_;
CallStatistics call_stats_;
}; };
} // namespace acm2 } // namespace acm2