Setting Opus target application.
This CL is to allow to set Opus target application at the creation of an encoder. According to Opus spec, there are three applications: OPUS_APPLICATION_VOIP OPUS_APPLICATION_AUDIO OPUS_APPLICATION_RESTRICTED_LOWDELAY BUG= R=henrik.lundin@webrtc.org, tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/37479004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@8103 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -999,6 +999,12 @@ int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ACMGenericCodec::SetOpusApplication(OpusApplicationMode /*application*/) {
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
|
||||
"The send-codec is not Opus, failed to set application.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) {
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
|
||||
"The send-codec is not Opus, failed to set maximum playback rate.");
|
||||
|
||||
@ -525,6 +525,20 @@ class ACMGenericCodec {
|
||||
uint8_t* payload,
|
||||
int16_t* payload_len_bytes);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// int SetOpusApplication()
|
||||
// Sets the intended application for the Opus encoder. Opus uses this to
|
||||
// optimize the encoding for applications like VOIP and music.
|
||||
//
|
||||
// Input:
|
||||
// - application : intended application.
|
||||
//
|
||||
// Return value:
|
||||
// -1 if failed or on codecs other than Opus.
|
||||
// 0 if succeeded.
|
||||
//
|
||||
virtual int SetOpusApplication(OpusApplicationMode /*application*/);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// int SetOpusMaxPlaybackRate()
|
||||
// Sets maximum playback rate the receiver will render, if the codec is Opus.
|
||||
@ -636,8 +650,8 @@ class ACMGenericCodec {
|
||||
// See InitEncoder() for the description of function, input(s)/output(s)
|
||||
// and return value.
|
||||
//
|
||||
int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
|
||||
bool force_initialization)
|
||||
virtual int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
|
||||
bool force_initialization)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -68,7 +68,8 @@ ACMOpus::ACMOpus(int16_t codec_id)
|
||||
sample_freq_(32000), // Default sampling frequency.
|
||||
bitrate_(20000), // Default bit-rate.
|
||||
channels_(1), // Default mono.
|
||||
packet_loss_rate_(0) { // Initial packet loss rate.
|
||||
packet_loss_rate_(0), // Initial packet loss rate.
|
||||
application_(kVoip) { // Initial application mode.
|
||||
codec_id_ = codec_id;
|
||||
// Opus has internal DTX, but we dont use it for now.
|
||||
has_internal_dtx_ = false;
|
||||
@ -113,6 +114,16 @@ int16_t ACMOpus::InternalEncode(uint8_t* bitstream,
|
||||
return *bitstream_len_byte;
|
||||
}
|
||||
|
||||
int16_t ACMOpus::InitEncoderSafe(WebRtcACMCodecParams* codec_params,
|
||||
bool force_initialization) {
|
||||
// Determine target application if codec is not initialized or a forced
|
||||
// initialization is requested.
|
||||
if (!encoder_initialized_ || force_initialization) {
|
||||
application_ = (codec_params->codec_inst.channels == 1) ? kVoip : kAudio;
|
||||
}
|
||||
return ACMGenericCodec::InitEncoderSafe(codec_params, force_initialization);
|
||||
}
|
||||
|
||||
int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
|
||||
int16_t ret;
|
||||
if (encoder_inst_ptr_ != NULL) {
|
||||
@ -120,7 +131,8 @@ int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
|
||||
encoder_inst_ptr_ = NULL;
|
||||
}
|
||||
ret = WebRtcOpus_EncoderCreate(&encoder_inst_ptr_,
|
||||
codec_params->codec_inst.channels);
|
||||
codec_params->codec_inst.channels,
|
||||
application_);
|
||||
// Store number of channels.
|
||||
channels_ = codec_params->codec_inst.channels;
|
||||
|
||||
@ -251,6 +263,13 @@ int ACMOpus::SetOpusMaxPlaybackRate(int frequency_hz) {
|
||||
return WebRtcOpus_SetMaxPlaybackRate(encoder_inst_ptr_, frequency_hz);
|
||||
}
|
||||
|
||||
int ACMOpus::SetOpusApplication(OpusApplicationMode application) {
|
||||
WriteLockScoped lockCodec(codec_wrapper_lock_);
|
||||
application_ = application;
|
||||
// Set Opus application invokes a reset of the encoder.
|
||||
return InternalResetEncoder();
|
||||
}
|
||||
|
||||
#endif // WEBRTC_CODEC_OPUS
|
||||
|
||||
} // namespace acm2
|
||||
|
||||
@ -29,23 +29,29 @@ class ACMOpus : public ACMGenericCodec {
|
||||
ACMGenericCodec* CreateInstance(void);
|
||||
|
||||
int16_t InternalEncode(uint8_t* bitstream,
|
||||
int16_t* bitstream_len_byte) OVERRIDE
|
||||
int16_t* bitstream_len_byte) override
|
||||
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
|
||||
|
||||
int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
|
||||
bool force_initialization) override
|
||||
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
|
||||
|
||||
int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
|
||||
|
||||
virtual int SetFEC(bool enable_fec) OVERRIDE;
|
||||
int SetFEC(bool enable_fec) override;
|
||||
|
||||
virtual int SetPacketLossRate(int loss_rate) OVERRIDE;
|
||||
int SetOpusApplication(OpusApplicationMode mode) override;
|
||||
|
||||
virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE;
|
||||
int SetPacketLossRate(int loss_rate) override;
|
||||
|
||||
int SetOpusMaxPlaybackRate(int frequency_hz) override;
|
||||
|
||||
protected:
|
||||
void DestructEncoderSafe();
|
||||
|
||||
int16_t InternalCreateEncoder();
|
||||
|
||||
int16_t SetBitRateSafe(const int32_t rate) OVERRIDE
|
||||
int16_t SetBitRateSafe(const int32_t rate) override
|
||||
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
|
||||
|
||||
WebRtcOpusEncInst* encoder_inst_ptr_;
|
||||
@ -54,6 +60,8 @@ class ACMOpus : public ACMGenericCodec {
|
||||
int channels_;
|
||||
|
||||
int packet_loss_rate_;
|
||||
|
||||
OpusApplicationMode application_;
|
||||
};
|
||||
|
||||
} // namespace acm2
|
||||
|
||||
@ -35,6 +35,11 @@ class AcmOpusTest : public ACMOpus {
|
||||
: ACMOpus(codec_id) {}
|
||||
~AcmOpusTest() {}
|
||||
int packet_loss_rate() { return packet_loss_rate_; }
|
||||
OpusApplicationMode application() { return application_; }
|
||||
bool encoder_initialized() {
|
||||
ReadLockScoped cs(codec_wrapper_lock_);
|
||||
return encoder_initialized_;
|
||||
}
|
||||
|
||||
void TestSetPacketLossRate(int from, int to, int expected_return);
|
||||
};
|
||||
@ -82,6 +87,54 @@ TEST(AcmOpusTest, PacketLossRateOptimized) {
|
||||
kPacketLossRate1);
|
||||
opus.TestSetPacketLossRate(0, 0, 0);
|
||||
}
|
||||
|
||||
TEST(AcmOpusTest, DefaultApplicationMode) {
|
||||
AcmOpusTest opus(ACMCodecDB::kOpus);
|
||||
WebRtcACMCodecParams params;
|
||||
memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
|
||||
|
||||
params.codec_inst.channels = 2;
|
||||
// Codec is not initialized, and hence without force initialization (2nd
|
||||
// argument being false), an initialization will take place.
|
||||
EXPECT_FALSE(opus.encoder_initialized());
|
||||
EXPECT_EQ(0, opus.InitEncoder(¶ms, false));
|
||||
EXPECT_EQ(kAudio, opus.application());
|
||||
|
||||
params.codec_inst.channels = 1;
|
||||
EXPECT_EQ(0, opus.InitEncoder(¶ms, true));
|
||||
EXPECT_EQ(kVoip, opus.application());
|
||||
}
|
||||
|
||||
TEST(AcmOpusTest, ChangeApplicationMode) {
|
||||
AcmOpusTest opus(ACMCodecDB::kOpus);
|
||||
WebRtcACMCodecParams params;
|
||||
memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
|
||||
|
||||
params.codec_inst.channels = 2;
|
||||
// Codec is not initialized, and hence without force initialization (2nd
|
||||
// argument being false), an initialization will take place.
|
||||
EXPECT_EQ(0, opus.InitEncoder(¶ms, false));
|
||||
EXPECT_EQ(kAudio, opus.application());
|
||||
|
||||
opus.SetOpusApplication(kVoip);
|
||||
EXPECT_EQ(kVoip, opus.application());
|
||||
}
|
||||
|
||||
TEST(AcmOpusTest, ResetWontChangeApplicationMode) {
|
||||
AcmOpusTest opus(ACMCodecDB::kOpus);
|
||||
WebRtcACMCodecParams params;
|
||||
memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
|
||||
|
||||
params.codec_inst.channels = 2;
|
||||
// Codec is not initialized, and hence without force initialization (2nd
|
||||
// argument being false), an initialization will take place.
|
||||
EXPECT_EQ(0, opus.InitEncoder(¶ms, false));
|
||||
EXPECT_EQ(kAudio, opus.application());
|
||||
|
||||
opus.ResetEncoder();
|
||||
EXPECT_EQ(kAudio, opus.application());
|
||||
}
|
||||
|
||||
#else
|
||||
void AcmOpusTest:TestSetPacketLossRate(int /* from */, int /* to */,
|
||||
int /* expected_return */) {
|
||||
|
||||
@ -54,6 +54,8 @@ class AcmSendTestOldApi : public AudioPacketizationCallback,
|
||||
size_t payload_len_bytes,
|
||||
const RTPFragmentationHeader* fragmentation) OVERRIDE;
|
||||
|
||||
AudioCodingModule* acm() { return acm_.get(); }
|
||||
|
||||
private:
|
||||
static const int kBlockSizeMs = 10;
|
||||
|
||||
|
||||
@ -1544,6 +1544,14 @@ int AudioCodingModuleImpl::ConfigISACBandwidthEstimator(
|
||||
frame_size_ms, rate_bit_per_sec, enforce_frame_size);
|
||||
}
|
||||
|
||||
int AudioCodingModuleImpl::SetOpusApplication(OpusApplicationMode application) {
|
||||
CriticalSectionScoped lock(acm_crit_sect_);
|
||||
if (!HaveValidEncoder("SetOpusApplication")) {
|
||||
return -1;
|
||||
}
|
||||
return codecs_[current_send_codec_idx_]->SetOpusApplication(application);
|
||||
}
|
||||
|
||||
// Informs Opus encoder of the maximum playback rate the receiver will render.
|
||||
int AudioCodingModuleImpl::SetOpusMaxPlaybackRate(int frequency_hz) {
|
||||
CriticalSectionScoped lock(acm_crit_sect_);
|
||||
|
||||
@ -224,6 +224,8 @@ class AudioCodingModuleImpl : public AudioCodingModule {
|
||||
int rate_bit_per_sec,
|
||||
bool enforce_frame_size = false) OVERRIDE;
|
||||
|
||||
int SetOpusApplication(OpusApplicationMode application) override;
|
||||
|
||||
// If current send codec is Opus, informs it about the maximum playback rate
|
||||
// the receiver will render.
|
||||
virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE;
|
||||
|
||||
@ -977,6 +977,22 @@ TEST_F(AcmSenderBitExactnessOldApi, MAYBE_Opus_stereo_20ms) {
|
||||
test::AcmReceiveTestOldApi::kStereoOutput);
|
||||
}
|
||||
|
||||
TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms_voip) {
|
||||
ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
|
||||
// If not set, default will be kAudio in case of stereo.
|
||||
send_test_->acm()->SetOpusApplication(kVoip);
|
||||
Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
|
||||
"9b9e12bc3cc793740966e11cbfa8b35b",
|
||||
"57412a4b5771d19ff03ec35deffe7067",
|
||||
"9b9e12bc3cc793740966e11cbfa8b35b"),
|
||||
AcmReceiverBitExactnessOldApi::PlatformChecksum(
|
||||
"c7340b1189652ab6b5e80dade7390cb4",
|
||||
"cdfe85939c411d12b61701c566e22d26",
|
||||
"c7340b1189652ab6b5e80dade7390cb4"),
|
||||
50,
|
||||
test::AcmReceiveTestOldApi::kStereoOutput);
|
||||
}
|
||||
|
||||
// This test fixture is implemented to run ACM and change the desired output
|
||||
// frequency during the call. The input packets are simply PCM16b-wb encoded
|
||||
// payloads with a constant value of |kSampleValue|. The test fixture itself
|
||||
|
||||
@ -874,6 +874,20 @@ class AudioCodingModule: public Module {
|
||||
int init_rate_bps,
|
||||
bool enforce_frame_size = false) = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// int SetOpusApplication()
|
||||
// Sets the intended application for the Opus encoder. Opus uses this to
|
||||
// optimize the encoding for applications like VOIP and music.
|
||||
//
|
||||
// Input:
|
||||
// - application : intended application.
|
||||
//
|
||||
// Return value:
|
||||
// -1 if failed or on codecs other than Opus.
|
||||
// 0 if succeeded.
|
||||
//
|
||||
virtual int SetOpusApplication(OpusApplicationMode /*application*/) = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// int SetOpusMaxPlaybackRate()
|
||||
// If current send codec is Opus, informs it about maximum playback rate the
|
||||
|
||||
@ -200,6 +200,18 @@ enum ACMBackgroundNoiseMode {
|
||||
Off
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Enumeration of Opus mode for intended application.
|
||||
//
|
||||
// kVoip : optimized for voice signals.
|
||||
// kAudio : optimized for non-voice signals like music.
|
||||
//
|
||||
enum OpusApplicationMode {
|
||||
kVoip = 0,
|
||||
kAudio = 1,
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_INTERFACE_AUDIO_CODING_MODULE_TYPEDEFS_H_
|
||||
|
||||
@ -79,8 +79,8 @@ void OpusTest::Perform() {
|
||||
in_file_mono_.ReadStereo(false);
|
||||
|
||||
// Create Opus encoders for mono and stereo.
|
||||
ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1), -1);
|
||||
ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2), -1);
|
||||
ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1, 0), -1);
|
||||
ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2, 1), -1);
|
||||
|
||||
// Create Opus decoders for mono and stereo for stand-alone testing of Opus.
|
||||
ASSERT_GT(WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1), -1);
|
||||
|
||||
Reference in New Issue
Block a user