Delete ACMGenericCodec::Encode and use AudioEncoder::Encode directly
Move timestamp conversion out of ACMGenericCodec. Also remove lock
from ACMGenericCodec since the instance is always protected by
acm_crit_sect_ in AudioCodingModuleImpl.
Restructuring the code in AudioCodingModuleImpl::Encode to streamline
the use of locks.
R=minyue@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/46479004
Cr-Commit-Position: refs/heads/master@{#8773}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8773 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
index 3a6a6ef..cf407db 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -29,6 +29,7 @@
#include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"
namespace webrtc {
@@ -85,9 +86,6 @@
int red_payload_type)
: has_internal_fec_(false),
copy_red_enabled_(enable_red),
- codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()),
- last_timestamp_(0xD87F3F9F),
- unique_id_(0),
encoder_(NULL),
bitrate_bps_(0),
fec_enabled_(false),
@@ -98,12 +96,8 @@
opus_dtx_enabled_(false),
is_opus_(false),
is_isac_(false),
- first_frame_(true),
red_payload_type_(red_payload_type),
opus_application_set_(false) {
- memset(&encoder_params_, 0, sizeof(WebRtcACMCodecParams));
- encoder_params_.codec_inst.pltype = -1;
-
acm_codec_params_.codec_inst = codec_inst;
acm_codec_params_.enable_dtx = false;
acm_codec_params_.enable_vad = false;
@@ -117,7 +111,6 @@
}
ACMGenericCodec::~ACMGenericCodec() {
- delete &codec_wrapper_lock_;
}
AudioDecoderProxy::AudioDecoderProxy()
@@ -212,42 +205,13 @@
return decoder_->CngDecoderInstance();
}
-void ACMGenericCodec::Encode(uint32_t input_timestamp,
- const int16_t* audio,
- uint16_t length_per_channel,
- uint8_t audio_channel,
- uint8_t* bitstream,
- int16_t* bitstream_len_byte,
- AudioEncoder::EncodedInfo* encoded_info) {
- WriteLockScoped wl(codec_wrapper_lock_);
- CHECK_EQ(length_per_channel, encoder_->SampleRateHz() / 100);
- rtp_timestamp_ = first_frame_
- ? input_timestamp
- : last_rtp_timestamp_ +
- rtc::CheckedDivExact(
- input_timestamp - last_timestamp_,
- static_cast<uint32_t>(rtc::CheckedDivExact(
- audio_encoder_->SampleRateHz(),
- audio_encoder_->RtpTimestampRateHz())));
- last_timestamp_ = input_timestamp;
- last_rtp_timestamp_ = rtp_timestamp_;
- first_frame_ = false;
- CHECK_EQ(audio_channel, encoder_->NumChannels());
-
- encoder_->Encode(rtp_timestamp_, audio, length_per_channel,
- 2 * MAX_PAYLOAD_SIZE_BYTE, bitstream, encoded_info);
- *bitstream_len_byte = static_cast<int16_t>(encoded_info->encoded_bytes);
-}
-
int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) {
- ReadLockScoped rl(codec_wrapper_lock_);
*enc_params = acm_codec_params_;
return 0;
}
int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params,
bool force_initialization) {
- WriteLockScoped wl(codec_wrapper_lock_);
bitrate_bps_ = 0;
loss_rate_ = 0;
opus_dtx_enabled_ = false;
@@ -431,7 +395,6 @@
}
int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) {
- WriteLockScoped wl(codec_wrapper_lock_);
encoder_->SetTargetBitrate(bitrate_bps);
bitrate_bps_ = bitrate_bps;
return 0;
@@ -440,7 +403,6 @@
int16_t ACMGenericCodec::SetVAD(bool* enable_dtx,
bool* enable_vad,
ACMVADMode* mode) {
- WriteLockScoped wl(codec_wrapper_lock_);
if (is_opus_) {
*enable_dtx = false;
*enable_vad = false;
@@ -468,14 +430,12 @@
}
void ACMGenericCodec::SetCngPt(int sample_rate_hz, int payload_type) {
- WriteLockScoped wl(codec_wrapper_lock_);
SetCngPtInMap(&cng_pt_, sample_rate_hz, payload_type);
ResetAudioEncoder();
}
int32_t ACMGenericCodec::SetISACMaxPayloadSize(
const uint16_t max_payload_len_bytes) {
- WriteLockScoped wl(codec_wrapper_lock_);
if (!is_isac_)
return -1; // Needed for tests to pass.
max_payload_size_bytes_ = max_payload_len_bytes;
@@ -484,7 +444,6 @@
}
int32_t ACMGenericCodec::SetISACMaxRate(const uint32_t max_rate_bps) {
- WriteLockScoped wl(codec_wrapper_lock_);
if (!is_isac_)
return -1; // Needed for tests to pass.
max_rate_bps_ = max_rate_bps;
@@ -493,7 +452,6 @@
}
int ACMGenericCodec::SetOpusMaxPlaybackRate(int frequency_hz) {
- WriteLockScoped wl(codec_wrapper_lock_);
if (!is_opus_)
return -1; // Needed for tests to pass.
max_playback_rate_hz_ = frequency_hz;
@@ -502,12 +460,10 @@
}
AudioDecoder* ACMGenericCodec::Decoder() {
- ReadLockScoped rl(codec_wrapper_lock_);
return decoder_proxy_.IsSet() ? &decoder_proxy_ : nullptr;
}
int ACMGenericCodec::EnableOpusDtx(bool force_voip) {
- WriteLockScoped wl(codec_wrapper_lock_);
if (!is_opus_)
return -1; // Needed for tests to pass.
if (!force_voip &&
@@ -523,7 +479,6 @@
}
int ACMGenericCodec::DisableOpusDtx() {
- WriteLockScoped wl(codec_wrapper_lock_);
if (!is_opus_)
return -1; // Needed for tests to pass.
opus_dtx_enabled_ = false;
@@ -534,7 +489,6 @@
int ACMGenericCodec::SetFEC(bool enable_fec) {
if (!HasInternalFEC())
return enable_fec ? -1 : 0;
- WriteLockScoped wl(codec_wrapper_lock_);
if (fec_enabled_ != enable_fec) {
fec_enabled_ = enable_fec;
ResetAudioEncoder();
@@ -544,7 +498,6 @@
int ACMGenericCodec::SetOpusApplication(OpusApplicationMode application,
bool disable_dtx_if_needed) {
- WriteLockScoped wl(codec_wrapper_lock_);
if (opus_dtx_enabled_ && application == kAudio) {
if (disable_dtx_if_needed) {
opus_dtx_enabled_ = false;
@@ -560,21 +513,18 @@
}
int ACMGenericCodec::SetPacketLossRate(int loss_rate) {
- WriteLockScoped wl(codec_wrapper_lock_);
encoder_->SetProjectedPacketLossRate(loss_rate / 100.0);
loss_rate_ = loss_rate;
return 0;
}
void ACMGenericCodec::EnableCopyRed(bool enable, int red_payload_type) {
- WriteLockScoped wl(codec_wrapper_lock_);
copy_red_enabled_ = enable;
red_payload_type_ = red_payload_type;
ResetAudioEncoder();
}
-const AudioEncoder* ACMGenericCodec::GetAudioEncoder() const {
- WriteLockScoped wl(codec_wrapper_lock_);
+AudioEncoder* ACMGenericCodec::GetAudioEncoder() {
return encoder_;
}
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
index 8849647..93fda43 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -34,6 +34,7 @@
struct WebRtcACMCodecParams;
struct CodecInst;
+class CriticalSectionWrapper;
namespace acm2 {
@@ -96,45 +97,6 @@
ACMGenericCodec* CreateInstance();
///////////////////////////////////////////////////////////////////////////
- // int16_t Encode()
- // The function is called to perform an encoding of the audio stored in
- // audio buffer. An encoding is performed only if enough audio, i.e. equal
- // to the frame-size of the codec, exist. The audio frame will be processed
- // by VAD and CN/DTX if required. There are few different cases.
- //
- // A) Neither VAD nor DTX is active; the frame is encoded by the encoder.
- //
- // B) VAD is enabled but not DTX; in this case the audio is processed by VAD
- // and encoded by the encoder. The "*encoding_type" will be either
- // "kActiveNormalEncode" or "kPassiveNormalEncode" if frame is active or
- // passive, respectively.
- //
- // C) DTX is enabled; if the codec has internal VAD/DTX we just encode the
- // frame by the encoder. Otherwise, the frame is passed through VAD and
- // if identified as passive, then it will be processed by CN/DTX. If the
- // frame is active it will be encoded by the encoder.
- //
- // This function acquires the appropriate locks and calls EncodeSafe() for
- // the actual processing.
- //
- // Outputs:
- // -bitstream : a buffer where bit-stream will be written to.
- // -bitstream_len_byte : contains the length of the bit-stream in
- // bytes.
- // -timestamp : contains the RTP timestamp, this is the
- // sampling time of the first sample encoded
- // (measured in number of samples).
- //
- //
- void Encode(uint32_t input_timestamp,
- const int16_t* audio,
- uint16_t length_per_channel,
- uint8_t audio_channel,
- uint8_t* bitstream,
- int16_t* bitstream_len_byte,
- AudioEncoder::EncodedInfo* encoded_info);
-
- ///////////////////////////////////////////////////////////////////////////
// bool EncoderInitialized();
//
// Return value:
@@ -269,8 +231,7 @@
// -1 if failed, or if this is meaningless for the given codec.
// 0 if succeeded.
//
- int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz)
- EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
+ int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz);
///////////////////////////////////////////////////////////////////////////
// EncoderSampFreq()
@@ -284,8 +245,7 @@
// -1 if failed to output sampling rate.
// 0 if the sample rate is returned successfully.
//
- int16_t EncoderSampFreq(uint16_t* samp_freq_hz)
- SHARED_LOCKS_REQUIRED(codec_wrapper_lock_);
+ int16_t EncoderSampFreq(uint16_t* samp_freq_hz);
///////////////////////////////////////////////////////////////////////////
// SetISACMaxPayloadSize()
@@ -401,7 +361,6 @@
// false otherwise.
//
bool HasInternalFEC() const {
- ReadLockScoped rl(codec_wrapper_lock_);
return has_internal_fec_;
}
@@ -438,52 +397,38 @@
// Sets if CopyRed should be enabled.
void EnableCopyRed(bool enable, int red_payload_type);
- // This method is only for testing.
- const AudioEncoder* GetAudioEncoder() const;
+ AudioEncoder* GetAudioEncoder();
private:
- bool has_internal_fec_ GUARDED_BY(codec_wrapper_lock_);
+ bool has_internal_fec_;
- bool copy_red_enabled_ GUARDED_BY(codec_wrapper_lock_);
+ bool copy_red_enabled_;
- WebRtcACMCodecParams encoder_params_ GUARDED_BY(codec_wrapper_lock_);
-
- // Used to lock wrapper internal data
- // such as buffers and state variables.
- RWLockWrapper& codec_wrapper_lock_;
-
- uint32_t last_timestamp_ GUARDED_BY(codec_wrapper_lock_);
- uint32_t unique_id_;
-
- void ResetAudioEncoder() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
+ void ResetAudioEncoder();
OpusApplicationMode GetOpusApplication(int num_channels,
- bool enable_dtx) const
- EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
+ bool enable_dtx) const;
- rtc::scoped_ptr<AudioEncoder> audio_encoder_ GUARDED_BY(codec_wrapper_lock_);
- rtc::scoped_ptr<AudioEncoder> cng_encoder_ GUARDED_BY(codec_wrapper_lock_);
- rtc::scoped_ptr<AudioEncoder> red_encoder_ GUARDED_BY(codec_wrapper_lock_);
- AudioEncoder* encoder_ GUARDED_BY(codec_wrapper_lock_);
- AudioDecoderProxy decoder_proxy_ GUARDED_BY(codec_wrapper_lock_);
- WebRtcACMCodecParams acm_codec_params_ GUARDED_BY(codec_wrapper_lock_);
- int bitrate_bps_ GUARDED_BY(codec_wrapper_lock_);
- bool fec_enabled_ GUARDED_BY(codec_wrapper_lock_);
- int loss_rate_ GUARDED_BY(codec_wrapper_lock_);
- int max_playback_rate_hz_ GUARDED_BY(codec_wrapper_lock_);
- int max_payload_size_bytes_ GUARDED_BY(codec_wrapper_lock_);
- int max_rate_bps_ GUARDED_BY(codec_wrapper_lock_);
- bool opus_dtx_enabled_ GUARDED_BY(codec_wrapper_lock_);
- bool is_opus_ GUARDED_BY(codec_wrapper_lock_);
- bool is_isac_ GUARDED_BY(codec_wrapper_lock_);
- bool first_frame_ GUARDED_BY(codec_wrapper_lock_);
- uint32_t rtp_timestamp_ GUARDED_BY(codec_wrapper_lock_);
- uint32_t last_rtp_timestamp_ GUARDED_BY(codec_wrapper_lock_);
+ rtc::scoped_ptr<AudioEncoder> audio_encoder_;
+ rtc::scoped_ptr<AudioEncoder> cng_encoder_;
+ rtc::scoped_ptr<AudioEncoder> red_encoder_;
+ AudioEncoder* encoder_;
+ AudioDecoderProxy decoder_proxy_;
+ WebRtcACMCodecParams acm_codec_params_;
+ int bitrate_bps_;
+ bool fec_enabled_;
+ int loss_rate_;
+ int max_playback_rate_hz_;
+ int max_payload_size_bytes_;
+ int max_rate_bps_;
+ bool opus_dtx_enabled_;
+ bool is_opus_;
+ bool is_isac_;
// Map from payload type to CNG sample rate (Hz).
- std::map<int, int> cng_pt_ GUARDED_BY(codec_wrapper_lock_);
- int red_payload_type_ GUARDED_BY(codec_wrapper_lock_);
- OpusApplicationMode opus_application_ GUARDED_BY(codec_wrapper_lock_);
- bool opus_application_set_ GUARDED_BY(codec_wrapper_lock_);
+ std::map<int, int> cng_pt_;
+ int red_payload_type_;
+ OpusApplicationMode opus_application_;
+ bool opus_application_set_;
};
} // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc
index e456302..43682a0 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc
@@ -17,9 +17,10 @@
namespace {
const int kDataLengthSamples = 80;
+const int kPacketSizeSamples = 2 * kDataLengthSamples;
const int16_t kZeroData[kDataLengthSamples] = {0};
const CodecInst kDefaultCodecInst =
- {0, "pcmu", 8000, 2 * kDataLengthSamples, 1, 64000};
+ {0, "pcmu", 8000, kPacketSizeSamples, 1, 64000};
const int kCngPt = 13;
const int kNoCngPt = 255;
const int kRedPt = 255; // Not using RED in this test.
@@ -43,15 +44,13 @@
uint32_t expected_timestamp,
int expected_payload_type,
int expected_send_even_if_empty) {
- uint8_t out[kDataLengthSamples];
- int16_t out_length;
+ uint8_t out[kPacketSizeSamples];
AudioEncoder::EncodedInfo encoded_info;
- codec_->Encode(timestamp_, kZeroData, kDataLengthSamples, 1, out,
- &out_length, &encoded_info);
+ codec_->GetAudioEncoder()->Encode(timestamp_, kZeroData, kDataLengthSamples,
+ kPacketSizeSamples, out, &encoded_info);
timestamp_ += kDataLengthSamples;
EXPECT_TRUE(encoded_info.redundant.empty());
EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
- EXPECT_EQ(expected_out_length, rtc::checked_cast<size_t>(out_length));
EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp);
if (expected_payload_type >= 0)
EXPECT_EQ(expected_payload_type, encoded_info.payload_type);
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
index 718992f..aebe4e0 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -145,6 +145,7 @@
aux_rtp_header_(NULL),
receiver_initialized_(false),
first_10ms_data_(false),
+ first_frame_(true),
callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
packetization_callback_(NULL),
vad_callback_(NULL) {
@@ -218,16 +219,9 @@
}
int32_t AudioCodingModuleImpl::Encode(const InputData& input_data) {
- // Make room for 1 RED payload.
- uint8_t stream[2 * MAX_PAYLOAD_SIZE_BYTE];
- // TODO(turajs): |length_bytes| & |red_length_bytes| can be of type int if
- // ACMGenericCodec::Encode() & ACMGenericCodec::GetRedPayload() allows.
- int16_t length_bytes = 2 * MAX_PAYLOAD_SIZE_BYTE;
- FrameType frame_type = kAudioFrameSpeech;
- uint8_t current_payload_type = 0;
- bool has_data_to_send = false;
- RTPFragmentationHeader my_fragmentation;
+ uint8_t stream[2 * MAX_PAYLOAD_SIZE_BYTE]; // Make room for 1 RED payload.
AudioEncoder::EncodedInfo encoded_info;
+ uint8_t previous_pltype;
// Keep the scope of the ACM critical section limited.
{
@@ -236,52 +230,63 @@
if (!HaveValidEncoder("Process")) {
return -1;
}
- codecs_[current_send_codec_idx_]->Encode(
- input_data.input_timestamp, input_data.audio,
- input_data.length_per_channel, input_data.audio_channel, stream,
- &length_bytes, &encoded_info);
+
+ AudioEncoder* audio_encoder =
+ codecs_[current_send_codec_idx_]->GetAudioEncoder();
+ // Scale the timestamp to the codec's RTP timestamp rate.
+ uint32_t rtp_timestamp =
+ first_frame_ ? input_data.input_timestamp
+ : last_rtp_timestamp_ +
+ rtc::CheckedDivExact(
+ input_data.input_timestamp - last_timestamp_,
+ static_cast<uint32_t>(rtc::CheckedDivExact(
+ audio_encoder->SampleRateHz(),
+ audio_encoder->RtpTimestampRateHz())));
+ last_timestamp_ = input_data.input_timestamp;
+ last_rtp_timestamp_ = rtp_timestamp;
+ first_frame_ = false;
+
+ audio_encoder->Encode(rtp_timestamp, input_data.audio,
+ input_data.length_per_channel, sizeof(stream), stream,
+ &encoded_info);
if (encoded_info.encoded_bytes == 0 && !encoded_info.send_even_if_empty) {
// Not enough data.
return 0;
- } else {
- if (encoded_info.encoded_bytes == 0 && encoded_info.send_even_if_empty) {
- frame_type = kFrameEmpty;
- current_payload_type = previous_pltype_;
- } else {
- DCHECK_GT(encoded_info.encoded_bytes, 0u);
- frame_type = encoded_info.speech ? kAudioFrameSpeech : kAudioFrameCN;
- current_payload_type = encoded_info.payload_type;
- previous_pltype_ = current_payload_type;
- }
- has_data_to_send = true;
-
- ConvertEncodedInfoToFragmentationHeader(encoded_info, &my_fragmentation);
}
+ previous_pltype = previous_pltype_; // Read it while we have the critsect.
}
- if (has_data_to_send) {
- CriticalSectionScoped lock(callback_crit_sect_);
+ RTPFragmentationHeader my_fragmentation;
+ ConvertEncodedInfoToFragmentationHeader(encoded_info, &my_fragmentation);
+ FrameType frame_type;
+ if (encoded_info.encoded_bytes == 0 && encoded_info.send_even_if_empty) {
+ frame_type = kFrameEmpty;
+ encoded_info.payload_type = previous_pltype;
+ } else {
+ DCHECK_GT(encoded_info.encoded_bytes, 0u);
+ frame_type = encoded_info.speech ? kAudioFrameSpeech : kAudioFrameCN;
+ }
- if (packetization_callback_ != NULL) {
- if (my_fragmentation.fragmentationVectorSize > 0) {
- // Callback with payload data, including redundant data (RED).
- packetization_callback_->SendData(
- frame_type, current_payload_type, encoded_info.encoded_timestamp,
- stream, length_bytes, &my_fragmentation);
- } else {
- // Callback with payload data.
- packetization_callback_->SendData(frame_type, current_payload_type,
- encoded_info.encoded_timestamp,
- stream, length_bytes, NULL);
- }
+ {
+ CriticalSectionScoped lock(callback_crit_sect_);
+ if (packetization_callback_) {
+ packetization_callback_->SendData(
+ frame_type, encoded_info.payload_type, encoded_info.encoded_timestamp,
+ stream, encoded_info.encoded_bytes,
+ my_fragmentation.fragmentationVectorSize > 0 ? &my_fragmentation
+ : nullptr);
}
- if (vad_callback_ != NULL) {
+ if (vad_callback_) {
// Callback with VAD decision.
vad_callback_->InFrameType(frame_type);
}
}
- return length_bytes;
+ {
+ CriticalSectionScoped lock(acm_crit_sect_);
+ previous_pltype_ = encoded_info.payload_type;
+ }
+ return static_cast<int32_t>(encoded_info.encoded_bytes);
}
/////////////////////////////////////////
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
index 0b61752..237d0ad 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -346,6 +346,10 @@
AudioFrame preprocess_frame_ GUARDED_BY(acm_crit_sect_);
bool first_10ms_data_ GUARDED_BY(acm_crit_sect_);
+ bool first_frame_ GUARDED_BY(acm_crit_sect_);
+ uint32_t last_timestamp_ GUARDED_BY(acm_crit_sect_);
+ uint32_t last_rtp_timestamp_ GUARDED_BY(acm_crit_sect_);
+
CriticalSectionWrapper* callback_crit_sect_;
AudioPacketizationCallback* packetization_callback_
GUARDED_BY(callback_crit_sect_);
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
index 136e414..829db2d 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
@@ -44,7 +44,6 @@
const int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms;
const int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t);
const uint8_t kPayloadType = 111;
-const int kUseDefaultPacketSize = -1;
} // namespace
class RtpUtility {
@@ -84,6 +83,7 @@
: num_calls_(0),
last_frame_type_(kFrameEmpty),
last_payload_type_(-1),
+ last_timestamp_(0),
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {}
int32_t SendData(FrameType frame_type,
@@ -96,6 +96,7 @@
++num_calls_;
last_frame_type_ = frame_type;
last_payload_type_ = payload_type;
+ last_timestamp_ = timestamp;
last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
return 0;
}
@@ -120,6 +121,11 @@
return last_payload_type_;
}
+ uint32_t last_timestamp() const {
+ CriticalSectionScoped lock(crit_sect_.get());
+ return last_timestamp_;
+ }
+
void SwapBuffers(std::vector<uint8_t>* payload) {
CriticalSectionScoped lock(crit_sect_.get());
last_payload_vec_.swap(*payload);
@@ -129,6 +135,7 @@
int num_calls_ GUARDED_BY(crit_sect_);
FrameType last_frame_type_ GUARDED_BY(crit_sect_);
int last_payload_type_ GUARDED_BY(crit_sect_);
+ uint32_t last_timestamp_ GUARDED_BY(crit_sect_);
std::vector<uint8_t> last_payload_vec_ GUARDED_BY(crit_sect_);
const rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
};
@@ -138,8 +145,7 @@
AudioCodingModuleTestOldApi()
: id_(1),
rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)),
- clock_(Clock::GetRealTimeClock()),
- packet_size_samples_(kUseDefaultPacketSize) {}
+ clock_(Clock::GetRealTimeClock()) {}
~AudioCodingModuleTestOldApi() {}
@@ -160,16 +166,17 @@
input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0]));
ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_));
+
+ SetUpL16Codec();
+ }
+
+ // Set up L16 codec.
+ virtual void SetUpL16Codec() {
+ ASSERT_EQ(0, AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1));
+ codec_.pltype = kPayloadType;
}
virtual void RegisterCodec() {
- AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1);
- codec_.pltype = kPayloadType;
- if (packet_size_samples_ != kUseDefaultPacketSize) {
- codec_.pacsize = packet_size_samples_;
- }
-
- // Register L16 codec in ACM.
ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_));
ASSERT_EQ(0, acm_->RegisterSendCodec(codec_));
}
@@ -193,7 +200,6 @@
virtual void InsertAudio() {
ASSERT_GE(acm_->Add10MsData(input_frame_), 0);
- VerifyEncoding();
input_frame_.timestamp_ += kNumSamples10ms;
}
@@ -203,6 +209,11 @@
<< "Last encoded packet was " << last_length << " bytes.";
}
+ virtual void InsertAudioAndVerifyEncoding() {
+ InsertAudio();
+ VerifyEncoding();
+ }
+
const int id_;
rtc::scoped_ptr<RtpUtility> rtp_utility_;
rtc::scoped_ptr<AudioCodingModule> acm_;
@@ -211,7 +222,6 @@
AudioFrame input_frame_;
CodecInst codec_;
Clock* clock_;
- int packet_size_samples_;
};
// Check if the statistics are initialized correctly. Before any call to ACM
@@ -307,19 +317,54 @@
// Also checks that the frame type is kAudioFrameSpeech.
TEST_F(AudioCodingModuleTestOldApi, TransportCallbackIsInvokedForEachPacket) {
const int k10MsBlocksPerPacket = 3;
- packet_size_samples_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
+ codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
RegisterCodec();
const int kLoops = 10;
for (int i = 0; i < kLoops; ++i) {
EXPECT_EQ(i / k10MsBlocksPerPacket, packet_cb_.num_calls());
if (packet_cb_.num_calls() > 0)
EXPECT_EQ(kAudioFrameSpeech, packet_cb_.last_frame_type());
- InsertAudio();
+ InsertAudioAndVerifyEncoding();
}
EXPECT_EQ(kLoops / k10MsBlocksPerPacket, packet_cb_.num_calls());
EXPECT_EQ(kAudioFrameSpeech, packet_cb_.last_frame_type());
}
+// Verifies that the RTP timestamp series is not reset when the codec is
+// changed.
+TEST_F(AudioCodingModuleTestOldApi, TimestampSeriesContinuesWhenCodecChanges) {
+ RegisterCodec(); // This registers the default codec.
+ uint32_t expected_ts = input_frame_.timestamp_;
+ int blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
+ // Encode 5 packets of the first codec type.
+ const int kNumPackets1 = 5;
+ for (int j = 0; j < kNumPackets1; ++j) {
+ for (int i = 0; i < blocks_per_packet; ++i) {
+ EXPECT_EQ(j, packet_cb_.num_calls());
+ InsertAudio();
+ }
+ EXPECT_EQ(j + 1, packet_cb_.num_calls());
+ EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
+ expected_ts += codec_.pacsize;
+ }
+
+ // Change codec.
+ ASSERT_EQ(0, AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1));
+ RegisterCodec();
+ blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
+ // Encode another 5 packets.
+ const int kNumPackets2 = 5;
+ for (int j = 0; j < kNumPackets2; ++j) {
+ for (int i = 0; i < blocks_per_packet; ++i) {
+ EXPECT_EQ(kNumPackets1 + j, packet_cb_.num_calls());
+ InsertAudio();
+ }
+ EXPECT_EQ(kNumPackets1 + j + 1, packet_cb_.num_calls());
+ EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
+ expected_ts += codec_.pacsize;
+ }
+}
+
// Introduce this class to set different expectations on the number of encoded
// bytes. This class expects all encoded packets to be 9 bytes (matching one
// CNG SID frame) or 0 bytes. This test depends on |input_frame_| containing
@@ -367,7 +412,7 @@
for (int i = 0; i < kLoops; ++i) {
int num_calls_before = packet_cb_.num_calls();
EXPECT_EQ(i / blocks_per_packet, num_calls_before);
- InsertAudio();
+ InsertAudioAndVerifyEncoding();
int num_calls = packet_cb_.num_calls();
if (num_calls == num_calls_before + 1) {
EXPECT_EQ(expectation[num_calls - 1].ix, i);
@@ -389,7 +434,7 @@
TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
TransportCallbackTestForComfortNoiseRegisterCngLast) {
const int k10MsBlocksPerPacket = 3;
- packet_size_samples_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
+ codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
RegisterCodec();
const int kCngPayloadType = 105;
RegisterCngCodec(kCngPayloadType);
@@ -400,7 +445,7 @@
TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
TransportCallbackTestForComfortNoiseRegisterCngFirst) {
const int k10MsBlocksPerPacket = 3;
- packet_size_samples_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
+ codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
const int kCngPayloadType = 105;
RegisterCngCodec(kCngPayloadType);
RegisterCodec();
@@ -487,7 +532,7 @@
test_complete_->Set();
}
++send_count_;
- InsertAudio();
+ InsertAudioAndVerifyEncoding();
if (TestDone()) {
test_complete_->Set();
}
@@ -593,7 +638,6 @@
static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
codec_.pltype = kPayloadType;
- ASSERT_EQ(kUseDefaultPacketSize, packet_size_samples_);
// Register iSAC codec in ACM, effectively unregistering the PCM16B codec
// registered in AudioCodingModuleTestOldApi::SetUp();