Chromium Code Reviews| Index: webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc | 
| diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc | 
| index d03f2d3cc2440c3d5fa029e91c4dd037fcf54c96..f5c7413dd25ff51beac786b0fb45d66fd67cf7d6 100644 | 
| --- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc | 
| +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc | 
| @@ -12,10 +12,14 @@ | 
| #include <algorithm> | 
| +#include "webrtc/base/arraysize.h" | 
| #include "webrtc/base/checks.h" | 
| #include "webrtc/base/safe_conversions.h" | 
| #include "webrtc/common_types.h" | 
| +#include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h" | 
| +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h" | 
| #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" | 
| +#include "webrtc/system_wrappers/include/clock.h" | 
| namespace webrtc { | 
| @@ -24,6 +28,7 @@ namespace { | 
| const int kSampleRateHz = 48000; | 
| const int kMinBitrateBps = 500; | 
| const int kMaxBitrateBps = 512000; | 
| +constexpr int kSupportedFrameLengths[] = {20, 60}; | 
| AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { | 
| AudioEncoderOpus::Config config; | 
| @@ -104,13 +109,17 @@ int AudioEncoderOpus::Config::GetBitrateBps() const { | 
| return num_channels == 1 ? 32000 : 64000; // Default value. | 
| } | 
| -AudioEncoderOpus::AudioEncoderOpus(const Config& config) | 
| - : packet_loss_rate_(0.0), inst_(nullptr) { | 
| +AudioEncoderOpus::AudioEncoderOpus( | 
| + const Config& config, | 
| + std::unique_ptr<AudioNetworkAdaptor> audio_network_adaptor) | 
| + : packet_loss_rate_(0.0), | 
| + inst_(nullptr), | 
| + audio_network_adaptor_(std::move(audio_network_adaptor)) { | 
| 
 
kwiberg-webrtc
2016/10/03 12:48:10
You still take the ANA as an argument in the const
 
minyue-webrtc
2016/10/03 12:57:15
This ctor is only used for integration test. I thi
 
 | 
| RTC_CHECK(RecreateEncoderInstance(config)); | 
| } | 
| AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) | 
| - : AudioEncoderOpus(CreateConfig(codec_inst)) {} | 
| + : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {} | 
| AudioEncoderOpus::~AudioEncoderOpus() { | 
| RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); | 
| @@ -141,15 +150,23 @@ void AudioEncoderOpus::Reset() { | 
| } | 
| bool AudioEncoderOpus::SetFec(bool enable) { | 
| - auto conf = config_; | 
| - conf.fec_enabled = enable; | 
| - return RecreateEncoderInstance(conf); | 
| + if (enable) { | 
| + RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_)); | 
| + } else { | 
| + RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_)); | 
| + } | 
| + config_.fec_enabled = enable; | 
| + return true; | 
| } | 
| bool AudioEncoderOpus::SetDtx(bool enable) { | 
| - auto conf = config_; | 
| - conf.dtx_enabled = enable; | 
| - return RecreateEncoderInstance(conf); | 
| + if (enable) { | 
| + RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); | 
| + } else { | 
| + RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); | 
| + } | 
| + config_.dtx_enabled = enable; | 
| + return true; | 
| } | 
| bool AudioEncoderOpus::GetDtx() const { | 
| @@ -192,6 +209,65 @@ void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { | 
| RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps())); | 
| } | 
| +bool AudioEncoderOpus::EnableAudioNetworkAdaptor( | 
| + const std::string& config_string, | 
| + const Clock* clock) { | 
| + AudioNetworkAdaptorImpl::Config config; | 
| + config.clock = clock; | 
| + audio_network_adaptor_.reset(new AudioNetworkAdaptorImpl( | 
| + config, ControllerManagerImpl::Create( | 
| + config_string, NumChannels(), | 
| + rtc::ArrayView<const int>(kSupportedFrameLengths, | 
| + arraysize(kSupportedFrameLengths)), | 
| 
 
kwiberg-webrtc
2016/10/03 12:48:10
1. Use the constructor that takes only an array ar
 
minyue-webrtc
2016/10/03 12:57:15
sure, will do.
 
 | 
| + num_channels_to_encode_, next_frame_length_ms_, | 
| + GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock))); | 
| + return audio_network_adaptor_.get(); | 
| +} | 
| + | 
| +void AudioEncoderOpus::DisableAudioNetworkAdaptor() { | 
| + audio_network_adaptor_.reset(nullptr); | 
| +} | 
| + | 
| +void AudioEncoderOpus::OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) { | 
| + if (!audio_network_adaptor_) | 
| + return; | 
| + audio_network_adaptor_->SetUplinkBandwidth(uplink_bandwidth_bps); | 
| + ApplyAudioNetworkAdaptor(); | 
| +} | 
| + | 
| +void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction( | 
| + float uplink_packet_loss_fraction) { | 
| + if (!audio_network_adaptor_) | 
| + return; | 
| + audio_network_adaptor_->SetUplinkPacketLossFraction( | 
| + uplink_packet_loss_fraction); | 
| + ApplyAudioNetworkAdaptor(); | 
| +} | 
| + | 
| +void AudioEncoderOpus::OnReceivedTargetAudioBitrate( | 
| + int target_audio_bitrate_bps) { | 
| + if (!audio_network_adaptor_) | 
| + return; | 
| + audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps); | 
| + ApplyAudioNetworkAdaptor(); | 
| +} | 
| + | 
| +void AudioEncoderOpus::OnReceivedRtt(int rtt_ms) { | 
| + if (!audio_network_adaptor_) | 
| + return; | 
| + audio_network_adaptor_->SetRtt(rtt_ms); | 
| + ApplyAudioNetworkAdaptor(); | 
| +} | 
| + | 
| +void AudioEncoderOpus::SetReceiverFrameLengthRange(int min_frame_length_ms, | 
| + int max_frame_length_ms) { | 
| + if (!audio_network_adaptor_) | 
| + return; | 
| + audio_network_adaptor_->SetReceiverFrameLengthRange(min_frame_length_ms, | 
| + max_frame_length_ms); | 
| + ApplyAudioNetworkAdaptor(); | 
| +} | 
| + | 
| AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( | 
| uint32_t rtp_timestamp, | 
| rtc::ArrayView<const int16_t> audio, | 
| @@ -226,6 +302,9 @@ AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( | 
| }); | 
| input_buffer_.clear(); | 
| + // Will use new packet size for next encoding. | 
| + config_.frame_size_ms = next_frame_length_ms_; | 
| + | 
| info.encoded_timestamp = first_timestamp_in_buffer_; | 
| info.payload_type = config_.payload_type; | 
| info.send_even_if_empty = true; // Allows Opus to send empty packets. | 
| @@ -282,7 +361,46 @@ bool AudioEncoderOpus::RecreateEncoderInstance(const Config& config) { | 
| WebRtcOpus_SetPacketLossRate( | 
| inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); | 
| config_ = config; | 
| + | 
| + num_channels_to_encode_ = NumChannels(); | 
| + next_frame_length_ms_ = config_.frame_size_ms; | 
| return true; | 
| } | 
| +void AudioEncoderOpus::SetFrameLength(int frame_length_ms) { | 
| + next_frame_length_ms_ = frame_length_ms; | 
| +} | 
| + | 
| +void AudioEncoderOpus::SetNumChannelsToEncode(size_t num_channels_to_encode) { | 
| + RTC_DCHECK_GT(num_channels_to_encode, 0u); | 
| + RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels); | 
| + | 
| + if (num_channels_to_encode_ == num_channels_to_encode) | 
| + return; | 
| + | 
| + RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode)); | 
| + num_channels_to_encode_ = num_channels_to_encode; | 
| +} | 
| + | 
| +void AudioEncoderOpus::ApplyAudioNetworkAdaptor() { | 
| + auto config = audio_network_adaptor_->GetEncoderRuntimeConfig(); | 
| + // |audio_network_adaptor_| is supposed to be configured to output all | 
| + // following parameters. | 
| + RTC_DCHECK(config.bitrate_bps); | 
| + RTC_DCHECK(config.frame_length_ms); | 
| + RTC_DCHECK(config.uplink_packet_loss_fraction); | 
| + RTC_DCHECK(config.enable_fec); | 
| + RTC_DCHECK(config.enable_dtx); | 
| + RTC_DCHECK(config.num_channels); | 
| + | 
| + RTC_DCHECK(*config.frame_length_ms == 20 || *config.frame_length_ms == 60); | 
| + | 
| + SetTargetBitrate(*config.bitrate_bps); | 
| + SetFrameLength(*config.frame_length_ms); | 
| + SetFec(*config.enable_fec); | 
| + SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction); | 
| + SetDtx(*config.enable_dtx); | 
| + SetNumChannelsToEncode(*config.num_channels); | 
| +} | 
| + | 
| } // namespace webrtc |