Add speech encoder to the encoder stack specification struct
BUG=webrtc:5028 Review URL: https://codereview.webrtc.org/1527933002 Cr-Commit-Position: refs/heads/master@{#11037}
This commit is contained in:
@ -165,7 +165,8 @@ int CodecManager::RegisterEncoder(const CodecInst& send_codec) {
|
||||
AudioEncoder* enc = rent_a_codec_.RentEncoder(send_codec);
|
||||
if (!enc)
|
||||
return -1;
|
||||
rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
|
||||
codec_stack_params_.speech_encoder = enc;
|
||||
rent_a_codec_.RentEncoderStack(&codec_stack_params_);
|
||||
RTC_DCHECK(CurrentEncoder());
|
||||
}
|
||||
|
||||
@ -187,7 +188,8 @@ void CodecManager::RegisterEncoder(AudioEncoder* external_speech_encoder) {
|
||||
static const char kName[] = "external";
|
||||
memcpy(send_codec_inst_.plname, kName, sizeof(kName));
|
||||
|
||||
rent_a_codec_.RentEncoderStack(external_speech_encoder, &codec_stack_params_);
|
||||
codec_stack_params_.speech_encoder = external_speech_encoder;
|
||||
rent_a_codec_.RentEncoderStack(&codec_stack_params_);
|
||||
}
|
||||
|
||||
rtc::Optional<CodecInst> CodecManager::GetCodecInst() const {
|
||||
@ -219,8 +221,7 @@ bool CodecManager::SetCopyRed(bool enable) {
|
||||
if (codec_stack_params_.use_red != enable) {
|
||||
codec_stack_params_.use_red = enable;
|
||||
if (CurrentEncoder())
|
||||
rent_a_codec_.RentEncoderStack(rent_a_codec_.GetEncoder(),
|
||||
&codec_stack_params_);
|
||||
rent_a_codec_.RentEncoderStack(&codec_stack_params_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -232,8 +233,10 @@ int CodecManager::SetVAD(bool enable, ACMVADMode mode) {
|
||||
|
||||
// Check that the send codec is mono. We don't support VAD/DTX for stereo
|
||||
// sending.
|
||||
auto* enc = rent_a_codec_.GetEncoder();
|
||||
const bool stereo_send = enc ? (enc->NumChannels() != 1) : false;
|
||||
const bool stereo_send =
|
||||
codec_stack_params_.speech_encoder
|
||||
? (codec_stack_params_.speech_encoder->NumChannels() != 1)
|
||||
: false;
|
||||
if (enable && stereo_send) {
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
||||
"VAD/DTX not supported for stereo sending");
|
||||
@ -252,8 +255,8 @@ int CodecManager::SetVAD(bool enable, ACMVADMode mode) {
|
||||
codec_stack_params_.vad_mode != mode) {
|
||||
codec_stack_params_.use_cng = enable;
|
||||
codec_stack_params_.vad_mode = mode;
|
||||
if (enc)
|
||||
rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
|
||||
if (codec_stack_params_.speech_encoder)
|
||||
rent_a_codec_.RentEncoderStack(&codec_stack_params_);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -249,37 +249,36 @@ RentACodec::StackParameters::StackParameters() {
|
||||
|
||||
RentACodec::StackParameters::~StackParameters() = default;
|
||||
|
||||
AudioEncoder* RentACodec::RentEncoderStack(AudioEncoder* speech_encoder,
|
||||
StackParameters* param) {
|
||||
RTC_DCHECK(speech_encoder);
|
||||
AudioEncoder* RentACodec::RentEncoderStack(StackParameters* param) {
|
||||
RTC_DCHECK(param->speech_encoder);
|
||||
|
||||
if (param->use_codec_fec) {
|
||||
// Switch FEC on. On failure, remember that FEC is off.
|
||||
if (!speech_encoder->SetFec(true))
|
||||
if (!param->speech_encoder->SetFec(true))
|
||||
param->use_codec_fec = false;
|
||||
} else {
|
||||
// Switch FEC off. This shouldn't fail.
|
||||
const bool success = speech_encoder->SetFec(false);
|
||||
const bool success = param->speech_encoder->SetFec(false);
|
||||
RTC_DCHECK(success);
|
||||
}
|
||||
|
||||
auto pt = [&speech_encoder](const std::map<int, int>& m) {
|
||||
auto it = m.find(speech_encoder->SampleRateHz());
|
||||
auto pt = [¶m](const std::map<int, int>& m) {
|
||||
auto it = m.find(param->speech_encoder->SampleRateHz());
|
||||
return it == m.end() ? rtc::Optional<int>()
|
||||
: rtc::Optional<int>(it->second);
|
||||
};
|
||||
auto cng_pt = pt(param->cng_payload_types);
|
||||
param->use_cng =
|
||||
param->use_cng && cng_pt && speech_encoder->NumChannels() == 1;
|
||||
param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
|
||||
auto red_pt = pt(param->red_payload_types);
|
||||
param->use_red = param->use_red && red_pt;
|
||||
|
||||
if (param->use_cng || param->use_red) {
|
||||
// The RED and CNG encoders need to be in sync with the speech encoder, so
|
||||
// reset the latter to ensure its buffer is empty.
|
||||
speech_encoder->Reset();
|
||||
param->speech_encoder->Reset();
|
||||
}
|
||||
encoder_stack_ = speech_encoder;
|
||||
encoder_stack_ = param->speech_encoder;
|
||||
if (param->use_red) {
|
||||
red_encoder_ = CreateRedEncoder(encoder_stack_, *red_pt);
|
||||
if (red_encoder_)
|
||||
|
@ -204,6 +204,7 @@ class RentACodec {
|
||||
StackParameters();
|
||||
~StackParameters();
|
||||
|
||||
AudioEncoder* speech_encoder = nullptr;
|
||||
bool use_codec_fec = false;
|
||||
bool use_red = false;
|
||||
bool use_cng = false;
|
||||
@ -219,12 +220,10 @@ class RentACodec {
|
||||
// will be changed to match (things will be switched off). The returned
|
||||
// encoder is live until the next successful call to this function, or until
|
||||
// the Rent-A-Codec is destroyed.
|
||||
AudioEncoder* RentEncoderStack(AudioEncoder* speech_encoder,
|
||||
StackParameters* param);
|
||||
AudioEncoder* RentEncoderStack(StackParameters* param);
|
||||
|
||||
// Get the last return values of RentEncoder and RentEncoderStack, or null if
|
||||
// they haven't been called.
|
||||
AudioEncoder* GetEncoder() const { return speech_encoder_.get(); }
|
||||
// The last return value of RentEncoderStack, or null if it hasn't been
|
||||
// called.
|
||||
AudioEncoder* GetEncoderStack() const { return encoder_stack_; }
|
||||
|
||||
// Creates and returns an iSAC decoder, which will remain live until the
|
||||
|
@ -34,7 +34,8 @@ class RentACodecTestF : public ::testing::Test {
|
||||
ASSERT_TRUE(speech_encoder_);
|
||||
RentACodec::StackParameters param;
|
||||
param.use_cng = true;
|
||||
encoder_ = rent_a_codec_.RentEncoderStack(speech_encoder_, ¶m);
|
||||
param.speech_encoder = speech_encoder_;
|
||||
encoder_ = rent_a_codec_.RentEncoderStack(¶m);
|
||||
}
|
||||
|
||||
void EncodeAndVerify(size_t expected_out_length,
|
||||
@ -110,7 +111,8 @@ TEST(RentACodecTest, ExternalEncoder) {
|
||||
|
||||
RentACodec rac;
|
||||
RentACodec::StackParameters param;
|
||||
EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&external_encoder, ¶m));
|
||||
param.speech_encoder = &external_encoder;
|
||||
EXPECT_EQ(&external_encoder, rac.RentEncoderStack(¶m));
|
||||
const int kPacketSizeSamples = kSampleRateHz / 100;
|
||||
int16_t audio[kPacketSizeSamples] = {0};
|
||||
uint8_t encoded[kPacketSizeSamples];
|
||||
@ -140,16 +142,17 @@ TEST(RentACodecTest, ExternalEncoder) {
|
||||
// Change to internal encoder.
|
||||
CodecInst codec_inst = kDefaultCodecInst;
|
||||
codec_inst.pacsize = kPacketSizeSamples;
|
||||
AudioEncoder* enc = rac.RentEncoder(codec_inst);
|
||||
ASSERT_TRUE(enc);
|
||||
EXPECT_EQ(enc, rac.RentEncoderStack(enc, ¶m));
|
||||
param.speech_encoder = rac.RentEncoder(codec_inst);
|
||||
ASSERT_TRUE(param.speech_encoder);
|
||||
EXPECT_EQ(param.speech_encoder, rac.RentEncoderStack(¶m));
|
||||
|
||||
// Don't expect any more calls to the external encoder.
|
||||
info = rac.GetEncoderStack()->Encode(1, audio, arraysize(encoded), encoded);
|
||||
external_encoder.Mark("B");
|
||||
|
||||
// Change back to external encoder again.
|
||||
EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&external_encoder, ¶m));
|
||||
param.speech_encoder = &external_encoder;
|
||||
EXPECT_EQ(&external_encoder, rac.RentEncoderStack(¶m));
|
||||
info = rac.GetEncoderStack()->Encode(2, audio, arraysize(encoded), encoded);
|
||||
EXPECT_EQ(2u, info.encoded_timestamp);
|
||||
}
|
||||
@ -173,13 +176,15 @@ void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) {
|
||||
}
|
||||
|
||||
RentACodec::StackParameters param1, param2;
|
||||
param1.speech_encoder = &speech_encoder;
|
||||
param2.speech_encoder = &speech_encoder;
|
||||
param2.use_cng = use_cng;
|
||||
param2.use_red = use_red;
|
||||
speech_encoder.Mark("disabled");
|
||||
RentACodec rac;
|
||||
rac.RentEncoderStack(&speech_encoder, ¶m1);
|
||||
rac.RentEncoderStack(¶m1);
|
||||
speech_encoder.Mark("enabled");
|
||||
rac.RentEncoderStack(&speech_encoder, ¶m2);
|
||||
rac.RentEncoderStack(¶m2);
|
||||
}
|
||||
|
||||
TEST(RentACodecTest, CngResetsSpeechEncoder) {
|
||||
@ -205,5 +210,13 @@ TEST(RentACodecTest, RentEncoderError) {
|
||||
EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) {
|
||||
RentACodec::StackParameters sp;
|
||||
EXPECT_EQ(nullptr, sp.speech_encoder);
|
||||
EXPECT_DEATH(RentACodec().RentEncoderStack(&sp), "");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace acm2
|
||||
} // namespace webrtc
|
||||
|
Reference in New Issue
Block a user