Introduce injectable NetEqController interface.

This interface is implemented by the DecisionLogic class, which now contains the DelayManager and DelayPeakDetector.

Bug: webrtc:11005
Change-Id: I4fb69fa359e60831cf153e41f101d5b623749380
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/155176
Reviewed-by: Minyue Li <minyue@webrtc.org>
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29613}
This commit is contained in:
Ivo Creusen
2019-10-24 15:20:39 +02:00
committed by Commit Bot
parent 16cec3be2c
commit 53a31f7db8
17 changed files with 629 additions and 540 deletions

View File

@ -11,103 +11,108 @@
#ifndef MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
#define MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
#include "modules/audio_coding/neteq/buffer_level_filter.h"
#include "modules/audio_coding/neteq/defines.h"
#include "modules/audio_coding/neteq/delay_manager.h"
#include "modules/audio_coding/neteq/delay_peak_detector.h"
#include "modules/audio_coding/neteq/neteq_controller.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/experiments/field_trial_parser.h"
namespace webrtc {
// Forward declarations.
class BufferLevelFilter;
class DecoderDatabase;
class DelayManager;
class Expand;
class PacketBuffer;
class SyncBuffer;
struct Packet;
// This is the class for the decision tree implementation.
class DecisionLogic final {
class DecisionLogic : public NetEqController {
public:
// Static factory function which creates different types of objects depending
// on the |playout_mode|.
static DecisionLogic* Create(int fs_hz,
size_t output_size_samples,
bool disallow_time_stretching,
DecoderDatabase* decoder_database,
const PacketBuffer& packet_buffer,
DelayManager* delay_manager,
BufferLevelFilter* buffer_level_filter,
const TickTimer* tick_timer);
static const int kReinitAfterExpands = 100;
static const int kMaxWaitForPacket = 10;
// Constructor.
DecisionLogic(int fs_hz,
size_t output_size_samples,
bool disallow_time_stretching,
DecoderDatabase* decoder_database,
const PacketBuffer& packet_buffer,
DelayManager* delay_manager,
BufferLevelFilter* buffer_level_filter,
const TickTimer* tick_timer);
DecisionLogic(NetEqController::Config config);
~DecisionLogic();
~DecisionLogic() override;
// Resets object to a clean state.
void Reset();
void Reset() override;
// Resets parts of the state. Typically done when switching codecs.
void SoftReset();
void SoftReset() override;
// Sets the sample rate and the output block size.
void SetSampleRate(int fs_hz, size_t output_size_samples);
void SetSampleRate(int fs_hz, size_t output_size_samples) override;
// Returns the operation that should be done next. |sync_buffer| and |expand|
// are provided for reference. |decoder_frame_length| is the number of samples
// Given info about the latest received packet, and current jitter buffer
// status, returns the operation. |target_timestamp| and |expand_mutefactor|
// are provided for reference. |last_packet_samples| is the number of samples
// obtained from the last decoded frame. If there is a packet available, it
// should be supplied in |next_packet|; otherwise it should be NULL. The mode
// should be supplied in |packet|; otherwise it should be NULL. The mode
// resulting from the last call to NetEqImpl::GetAudio is supplied in
// |prev_mode|. If there is a DTMF event to play, |play_dtmf| should be set to
// |last_mode|. If there is a DTMF event to play, |play_dtmf| should be set to
// true. The output variable |reset_decoder| will be set to true if a reset is
// required; otherwise it is left unchanged (i.e., it can remain true if it
// was true before the call). This method end with calling
// GetDecisionSpecialized to get the actual return value.
Operations GetDecision(const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
size_t generated_noise_samples,
bool* reset_decoder);
// was true before the call).
Operations GetDecision(const NetEqStatus& status,
bool* reset_decoder) override;
// These methods test the |cng_state_| for different conditions.
bool CngRfc3389On() const { return cng_state_ == kCngRfc3389On; }
bool CngOff() const { return cng_state_ == kCngOff; }
bool CngRfc3389On() const override { return cng_state_ == kCngRfc3389On; }
bool CngOff() const override { return cng_state_ == kCngOff; }
// Resets the |cng_state_| to kCngOff.
void SetCngOff() { cng_state_ = kCngOff; }
void SetCngOff() override { cng_state_ = kCngOff; }
// Reports back to DecisionLogic whether the decision to do expand remains or
// not. Note that this is necessary, since an expand decision can be changed
// to kNormal in NetEqImpl::GetDecision if there is still enough data in the
// sync buffer.
void ExpandDecision(Operations operation);
void ExpandDecision(Operations operation) override;
// Adds |value| to |sample_memory_|.
void AddSampleMemory(int32_t value) { sample_memory_ += value; }
void AddSampleMemory(int32_t value) override { sample_memory_ += value; }
int TargetLevelMs() override {
return ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8) /
rtc::CheckedDivExact(sample_rate_, 1000);
}
absl::optional<int> PacketArrived(bool last_cng_or_dtmf,
size_t packet_length_samples,
bool should_update_stats,
uint16_t main_sequence_number,
uint32_t main_timestamp,
int fs_hz) override;
void RegisterEmptyPacket() override { delay_manager_->RegisterEmptyPacket(); }
bool SetMaximumDelay(int delay_ms) override {
return delay_manager_->SetMaximumDelay(delay_ms);
}
bool SetMinimumDelay(int delay_ms) override {
return delay_manager_->SetMinimumDelay(delay_ms);
}
bool SetBaseMinimumDelay(int delay_ms) override {
return delay_manager_->SetBaseMinimumDelay(delay_ms);
}
int GetBaseMinimumDelay() const override {
return delay_manager_->GetBaseMinimumDelay();
}
bool PeakFound() const override { return delay_manager_->PeakFound(); }
virtual int GetFilteredBufferLevel() const override {
return buffer_level_filter_.filtered_current_level();
}
// Accessors and mutators.
void set_sample_memory(int32_t value) { sample_memory_ = value; }
size_t noise_fast_forward() const { return noise_fast_forward_; }
size_t packet_length_samples() const { return packet_length_samples_; }
void set_packet_length_samples(size_t value) {
void set_sample_memory(int32_t value) override { sample_memory_ = value; }
size_t noise_fast_forward() const override { return noise_fast_forward_; }
size_t packet_length_samples() const override {
return packet_length_samples_;
}
void set_packet_length_samples(size_t value) override {
packet_length_samples_ = value;
}
void set_prev_time_scale(bool value) { prev_time_scale_ = value; }
void set_prev_time_scale(bool value) override { prev_time_scale_ = value; }
private:
// The value 5 sets maximum time-stretch rate to about 100 ms/s.
@ -140,7 +145,9 @@ class DecisionLogic final {
uint32_t target_timestamp,
uint32_t available_timestamp,
bool play_dtmf,
size_t generated_noise_samples);
size_t generated_noise_samples,
size_t span_samples_in_packet_buffer,
size_t num_packets_in_packet_buffer);
// Checks if enough time has elapsed since the last successful timescale
// operation was done (i.e., accelerate or preemptive expand).
@ -163,23 +170,22 @@ class DecisionLogic final {
// Checks if num_consecutive_expands_ >= kMaxWaitForPacket.
bool MaxWaitForPacket() const;
DecoderDatabase* decoder_database_;
const PacketBuffer& packet_buffer_;
DelayManager* delay_manager_;
BufferLevelFilter* buffer_level_filter_;
DelayPeakDetector delay_peak_detector_;
std::unique_ptr<DelayManager> delay_manager_;
BufferLevelFilter buffer_level_filter_;
const TickTimer* tick_timer_;
int sample_rate_;
size_t output_size_samples_;
CngState cng_state_; // Remember if comfort noise is interrupted by other
// event (e.g., DTMF).
CngState cng_state_ = kCngOff; // Remember if comfort noise is interrupted by
// other event (e.g., DTMF).
size_t noise_fast_forward_ = 0;
size_t packet_length_samples_;
int sample_memory_;
bool prev_time_scale_;
size_t packet_length_samples_ = 0;
int sample_memory_ = 0;
bool prev_time_scale_ = false;
bool disallow_time_stretching_;
std::unique_ptr<TickTimer::Countdown> timescale_countdown_;
int num_consecutive_expands_;
int time_stretched_cn_samples_;
int num_consecutive_expands_ = 0;
int time_stretched_cn_samples_ = 0;
FieldTrialParameter<bool> estimate_dtx_delay_;
FieldTrialParameter<bool> time_stretch_cn_;
FieldTrialConstrained<int> target_level_window_ms_;