Eliminate AcmGenericCodec::Add10MsData
All encoding work is now done in the Encode function. Note: This CL leaves a technical debt in AudioCodingModuleImpl::Add10MsData. This will be fixed in later changes. COAUTHOR=kwiberg@webrtc.org R=jmarusic@webrtc.org Review URL: https://webrtc-codereview.appspot.com/46419004 Cr-Commit-Position: refs/heads/master@{#8594} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8594 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
f82109cb4d
commit
61c22aca5f
@ -230,19 +230,32 @@ CNG_dec_inst* AudioDecoderProxy::CngDecoderInstance() {
|
||||
return decoder_->CngDecoderInstance();
|
||||
}
|
||||
|
||||
int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
|
||||
int16_t 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,
|
||||
uint32_t* timestamp,
|
||||
WebRtcACMEncodingType* encoding_type,
|
||||
AudioEncoder::EncodedInfo* encoded_info) {
|
||||
WriteLockScoped wl(codec_wrapper_lock_);
|
||||
CHECK(!input_.empty());
|
||||
encoder_->Encode(rtp_timestamp_, &input_[0],
|
||||
input_.size() / encoder_->NumChannels(),
|
||||
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);
|
||||
input_.clear();
|
||||
*bitstream_len_byte = static_cast<int16_t>(encoded_info->encoded_bytes);
|
||||
*timestamp = encoded_info->encoded_timestamp;
|
||||
if (encoded_info->encoded_bytes == 0) {
|
||||
*encoding_type = kNoEncoding;
|
||||
if (encoded_info->send_even_if_empty) {
|
||||
@ -466,32 +479,6 @@ OpusApplicationMode ACMGenericCodec::GetOpusApplication(
|
||||
return num_channels == 1 || enable_dtx ? kVoip : kAudio;
|
||||
}
|
||||
|
||||
int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp,
|
||||
const int16_t* data,
|
||||
const uint16_t length_per_channel,
|
||||
const uint8_t audio_channel) {
|
||||
WriteLockScoped wl(codec_wrapper_lock_);
|
||||
CHECK(input_.empty());
|
||||
CHECK_EQ(length_per_channel, encoder_->SampleRateHz() / 100);
|
||||
for (int i = 0; i < length_per_channel * encoder_->NumChannels(); ++i) {
|
||||
input_.push_back(data[i]);
|
||||
}
|
||||
rtp_timestamp_ = first_frame_
|
||||
? timestamp
|
||||
: last_rtp_timestamp_ +
|
||||
rtc::CheckedDivExact(
|
||||
timestamp - last_timestamp_,
|
||||
static_cast<uint32_t>(rtc::CheckedDivExact(
|
||||
audio_encoder_->SampleRateHz(),
|
||||
audio_encoder_->RtpTimestampRateHz())));
|
||||
last_timestamp_ = timestamp;
|
||||
last_rtp_timestamp_ = rtp_timestamp_;
|
||||
first_frame_ = false;
|
||||
|
||||
CHECK_EQ(audio_channel, encoder_->NumChannels());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) {
|
||||
WriteLockScoped wl(codec_wrapper_lock_);
|
||||
encoder_->SetTargetBitrate(bitrate_bps);
|
||||
|
@ -146,9 +146,12 @@ class ACMGenericCodec {
|
||||
// -1 if error is occurred, otherwise the length of the bit-stream in
|
||||
// bytes.
|
||||
//
|
||||
int16_t Encode(uint8_t* bitstream,
|
||||
int16_t 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,
|
||||
uint32_t* timestamp,
|
||||
WebRtcACMEncodingType* encoding_type,
|
||||
AudioEncoder::EncodedInfo* encoded_info);
|
||||
|
||||
@ -196,30 +199,6 @@ class ACMGenericCodec {
|
||||
int16_t InitEncoder(WebRtcACMCodecParams* codec_params,
|
||||
bool force_initialization);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// int32_t Add10MsData(...)
|
||||
// This function is called to add 10 ms of audio to the audio buffer of
|
||||
// the codec.
|
||||
//
|
||||
// Inputs:
|
||||
// -timestamp : the timestamp of the 10 ms audio. the timestamp
|
||||
// is the sampling time of the
|
||||
// first sample measured in number of samples.
|
||||
// -data : a buffer that contains the audio. The codec
|
||||
// expects to get the audio in correct sampling
|
||||
// frequency
|
||||
// -length : the length of the audio buffer
|
||||
// -audio_channel : 0 for mono, 1 for stereo (not supported yet)
|
||||
//
|
||||
// Return values:
|
||||
// -1 if failed
|
||||
// 0 otherwise.
|
||||
//
|
||||
int32_t Add10MsData(const uint32_t timestamp,
|
||||
const int16_t* data,
|
||||
const uint16_t length,
|
||||
const uint8_t audio_channel);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// uint32_t NoMissedSamples()
|
||||
// This function returns the number of samples which are overwritten in
|
||||
@ -495,7 +474,6 @@ class ACMGenericCodec {
|
||||
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_);
|
||||
std::vector<int16_t> input_ 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_);
|
||||
|
@ -39,12 +39,6 @@ class AcmGenericCodecTest : public ::testing::Test {
|
||||
ASSERT_EQ(0, codec_->InitEncoder(&acm_codec_params_, true));
|
||||
}
|
||||
|
||||
void AddData() {
|
||||
EXPECT_EQ(
|
||||
0, codec_->Add10MsData(timestamp_, kZeroData, kDataLengthSamples, 1));
|
||||
timestamp_ += kDataLengthSamples;
|
||||
}
|
||||
|
||||
void EncodeAndVerify(int expected_return_val,
|
||||
size_t expected_out_length,
|
||||
uint32_t expected_timestamp,
|
||||
@ -53,13 +47,12 @@ class AcmGenericCodecTest : public ::testing::Test {
|
||||
int expected_send_even_if_empty) {
|
||||
uint8_t out[kDataLengthSamples];
|
||||
int16_t out_length;
|
||||
uint32_t out_timestamp;
|
||||
WebRtcACMEncodingType encoding_type;
|
||||
AudioEncoder::EncodedInfo encoded_info;
|
||||
EXPECT_EQ(expected_return_val,
|
||||
codec_->Encode(out, &out_length, &out_timestamp, &encoding_type,
|
||||
&encoded_info));
|
||||
EXPECT_EQ(expected_timestamp, out_timestamp);
|
||||
codec_->Encode(timestamp_, kZeroData, kDataLengthSamples, 1, out,
|
||||
&out_length,&encoding_type, &encoded_info));
|
||||
timestamp_ += kDataLengthSamples;
|
||||
EXPECT_EQ(expected_encoding_type, encoding_type);
|
||||
EXPECT_TRUE(encoded_info.redundant.empty());
|
||||
EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
|
||||
@ -89,28 +82,24 @@ TEST_F(AcmGenericCodecTest, VerifyCngFrames) {
|
||||
CreateCodec();
|
||||
uint32_t expected_timestamp = timestamp_;
|
||||
// Verify no frame.
|
||||
AddData();
|
||||
{
|
||||
SCOPED_TRACE("First encoding");
|
||||
EncodeAndVerify(0, 0, expected_timestamp, kNoEncoding, -1, -1);
|
||||
}
|
||||
|
||||
// Verify SID frame delivered.
|
||||
AddData();
|
||||
{
|
||||
SCOPED_TRACE("Second encoding");
|
||||
EncodeAndVerify(9, 9, expected_timestamp, kPassiveDTXNB, kCngPt, 1);
|
||||
}
|
||||
|
||||
// Verify no frame.
|
||||
AddData();
|
||||
{
|
||||
SCOPED_TRACE("Third encoding");
|
||||
EncodeAndVerify(0, 0, expected_timestamp, kNoEncoding, -1, -1);
|
||||
}
|
||||
|
||||
// Verify NoEncoding.
|
||||
AddData();
|
||||
expected_timestamp += 2 * kDataLengthSamples;
|
||||
{
|
||||
SCOPED_TRACE("Fourth encoding");
|
||||
|
@ -217,19 +217,19 @@ AudioCodingModuleImpl::~AudioCodingModuleImpl() {
|
||||
"Destroyed");
|
||||
}
|
||||
|
||||
int32_t AudioCodingModuleImpl::Encode() {
|
||||
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;
|
||||
uint32_t rtp_timestamp;
|
||||
int status;
|
||||
WebRtcACMEncodingType encoding_type;
|
||||
FrameType frame_type = kAudioFrameSpeech;
|
||||
uint8_t current_payload_type = 0;
|
||||
bool has_data_to_send = false;
|
||||
RTPFragmentationHeader my_fragmentation;
|
||||
AudioEncoder::EncodedInfo encoded_info;
|
||||
|
||||
// Keep the scope of the ACM critical section limited.
|
||||
{
|
||||
@ -238,9 +238,10 @@ int32_t AudioCodingModuleImpl::Encode() {
|
||||
if (!HaveValidEncoder("Process")) {
|
||||
return -1;
|
||||
}
|
||||
AudioEncoder::EncodedInfo encoded_info;
|
||||
status = codecs_[current_send_codec_idx_]->Encode(
|
||||
stream, &length_bytes, &rtp_timestamp, &encoding_type, &encoded_info);
|
||||
input_data.input_timestamp, input_data.audio,
|
||||
input_data.length_per_channel, input_data.audio_channel, stream,
|
||||
&length_bytes, &encoding_type, &encoded_info);
|
||||
if (status < 0) {
|
||||
// Encode failed.
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
||||
@ -294,14 +295,14 @@ int32_t AudioCodingModuleImpl::Encode() {
|
||||
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,
|
||||
rtp_timestamp, stream, length_bytes,
|
||||
&my_fragmentation);
|
||||
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,
|
||||
rtp_timestamp, stream, length_bytes,
|
||||
NULL);
|
||||
encoded_info.encoded_timestamp,
|
||||
stream, length_bytes, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -745,11 +746,13 @@ int AudioCodingModuleImpl::RegisterTransportCallback(
|
||||
|
||||
// Add 10MS of raw (PCM) audio data to the encoder.
|
||||
int AudioCodingModuleImpl::Add10MsData(const AudioFrame& audio_frame) {
|
||||
int r = Add10MsDataInternal(audio_frame);
|
||||
return r < 0 ? r : Encode();
|
||||
InputData input_data;
|
||||
int r = Add10MsDataInternal(audio_frame, &input_data);
|
||||
return r < 0 ? r : Encode(input_data);
|
||||
}
|
||||
|
||||
int AudioCodingModuleImpl::Add10MsDataInternal(const AudioFrame& audio_frame) {
|
||||
int AudioCodingModuleImpl::Add10MsDataInternal(const AudioFrame& audio_frame,
|
||||
InputData* input_data) {
|
||||
if (audio_frame.samples_per_channel_ <= 0) {
|
||||
assert(false);
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
||||
@ -798,15 +801,12 @@ int AudioCodingModuleImpl::Add10MsDataInternal(const AudioFrame& audio_frame) {
|
||||
// Check whether we need an up-mix or down-mix?
|
||||
bool remix = ptr_frame->num_channels_ != send_codec_inst_.channels;
|
||||
|
||||
// If a re-mix is required (up or down), this buffer will store re-mixed
|
||||
// version of the input.
|
||||
int16_t buffer[WEBRTC_10MS_PCM_AUDIO];
|
||||
if (remix) {
|
||||
if (ptr_frame->num_channels_ == 1) {
|
||||
if (UpMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, buffer) < 0)
|
||||
if (UpMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, input_data->buffer) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
if (DownMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, buffer) < 0)
|
||||
if (DownMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, input_data->buffer) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -817,12 +817,12 @@ int AudioCodingModuleImpl::Add10MsDataInternal(const AudioFrame& audio_frame) {
|
||||
|
||||
// For pushing data to primary, point the |ptr_audio| to correct buffer.
|
||||
if (send_codec_inst_.channels != ptr_frame->num_channels_)
|
||||
ptr_audio = buffer;
|
||||
ptr_audio = input_data->buffer;
|
||||
|
||||
if (codecs_[current_send_codec_idx_]->Add10MsData(
|
||||
ptr_frame->timestamp_, ptr_audio, ptr_frame->samples_per_channel_,
|
||||
send_codec_inst_.channels) < 0)
|
||||
return -1;
|
||||
input_data->input_timestamp = ptr_frame->timestamp_;
|
||||
input_data->audio = ptr_audio;
|
||||
input_data->length_per_channel = ptr_frame->samples_per_channel_;
|
||||
input_data->audio_channel = send_codec_inst_.channels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1565,9 +1565,10 @@ const CodecInst* AudioCodingImpl::GetSenderCodecInst() {
|
||||
}
|
||||
|
||||
int AudioCodingImpl::Add10MsAudio(const AudioFrame& audio_frame) {
|
||||
if (acm_old_->Add10MsDataInternal(audio_frame) != 0)
|
||||
acm2::AudioCodingModuleImpl::InputData input_data;
|
||||
if (acm_old_->Add10MsDataInternal(audio_frame, &input_data) != 0)
|
||||
return -1;
|
||||
return acm_old_->Encode();
|
||||
return acm_old_->Encode(input_data);
|
||||
}
|
||||
|
||||
const ReceiverInfo* AudioCodingImpl::GetReceiverInfo() const {
|
||||
|
@ -240,8 +240,18 @@ class AudioCodingModuleImpl : public AudioCodingModule {
|
||||
AudioDecodingCallStats* stats) const OVERRIDE;
|
||||
|
||||
private:
|
||||
int Add10MsDataInternal(const AudioFrame& audio_frame);
|
||||
int Encode();
|
||||
struct InputData {
|
||||
uint32_t input_timestamp;
|
||||
const int16_t* audio;
|
||||
uint16_t length_per_channel;
|
||||
uint8_t audio_channel;
|
||||
// If a re-mix is required (up or down), this buffer will store a re-mixed
|
||||
// version of the input.
|
||||
int16_t buffer[WEBRTC_10MS_PCM_AUDIO];
|
||||
};
|
||||
|
||||
int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data);
|
||||
int Encode(const InputData& input_data);
|
||||
|
||||
ACMGenericCodec* CreateCodec(const CodecInst& codec);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user