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}
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 8862905..4a47a4d 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -16,17 +16,17 @@
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_coding/neteq/accelerate.h"
+#include "modules/audio_coding/neteq/decision_logic.h"
#include "modules/audio_coding/neteq/expand.h"
#include "modules/audio_coding/neteq/histogram.h"
#include "modules/audio_coding/neteq/include/neteq.h"
-#include "modules/audio_coding/neteq/mock/mock_buffer_level_filter.h"
#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
-#include "modules/audio_coding/neteq/mock/mock_delay_manager.h"
-#include "modules/audio_coding/neteq/mock/mock_delay_peak_detector.h"
#include "modules/audio_coding/neteq/mock/mock_dtmf_buffer.h"
#include "modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h"
+#include "modules/audio_coding/neteq/mock/mock_neteq_controller.h"
#include "modules/audio_coding/neteq/mock/mock_packet_buffer.h"
#include "modules/audio_coding/neteq/mock/mock_red_payload_splitter.h"
+#include "modules/audio_coding/neteq/neteq_controller.h"
#include "modules/audio_coding/neteq/preemptive_expand.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
#include "modules/audio_coding/neteq/sync_buffer.h"
@@ -78,13 +78,6 @@
// Get a local pointer to NetEq's TickTimer object.
tick_timer_ = deps.tick_timer.get();
- if (use_mock_buffer_level_filter_) {
- std::unique_ptr<MockBufferLevelFilter> mock(new MockBufferLevelFilter);
- mock_buffer_level_filter_ = mock.get();
- deps.buffer_level_filter = std::move(mock);
- }
- buffer_level_filter_ = deps.buffer_level_filter.get();
-
if (use_mock_decoder_database_) {
std::unique_ptr<MockDecoderDatabase> mock(new MockDecoderDatabase);
mock_decoder_database_ = mock.get();
@@ -94,26 +87,6 @@
}
decoder_database_ = deps.decoder_database.get();
- if (use_mock_delay_peak_detector_) {
- std::unique_ptr<MockDelayPeakDetector> mock(
- new MockDelayPeakDetector(tick_timer_, config_.enable_rtx_handling));
- mock_delay_peak_detector_ = mock.get();
- EXPECT_CALL(*mock_delay_peak_detector_, Reset()).Times(1);
- deps.delay_peak_detector = std::move(mock);
- }
- delay_peak_detector_ = deps.delay_peak_detector.get();
-
- if (use_mock_delay_manager_) {
- std::unique_ptr<MockDelayManager> mock(new MockDelayManager(
- config_.max_packets_in_buffer, config_.min_delay_ms, 1020054733,
- DelayManager::HistogramMode::INTER_ARRIVAL_TIME,
- config_.enable_rtx_handling, delay_peak_detector_, tick_timer_,
- deps.stats.get(), std::make_unique<Histogram>(50, 32745)));
- mock_delay_manager_ = mock.get();
- deps.delay_manager = std::move(mock);
- }
- delay_manager_ = deps.delay_manager.get();
-
if (use_mock_dtmf_buffer_) {
std::unique_ptr<MockDtmfBuffer> mock(
new MockDtmfBuffer(config_.sample_rate_hz));
@@ -137,6 +110,23 @@
}
packet_buffer_ = deps.packet_buffer.get();
+ if (use_mock_neteq_controller_) {
+ std::unique_ptr<MockNetEqController> mock(new MockNetEqController());
+ mock_neteq_controller_ = mock.get();
+ deps.neteq_controller = std::move(mock);
+ } else {
+ deps.stats = std::make_unique<StatisticsCalculator>();
+ NetEqController::Config controller_config;
+ controller_config.tick_timer = tick_timer_;
+ controller_config.base_min_delay_ms = config_.min_delay_ms;
+ controller_config.enable_rtx_handling = config_.enable_rtx_handling;
+ controller_config.allow_time_stretching = true;
+ controller_config.max_packets_in_buffer = config_.max_packets_in_buffer;
+ deps.neteq_controller =
+ std::make_unique<DecisionLogic>(std::move(controller_config));
+ }
+ neteq_controller_ = deps.neteq_controller.get();
+
if (use_mock_payload_splitter_) {
std::unique_ptr<MockRedPayloadSplitter> mock(new MockRedPayloadSplitter);
mock_payload_splitter_ = mock.get();
@@ -155,10 +145,8 @@
void UseNoMocks() {
ASSERT_TRUE(neteq_ == NULL) << "Must call UseNoMocks before CreateInstance";
- use_mock_buffer_level_filter_ = false;
use_mock_decoder_database_ = false;
- use_mock_delay_peak_detector_ = false;
- use_mock_delay_manager_ = false;
+ use_mock_neteq_controller_ = false;
use_mock_dtmf_buffer_ = false;
use_mock_dtmf_tone_generator_ = false;
use_mock_packet_buffer_ = false;
@@ -166,17 +154,11 @@
}
virtual ~NetEqImplTest() {
- if (use_mock_buffer_level_filter_) {
- EXPECT_CALL(*mock_buffer_level_filter_, Die()).Times(1);
- }
if (use_mock_decoder_database_) {
EXPECT_CALL(*mock_decoder_database_, Die()).Times(1);
}
- if (use_mock_delay_manager_) {
- EXPECT_CALL(*mock_delay_manager_, Die()).Times(1);
- }
- if (use_mock_delay_peak_detector_) {
- EXPECT_CALL(*mock_delay_peak_detector_, Die()).Times(1);
+ if (use_mock_neteq_controller_) {
+ EXPECT_CALL(*mock_neteq_controller_, Die()).Times(1);
}
if (use_mock_dtmf_buffer_) {
EXPECT_CALL(*mock_dtmf_buffer_, Die()).Times(1);
@@ -242,18 +224,12 @@
NetEq::Config config_;
SimulatedClock clock_;
TickTimer* tick_timer_ = nullptr;
- MockBufferLevelFilter* mock_buffer_level_filter_ = nullptr;
- BufferLevelFilter* buffer_level_filter_ = nullptr;
- bool use_mock_buffer_level_filter_ = true;
MockDecoderDatabase* mock_decoder_database_ = nullptr;
DecoderDatabase* decoder_database_ = nullptr;
bool use_mock_decoder_database_ = true;
- MockDelayPeakDetector* mock_delay_peak_detector_ = nullptr;
- DelayPeakDetector* delay_peak_detector_ = nullptr;
- bool use_mock_delay_peak_detector_ = true;
- MockDelayManager* mock_delay_manager_ = nullptr;
- DelayManager* delay_manager_ = nullptr;
- bool use_mock_delay_manager_ = true;
+ MockNetEqController* mock_neteq_controller_ = nullptr;
+ NetEqController* neteq_controller_ = nullptr;
+ bool use_mock_neteq_controller_ = true;
MockDtmfBuffer* mock_dtmf_buffer_ = nullptr;
DtmfBuffer* dtmf_buffer_ = nullptr;
bool use_mock_dtmf_buffer_ = true;
@@ -367,16 +343,20 @@
// All expectations within this block must be called in this specific order.
InSequence sequence; // Dummy variable.
// Expectations when the first packet is inserted.
- EXPECT_CALL(*mock_delay_manager_, last_pack_cng_or_dtmf())
- .Times(2)
- .WillRepeatedly(Return(-1));
- EXPECT_CALL(*mock_delay_manager_, set_last_pack_cng_or_dtmf(0)).Times(1);
- EXPECT_CALL(*mock_delay_manager_, ResetPacketIatCount()).Times(1);
- // Expectations when the second packet is inserted. Slightly different.
- EXPECT_CALL(*mock_delay_manager_, last_pack_cng_or_dtmf())
- .WillOnce(Return(0));
- EXPECT_CALL(*mock_delay_manager_, SetPacketAudioLength(30))
- .WillOnce(Return(0));
+ EXPECT_CALL(*mock_neteq_controller_,
+ PacketArrived(/*last_cng_or_dtmf*/ false,
+ /*packet_length_samples*/ _,
+ /*should_update_stats*/ _,
+ /*main_sequence_number*/ kFirstSequenceNumber,
+ /*main_timestamp*/ kFirstTimestamp,
+ /*fs_hz*/ 8000));
+ EXPECT_CALL(*mock_neteq_controller_,
+ PacketArrived(/*last_cng_or_dtmf*/ false,
+ /*packet_length_samples*/ _,
+ /*should_update_stats*/ _,
+ /*main_sequence_number*/ kFirstSequenceNumber + 1,
+ /*main_timestamp*/ kFirstTimestamp + 160,
+ /*fs_hz*/ 8000));
}
// Insert first packet.
@@ -1340,10 +1320,10 @@
TEST_F(NetEqImplTest, SetBaseMinimumDelay) {
UseNoMocks();
- use_mock_delay_manager_ = true;
+ use_mock_neteq_controller_ = true;
CreateInstance();
- EXPECT_CALL(*mock_delay_manager_, SetBaseMinimumDelay(_))
+ EXPECT_CALL(*mock_neteq_controller_, SetBaseMinimumDelay(_))
.WillOnce(Return(true))
.WillOnce(Return(false));
@@ -1355,12 +1335,12 @@
TEST_F(NetEqImplTest, GetBaseMinimumDelayMs) {
UseNoMocks();
- use_mock_delay_manager_ = true;
+ use_mock_neteq_controller_ = true;
CreateInstance();
const int delay_ms = 200;
- EXPECT_CALL(*mock_delay_manager_, GetBaseMinimumDelay())
+ EXPECT_CALL(*mock_neteq_controller_, GetBaseMinimumDelay())
.WillOnce(Return(delay_ms));
EXPECT_EQ(delay_ms, neteq_->GetBaseMinimumDelayMs());
@@ -1368,20 +1348,17 @@
TEST_F(NetEqImplTest, TargetDelayMs) {
UseNoMocks();
- use_mock_delay_manager_ = true;
+ use_mock_neteq_controller_ = true;
CreateInstance();
- // Let the dummy target delay be 17 packets.
- constexpr int kTargetLevelPacketsQ8 = 17 << 8;
- EXPECT_CALL(*mock_delay_manager_, TargetLevel())
- .WillOnce(Return(kTargetLevelPacketsQ8));
- // Default packet size before any packet has been decoded is 30 ms, so we are
- // expecting 17 * 30 = 510 ms target delay.
- EXPECT_EQ(17 * 30, neteq_->TargetDelayMs());
+ constexpr int kTargetLevelMs = 510;
+ EXPECT_CALL(*mock_neteq_controller_, TargetLevelMs())
+ .WillOnce(Return(kTargetLevelMs));
+ EXPECT_EQ(510, neteq_->TargetDelayMs());
}
TEST_F(NetEqImplTest, InsertEmptyPacket) {
UseNoMocks();
- use_mock_delay_manager_ = true;
+ use_mock_neteq_controller_ = true;
CreateInstance();
RTPHeader rtp_header;
@@ -1390,18 +1367,18 @@
rtp_header.timestamp = 0x12345678;
rtp_header.ssrc = 0x87654321;
- EXPECT_CALL(*mock_delay_manager_, RegisterEmptyPacket());
+ EXPECT_CALL(*mock_neteq_controller_, RegisterEmptyPacket());
neteq_->InsertEmptyPacket(rtp_header);
}
TEST_F(NetEqImplTest, EnableRtxHandling) {
UseNoMocks();
- use_mock_delay_manager_ = true;
+ use_mock_neteq_controller_ = true;
config_.enable_rtx_handling = true;
CreateInstance();
- EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
+ EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
- .WillOnce(DoAll(SetArgPointee<0>(0), SetArgPointee<1>(0)));
+ .WillOnce(Return(kNormal));
const int kPayloadLengthSamples = 80;
const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples; // PCM 16-bit.
@@ -1423,8 +1400,15 @@
// Insert second packet that was sent before the first packet.
rtp_header.sequenceNumber -= 1;
rtp_header.timestamp -= kPayloadLengthSamples;
- EXPECT_CALL(*mock_delay_manager_,
- Update(rtp_header.sequenceNumber, rtp_header.timestamp, _));
+ EXPECT_CALL(*mock_neteq_controller_,
+ PacketArrived(
+ /*last_cng_or_dtmf*/ _,
+ /*packet_length_samples*/ kPayloadLengthSamples,
+ /*should_update_stats*/ _,
+ /*main_sequence_number*/ rtp_header.sequenceNumber,
+ /*main_timestamp*/ rtp_header.timestamp,
+ /*fs_hz*/ 8000));
+
EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
}
@@ -1474,7 +1458,7 @@
void CreateInstanceWithDelayManagerMock() {
UseNoMocks();
- use_mock_delay_manager_ = true;
+ use_mock_neteq_controller_ = true;
CreateInstance(decoder_factory_);
EXPECT_TRUE(neteq_->RegisterPayloadType(
kPayloadType, SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})));
@@ -1551,16 +1535,19 @@
Register120msCodec(AudioDecoder::kSpeech);
CreateInstanceWithDelayManagerMock();
+ EXPECT_CALL(*mock_neteq_controller_, CngOff()).WillRepeatedly(Return(true));
InsertPacket(first_timestamp());
GetFirstPacket();
bool muted;
+ EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
+ .WillOnce(Return(kExpand));
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
InsertPacket(first_timestamp() + 2 * timestamp_diff_between_packets());
- // Delay manager reports a target level which should cause a Merge.
- EXPECT_CALL(*mock_delay_manager_, TargetLevel()).WillOnce(Return(-10));
+ EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
+ .WillOnce(Return(kMerge));
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kMerge, neteq_->last_operation_for_test());
@@ -1586,10 +1573,9 @@
GetFirstPacket();
InsertPacket(first_timestamp() + timestamp_diff_between_packets());
- // Delay manager report buffer limit which should cause a FastAccelerate.
- EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
+ EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
- .WillOnce(DoAll(SetArgPointee<0>(0), SetArgPointee<1>(0)));
+ .WillOnce(Return(kFastAccelerate));
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
@@ -1605,10 +1591,9 @@
InsertPacket(first_timestamp() + timestamp_diff_between_packets());
- // Delay manager report buffer limit which should cause a PreemptiveExpand.
- EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
+ EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
- .WillOnce(DoAll(SetArgPointee<0>(100), SetArgPointee<1>(100)));
+ .WillOnce(Return(kPreemptiveExpand));
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
@@ -1624,10 +1609,9 @@
InsertPacket(first_timestamp() + timestamp_diff_between_packets());
- // Delay manager report buffer limit which should cause a Accelerate.
- EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
+ EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
- .WillOnce(DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2)));
+ .WillOnce(Return(kAccelerate));
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));