Reland 8749: AudioEncoder: return EncodedInfo from Encode() and EncodeInternal()

Old review at:
https://webrtc-codereview.appspot.com/43839004/

R=kwiberg@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8788}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8788 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
jmarusic@webrtc.org
2015-03-19 08:50:26 +00:00
parent d21406d333
commit 9afaee74ab
22 changed files with 219 additions and 236 deletions

View File

@ -60,48 +60,48 @@ void AudioEncoderCopyRed::SetProjectedPacketLossRate(double fraction) {
speech_encoder_->SetProjectedPacketLossRate(fraction);
}
void AudioEncoderCopyRed::EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded,
EncodedInfo* info) {
speech_encoder_->Encode(rtp_timestamp, audio,
static_cast<size_t>(SampleRateHz() / 100),
max_encoded_bytes, encoded, info);
AudioEncoder::EncodedInfo AudioEncoderCopyRed::EncodeInternal(
uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) {
EncodedInfo info = speech_encoder_->Encode(
rtp_timestamp, audio, static_cast<size_t>(SampleRateHz() / 100),
max_encoded_bytes, encoded);
CHECK_GE(max_encoded_bytes,
info->encoded_bytes + secondary_info_.encoded_bytes);
CHECK(info->redundant.empty()) << "Cannot use nested redundant encoders.";
info.encoded_bytes + secondary_info_.encoded_bytes);
CHECK(info.redundant.empty()) << "Cannot use nested redundant encoders.";
if (info->encoded_bytes > 0) {
if (info.encoded_bytes > 0) {
// |info| will be implicitly cast to an EncodedInfoLeaf struct, effectively
// discarding the (empty) vector of redundant information. This is
// intentional.
info->redundant.push_back(*info);
DCHECK_EQ(info->redundant.size(), 1u);
info.redundant.push_back(info);
DCHECK_EQ(info.redundant.size(), 1u);
if (secondary_info_.encoded_bytes > 0) {
memcpy(&encoded[info->encoded_bytes], secondary_encoded_.get(),
memcpy(&encoded[info.encoded_bytes], secondary_encoded_.get(),
secondary_info_.encoded_bytes);
info->redundant.push_back(secondary_info_);
DCHECK_EQ(info->redundant.size(), 2u);
info.redundant.push_back(secondary_info_);
DCHECK_EQ(info.redundant.size(), 2u);
}
// Save primary to secondary.
if (secondary_allocated_ < info->encoded_bytes) {
secondary_encoded_.reset(new uint8_t[info->encoded_bytes]);
secondary_allocated_ = info->encoded_bytes;
if (secondary_allocated_ < info.encoded_bytes) {
secondary_encoded_.reset(new uint8_t[info.encoded_bytes]);
secondary_allocated_ = info.encoded_bytes;
}
CHECK(secondary_encoded_);
memcpy(secondary_encoded_.get(), encoded, info->encoded_bytes);
secondary_info_ = *info;
DCHECK_EQ(info->speech, info->redundant[0].speech);
memcpy(secondary_encoded_.get(), encoded, info.encoded_bytes);
secondary_info_ = info;
DCHECK_EQ(info.speech, info.redundant[0].speech);
}
// Update main EncodedInfo.
info->payload_type = red_payload_type_;
info->encoded_bytes = 0;
for (std::vector<EncodedInfoLeaf>::const_iterator it =
info->redundant.begin();
it != info->redundant.end(); ++it) {
info->encoded_bytes += it->encoded_bytes;
info.payload_type = red_payload_type_;
info.encoded_bytes = 0;
for (std::vector<EncodedInfoLeaf>::const_iterator it = info.redundant.begin();
it != info.redundant.end(); ++it) {
info.encoded_bytes += it->encoded_bytes;
}
return info;
}
} // namespace webrtc

View File

@ -45,11 +45,10 @@ class AudioEncoderCopyRed : public AudioEncoder {
void SetProjectedPacketLossRate(double fraction) override;
protected:
void EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded,
EncodedInfo* info) override;
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) override;
private:
AudioEncoder* speech_encoder_;

View File

@ -60,9 +60,8 @@ class AudioEncoderCopyRedTest : public ::testing::Test {
void Encode() {
ASSERT_TRUE(red_.get() != NULL);
encoded_info_ = AudioEncoder::EncodedInfo();
red_->Encode(timestamp_, audio_, num_audio_samples_10ms,
encoded_.size(), &encoded_[0], &encoded_info_);
encoded_info_ = red_->Encode(timestamp_, audio_, num_audio_samples_10ms,
encoded_.size(), &encoded_[0]);
timestamp_ += num_audio_samples_10ms;
}
@ -83,18 +82,16 @@ class MockEncodeHelper {
memset(&info_, 0, sizeof(info_));
}
void Encode(uint32_t timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded,
AudioEncoder::EncodedInfo* info) {
AudioEncoder::EncodedInfo Encode(uint32_t timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) {
if (write_payload_) {
CHECK(encoded);
CHECK_LE(info_.encoded_bytes, max_encoded_bytes);
memcpy(encoded, payload_, info_.encoded_bytes);
}
CHECK(info);
*info = info_;
return info_;
}
AudioEncoder::EncodedInfo info_;
@ -144,7 +141,8 @@ TEST_F(AudioEncoderCopyRedTest, CheckImmediateEncode) {
InSequence s;
MockFunction<void(int check_point_id)> check;
for (int i = 1; i <= 6; ++i) {
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _));
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillRepeatedly(Return(AudioEncoder::EncodedInfo()));
EXPECT_CALL(check, Call(i));
Encode();
check.Call(i);
@ -153,13 +151,13 @@ TEST_F(AudioEncoderCopyRedTest, CheckImmediateEncode) {
// Checks that no output is produced if the underlying codec doesn't emit any
// new data, even if the RED codec is loaded with a secondary encoding.
TEST_F(AudioEncoderCopyRedTest, CheckNoOuput) {
TEST_F(AudioEncoderCopyRedTest, CheckNoOutput) {
// Start with one Encode() call that will produce output.
static const size_t kEncodedSize = 17;
AudioEncoder::EncodedInfo info;
info.encoded_bytes = kEncodedSize;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
.WillOnce(SetArgPointee<4>(info));
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillOnce(Return(info));
Encode();
// First call is a special case, since it does not include a secondary
// payload.
@ -168,15 +166,15 @@ TEST_F(AudioEncoderCopyRedTest, CheckNoOuput) {
// Next call to the speech encoder will not produce any output.
info.encoded_bytes = 0;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
.WillOnce(SetArgPointee<4>(info));
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillOnce(Return(info));
Encode();
EXPECT_EQ(0u, encoded_info_.encoded_bytes);
// Final call to the speech encoder will produce output.
info.encoded_bytes = kEncodedSize;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
.WillOnce(SetArgPointee<4>(info));
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillOnce(Return(info));
Encode();
EXPECT_EQ(2 * kEncodedSize, encoded_info_.encoded_bytes);
ASSERT_EQ(2u, encoded_info_.redundant.size());
@ -192,8 +190,8 @@ TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes) {
for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) {
AudioEncoder::EncodedInfo info;
info.encoded_bytes = encode_size;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
.WillOnce(SetArgPointee<4>(info));
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillOnce(Return(info));
}
// First call is a special case, since it does not include a secondary
@ -218,7 +216,7 @@ TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) {
helper.info_.encoded_bytes = 17;
helper.info_.encoded_timestamp = timestamp_;
uint32_t primary_timestamp = timestamp_;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode));
// First call is a special case, since it does not include a secondary
@ -249,7 +247,7 @@ TEST_F(AudioEncoderCopyRedTest, CheckPayloads) {
payload[i] = i;
}
helper.payload_ = payload;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode));
// First call is a special case, since it does not include a secondary
@ -286,7 +284,7 @@ TEST_F(AudioEncoderCopyRedTest, CheckPayloadType) {
helper.info_.encoded_bytes = 17;
const int primary_payload_type = red_payload_type_ + 1;
helper.info_.payload_type = primary_payload_type;
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _, _))
EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
.WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode));
// First call is a special case, since it does not include a secondary