diff --git a/webrtc/modules/audio_coding/neteq/decision_logic.cc b/webrtc/modules/audio_coding/neteq/decision_logic.cc index 8cef2c96d4..545d1d6245 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic.cc +++ b/webrtc/modules/audio_coding/neteq/decision_logic.cc @@ -29,26 +29,19 @@ DecisionLogic* DecisionLogic::Create(int fs_hz, DecoderDatabase* decoder_database, const PacketBuffer& packet_buffer, DelayManager* delay_manager, - BufferLevelFilter* buffer_level_filter) { + BufferLevelFilter* buffer_level_filter, + const TickTimer* tick_timer) { switch (playout_mode) { case kPlayoutOn: case kPlayoutStreaming: - return new DecisionLogicNormal(fs_hz, - output_size_samples, - playout_mode, - decoder_database, - packet_buffer, - delay_manager, - buffer_level_filter); + return new DecisionLogicNormal( + fs_hz, output_size_samples, playout_mode, decoder_database, + packet_buffer, delay_manager, buffer_level_filter, tick_timer); case kPlayoutFax: case kPlayoutOff: - return new DecisionLogicFax(fs_hz, - output_size_samples, - playout_mode, - decoder_database, - packet_buffer, - delay_manager, - buffer_level_filter); + return new DecisionLogicFax( + fs_hz, output_size_samples, playout_mode, decoder_database, + packet_buffer, delay_manager, buffer_level_filter, tick_timer); } // This line cannot be reached, but must be here to avoid compiler errors. assert(false); @@ -61,29 +54,34 @@ DecisionLogic::DecisionLogic(int fs_hz, DecoderDatabase* decoder_database, const PacketBuffer& packet_buffer, DelayManager* delay_manager, - BufferLevelFilter* buffer_level_filter) + BufferLevelFilter* buffer_level_filter, + const TickTimer* tick_timer) : decoder_database_(decoder_database), packet_buffer_(packet_buffer), delay_manager_(delay_manager), buffer_level_filter_(buffer_level_filter), + tick_timer_(tick_timer), cng_state_(kCngOff), packet_length_samples_(0), sample_memory_(0), prev_time_scale_(false), - timescale_hold_off_(kMinTimescaleInterval), + timescale_countdown_( + tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)), num_consecutive_expands_(0), playout_mode_(playout_mode) { delay_manager_->set_streaming_mode(playout_mode_ == kPlayoutStreaming); SetSampleRate(fs_hz, output_size_samples); } +DecisionLogic::~DecisionLogic() = default; + void DecisionLogic::Reset() { cng_state_ = kCngOff; noise_fast_forward_ = 0; packet_length_samples_ = 0; sample_memory_ = 0; prev_time_scale_ = false; - timescale_hold_off_ = 0; + timescale_countdown_.reset(); num_consecutive_expands_ = 0; } @@ -91,7 +89,8 @@ void DecisionLogic::SoftReset() { packet_length_samples_ = 0; sample_memory_ = 0; prev_time_scale_ = false; - timescale_hold_off_ = kMinTimescaleInterval; + timescale_countdown_ = + tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1); } void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) { @@ -165,14 +164,13 @@ void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples, int sample_memory_local = 0; if (prev_time_scale_) { sample_memory_local = sample_memory_; - timescale_hold_off_ = kMinTimescaleInterval; + timescale_countdown_ = + tick_timer_->GetNewCountdown(kMinTimescaleInterval); } buffer_level_filter_->Update(buffer_size_packets, sample_memory_local, packet_length_samples_); prev_time_scale_ = false; } - - timescale_hold_off_ = std::max(timescale_hold_off_ - 1, 0); } } // namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq/decision_logic.h b/webrtc/modules/audio_coding/neteq/decision_logic.h index 18f424aa09..008655d1a2 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic.h +++ b/webrtc/modules/audio_coding/neteq/decision_logic.h @@ -14,6 +14,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/modules/audio_coding/neteq/defines.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" +#include "webrtc/modules/audio_coding/neteq/tick_timer.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -39,7 +40,8 @@ class DecisionLogic { DecoderDatabase* decoder_database, const PacketBuffer& packet_buffer, DelayManager* delay_manager, - BufferLevelFilter* buffer_level_filter); + BufferLevelFilter* buffer_level_filter, + const TickTimer* tick_timer); // Constructor. DecisionLogic(int fs_hz, @@ -48,10 +50,10 @@ class DecisionLogic { DecoderDatabase* decoder_database, const PacketBuffer& packet_buffer, DelayManager* delay_manager, - BufferLevelFilter* buffer_level_filter); + BufferLevelFilter* buffer_level_filter, + const TickTimer* tick_timer); - // Destructor. - virtual ~DecisionLogic() {} + virtual ~DecisionLogic(); // Resets object to a clean state. void Reset(); @@ -111,8 +113,8 @@ class DecisionLogic { NetEqPlayoutMode playout_mode() const { return playout_mode_; } protected: - // The value 6 sets maximum time-stretch rate to about 100 ms/s. - static const int kMinTimescaleInterval = 6; + // The value 5 sets maximum time-stretch rate to about 100 ms/s. + static const int kMinTimescaleInterval = 5; enum CngState { kCngOff, @@ -147,6 +149,7 @@ class DecisionLogic { const PacketBuffer& packet_buffer_; DelayManager* delay_manager_; BufferLevelFilter* buffer_level_filter_; + const TickTimer* tick_timer_; int fs_mult_; size_t output_size_samples_; CngState cng_state_; // Remember if comfort noise is interrupted by other @@ -155,7 +158,7 @@ class DecisionLogic { size_t packet_length_samples_; int sample_memory_; bool prev_time_scale_; - int timescale_hold_off_; + std::unique_ptr timescale_countdown_; int num_consecutive_expands_; const NetEqPlayoutMode playout_mode_; diff --git a/webrtc/modules/audio_coding/neteq/decision_logic_fax.h b/webrtc/modules/audio_coding/neteq/decision_logic_fax.h index fbb0cc0aee..6958f908b1 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic_fax.h +++ b/webrtc/modules/audio_coding/neteq/decision_logic_fax.h @@ -28,11 +28,16 @@ class DecisionLogicFax : public DecisionLogic { DecoderDatabase* decoder_database, const PacketBuffer& packet_buffer, DelayManager* delay_manager, - BufferLevelFilter* buffer_level_filter) - : DecisionLogic(fs_hz, output_size_samples, playout_mode, - decoder_database, packet_buffer, delay_manager, - buffer_level_filter) { - } + BufferLevelFilter* buffer_level_filter, + const TickTimer* tick_timer) + : DecisionLogic(fs_hz, + output_size_samples, + playout_mode, + decoder_database, + packet_buffer, + delay_manager, + buffer_level_filter, + tick_timer) {} protected: // Returns the operation that should be done next. |sync_buffer| and |expand| diff --git a/webrtc/modules/audio_coding/neteq/decision_logic_normal.h b/webrtc/modules/audio_coding/neteq/decision_logic_normal.h index 57aa13bf8b..aa0edf3152 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic_normal.h +++ b/webrtc/modules/audio_coding/neteq/decision_logic_normal.h @@ -28,11 +28,16 @@ class DecisionLogicNormal : public DecisionLogic { DecoderDatabase* decoder_database, const PacketBuffer& packet_buffer, DelayManager* delay_manager, - BufferLevelFilter* buffer_level_filter) - : DecisionLogic(fs_hz, output_size_samples, playout_mode, - decoder_database, packet_buffer, delay_manager, - buffer_level_filter) { - } + BufferLevelFilter* buffer_level_filter, + const TickTimer* tick_timer) + : DecisionLogic(fs_hz, + output_size_samples, + playout_mode, + decoder_database, + packet_buffer, + delay_manager, + buffer_level_filter, + tick_timer) {} protected: static const int kAllowMergeWithoutExpandMs = 20; // 20 ms. @@ -86,7 +91,9 @@ class DecisionLogicNormal : public DecisionLogic { // Checks if enough time has elapsed since the last successful timescale // operation was done (i.e., accelerate or preemptive expand). - bool TimescaleAllowed() const { return timescale_hold_off_ == 0; } + bool TimescaleAllowed() const { + return !timescale_countdown_ || timescale_countdown_->Finished(); + } // Checks if the current (filtered) buffer level is under the target level. bool UnderTargetLevel() const; diff --git a/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc b/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc index dd71953f1a..ebb366890b 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc @@ -32,28 +32,21 @@ TEST(DecisionLogic, CreateAndDestroy) { DelayPeakDetector delay_peak_detector(&tick_timer); DelayManager delay_manager(240, &delay_peak_detector, &tick_timer); BufferLevelFilter buffer_level_filter; - DecisionLogic* logic = DecisionLogic::Create(fs_hz, output_size_samples, - kPlayoutOn, &decoder_database, - packet_buffer, &delay_manager, - &buffer_level_filter); + DecisionLogic* logic = DecisionLogic::Create( + fs_hz, output_size_samples, kPlayoutOn, &decoder_database, packet_buffer, + &delay_manager, &buffer_level_filter, &tick_timer); delete logic; - logic = DecisionLogic::Create(fs_hz, output_size_samples, - kPlayoutStreaming, - &decoder_database, - packet_buffer, &delay_manager, - &buffer_level_filter); + logic = DecisionLogic::Create( + fs_hz, output_size_samples, kPlayoutStreaming, &decoder_database, + packet_buffer, &delay_manager, &buffer_level_filter, &tick_timer); delete logic; - logic = DecisionLogic::Create(fs_hz, output_size_samples, - kPlayoutFax, - &decoder_database, - packet_buffer, &delay_manager, - &buffer_level_filter); + logic = DecisionLogic::Create( + fs_hz, output_size_samples, kPlayoutFax, &decoder_database, packet_buffer, + &delay_manager, &buffer_level_filter, &tick_timer); delete logic; - logic = DecisionLogic::Create(fs_hz, output_size_samples, - kPlayoutOff, - &decoder_database, - packet_buffer, &delay_manager, - &buffer_level_filter); + logic = DecisionLogic::Create( + fs_hz, output_size_samples, kPlayoutOff, &decoder_database, packet_buffer, + &delay_manager, &buffer_level_filter, &tick_timer); delete logic; } diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 6d705e133e..555d3c71bc 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -2147,11 +2147,9 @@ NetEqImpl::OutputType NetEqImpl::LastOutputType() { } void NetEqImpl::CreateDecisionLogic() { - decision_logic_.reset(DecisionLogic::Create(fs_hz_, output_size_samples_, - playout_mode_, - decoder_database_.get(), - *packet_buffer_.get(), - delay_manager_.get(), - buffer_level_filter_.get())); + decision_logic_.reset(DecisionLogic::Create( + fs_hz_, output_size_samples_, playout_mode_, decoder_database_.get(), + *packet_buffer_.get(), delay_manager_.get(), buffer_level_filter_.get(), + tick_timer_.get())); } } // namespace webrtc