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:
@ -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_;
|
||||
|
||||
Reference in New Issue
Block a user