Add NetEq config flag that enables RTX handling.

When enabled, the delay manager is updated with reordered packets. It also makes the peak detector ignore the reordered packets.

Change-Id: I2bdc99764cc76b15e613ed3dc75f83aaf66eee4e
Bug: webrtc:10178
Reviewed-on: https://webrtc-review.googlesource.com/c/116481
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26187}
This commit is contained in:
Jakob Ivarsson
2019-01-10 10:28:23 +01:00
committed by Commit Bot
parent d8bd75079b
commit 39b934ba2e
14 changed files with 135 additions and 47 deletions

View File

@ -30,7 +30,7 @@ TEST(DecisionLogic, CreateAndDestroy) {
new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
TickTimer tick_timer;
PacketBuffer packet_buffer(10, &tick_timer);
DelayPeakDetector delay_peak_detector(&tick_timer);
DelayPeakDetector delay_peak_detector(&tick_timer, false);
DelayManager delay_manager(240, 0, &delay_peak_detector, &tick_timer);
BufferLevelFilter buffer_level_filter;
DecisionLogic* logic = DecisionLogic::Create(
@ -47,7 +47,7 @@ TEST(DecisionLogic, PostponeDecodingAfterExpansionSettings) {
new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
TickTimer tick_timer;
PacketBuffer packet_buffer(10, &tick_timer);
DelayPeakDetector delay_peak_detector(&tick_timer);
DelayPeakDetector delay_peak_detector(&tick_timer, false);
DelayManager delay_manager(240, 0, &delay_peak_detector, &tick_timer);
BufferLevelFilter buffer_level_filter;
{

View File

@ -158,6 +158,7 @@ int DelayManager::Update(uint16_t sequence_number,
}
// Check for discontinuous packet sequence and re-ordering.
bool reordered = false;
if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
// Compensate for gap in the sequence numbers. Reduce IAT with the
// expected extra time due to lost packets, but ensure that the IAT is
@ -166,6 +167,7 @@ int DelayManager::Update(uint16_t sequence_number,
iat_packets = std::max(iat_packets, 0);
} else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
iat_packets += static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
reordered = true;
}
// Saturate IAT at maximum value.
@ -173,7 +175,7 @@ int DelayManager::Update(uint16_t sequence_number,
iat_packets = std::min(iat_packets, max_iat);
UpdateHistogram(iat_packets);
// Calculate new |target_level_| based on updated statistics.
target_level_ = CalculateTargetLevel(iat_packets);
target_level_ = CalculateTargetLevel(iat_packets, reordered);
if (streaming_mode_) {
target_level_ = std::max(target_level_, max_iat_cumulative_sum_);
}
@ -294,7 +296,7 @@ void DelayManager::LimitTargetLevel() {
target_level_ = std::max(target_level_, 1 << 8);
}
int DelayManager::CalculateTargetLevel(int iat_packets) {
int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) {
int limit_probability = forced_limit_probability_.value_or(kLimitProbability);
if (streaming_mode_) {
limit_probability = kLimitProbabilityStreaming;
@ -325,7 +327,8 @@ int DelayManager::CalculateTargetLevel(int iat_packets) {
base_target_level_ = static_cast<int>(index);
// Update detector for delay peaks.
bool delay_peak_found = peak_detector_.Update(iat_packets, target_level);
bool delay_peak_found =
peak_detector_.Update(iat_packets, reordered, target_level);
if (delay_peak_found) {
target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
}

View File

@ -57,7 +57,7 @@ class DelayManager {
// Sets target_level_ (in Q8) and returns the same value. Also calculates
// and updates base_target_level_, which is the target buffer level before
// taking delay peaks into account.
virtual int CalculateTargetLevel(int iat_packets);
virtual int CalculateTargetLevel(int iat_packets, bool reordered);
// Notifies the DelayManager of how much audio data is carried in each packet.
// The method updates the DelayPeakDetector too, and resets the inter-arrival

View File

@ -49,7 +49,10 @@ class DelayManagerTest : public ::testing::Test {
};
DelayManagerTest::DelayManagerTest()
: dm_(nullptr), detector_(&tick_timer_), seq_no_(0x1234), ts_(0x12345678) {}
: dm_(nullptr),
detector_(&tick_timer_, false),
seq_no_(0x1234),
ts_(0x12345678) {}
void DelayManagerTest::SetUp() {
RecreateDelayManager();
@ -126,7 +129,7 @@ TEST_F(DelayManagerTest, UpdateNormal) {
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet, and (base) target level equal to 1 as well.
// Return false to indicate no peaks found.
EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
InsertNextPacket();
EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8.
EXPECT_EQ(1, dm_->base_target_level());
@ -149,7 +152,7 @@ TEST_F(DelayManagerTest, UpdateLongInterArrivalTime) {
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet, and (base) target level equal to 1 as well.
// Return false to indicate no peaks found.
EXPECT_CALL(detector_, Update(2, 2)).WillOnce(Return(false));
EXPECT_CALL(detector_, Update(2, false, 2)).WillOnce(Return(false));
InsertNextPacket();
EXPECT_EQ(2 << 8, dm_->TargetLevel()); // In Q8.
EXPECT_EQ(2, dm_->base_target_level());
@ -172,7 +175,7 @@ TEST_F(DelayManagerTest, UpdatePeakFound) {
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet, and (base) target level equal to 1 as well.
// Return true to indicate that peaks are found. Let the peak height be 5.
EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(true));
EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(true));
EXPECT_CALL(detector_, MaxPeakHeight()).WillOnce(Return(5));
InsertNextPacket();
EXPECT_EQ(5 << 8, dm_->TargetLevel());
@ -194,7 +197,7 @@ TEST_F(DelayManagerTest, TargetDelay) {
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet, and (base) target level equal to 1 as well.
// Return false to indicate no peaks found.
EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
InsertNextPacket();
const int kExpectedTarget = 1;
EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); // In Q8.
@ -216,7 +219,7 @@ TEST_F(DelayManagerTest, MaxDelay) {
// Second packet arrival.
// Expect detector update method to be called once with inter-arrival time
// equal to |kExpectedTarget| packet. Return true to indicate peaks found.
EXPECT_CALL(detector_, Update(kExpectedTarget, _))
EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(detector_, MaxPeakHeight())
.WillRepeatedly(Return(kExpectedTarget));
@ -246,7 +249,7 @@ TEST_F(DelayManagerTest, MinDelay) {
// Second packet arrival.
// Expect detector update method to be called once with inter-arrival time
// equal to |kExpectedTarget| packet. Return true to indicate peaks found.
EXPECT_CALL(detector_, Update(kExpectedTarget, _))
EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
.WillRepeatedly(Return(true));
EXPECT_CALL(detector_, MaxPeakHeight())
.WillRepeatedly(Return(kExpectedTarget));
@ -264,6 +267,15 @@ TEST_F(DelayManagerTest, MinDelay) {
EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel());
}
TEST_F(DelayManagerTest, UpdateReorderedPacket) {
SetPacketAudioLength(kFrameSizeMs);
InsertNextPacket();
// Insert packet that was sent before the previous packet.
EXPECT_CALL(detector_, Update(_, true, _));
EXPECT_EQ(0, dm_->Update(seq_no_ - 1, ts_ - kFrameSizeMs, kFs));
}
// Tests that skipped sequence numbers (simulating empty packets) are handled
// correctly.
TEST_F(DelayManagerTest, EmptyPacketsReported) {
@ -285,7 +297,7 @@ TEST_F(DelayManagerTest, EmptyPacketsReported) {
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet, and (base) target level equal to 1 as well.
// Return false to indicate no peaks found.
EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
InsertNextPacket();
EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8.
@ -309,7 +321,7 @@ TEST_F(DelayManagerTest, EmptyPacketsNotReported) {
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet, and (base) target level equal to 1 as well.
// Return false to indicate no peaks found.
EXPECT_CALL(detector_, Update(10, 10)).WillOnce(Return(false));
EXPECT_CALL(detector_, Update(10, false, 10)).WillOnce(Return(false));
InsertNextPacket();
// Note 10 times higher target value.
@ -348,7 +360,7 @@ TEST_F(DelayManagerTest, TargetDelayGreaterThanOne) {
// Second packet arrival.
// Expect detector update method to be called once with inter-arrival time
// equal to 1 packet.
EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
InsertNextPacket();
constexpr int kExpectedTarget = 1;
EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); // In Q8.

View File

@ -26,10 +26,12 @@ namespace webrtc {
DelayPeakDetector::~DelayPeakDetector() = default;
DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer)
DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer,
bool ignore_reordered_packets)
: peak_found_(false),
peak_detection_threshold_(0),
tick_timer_(tick_timer),
ignore_reordered_packets_(ignore_reordered_packets),
frame_length_change_experiment_(
field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")) {
RTC_DCHECK(!peak_period_stopwatch_);
@ -79,7 +81,12 @@ uint64_t DelayPeakDetector::MaxPeakPeriod() const {
return max_period_element->period_ms;
}
bool DelayPeakDetector::Update(int inter_arrival_time, int target_level) {
bool DelayPeakDetector::Update(int inter_arrival_time,
bool reordered,
int target_level) {
if (ignore_reordered_packets_ && reordered) {
return CheckPeakConditions();
}
if (inter_arrival_time > target_level + peak_detection_threshold_ ||
inter_arrival_time > 2 * target_level) {
// A delay peak is observed.

View File

@ -23,7 +23,7 @@ namespace webrtc {
class DelayPeakDetector {
public:
DelayPeakDetector(const TickTimer* tick_timer);
DelayPeakDetector(const TickTimer* tick_timer, bool ignore_reordered_packets);
virtual ~DelayPeakDetector();
virtual void Reset();
@ -43,10 +43,11 @@ class DelayPeakDetector {
// larger than 0), or 0 if no delay peaks have been observed recently.
virtual uint64_t MaxPeakPeriod() const;
// Updates the DelayPeakDetector with a new inter-arrival time (in packets)
// and the current target buffer level (needed to decide if a peak is observed
// or not). Returns true if peak-mode is active, false if not.
virtual bool Update(int inter_arrival_time, int target_level);
// Updates the DelayPeakDetector with a new inter-arrival time (in packets),
// the current target buffer level (needed to decide if a peak is observed or
// not) and if the new inter-arrival time includes a compensation for
// reordering. Returns true if peak-mode is active, false if not.
virtual bool Update(int inter_arrival_time, bool reordered, int target_level);
private:
static const size_t kMaxNumPeaks = 8;
@ -66,6 +67,7 @@ class DelayPeakDetector {
int peak_detection_threshold_;
const TickTimer* tick_timer_;
std::unique_ptr<TickTimer::Stopwatch> peak_period_stopwatch_;
const bool ignore_reordered_packets_;
const bool frame_length_change_experiment_;
RTC_DISALLOW_COPY_AND_ASSIGN(DelayPeakDetector);

View File

@ -18,14 +18,14 @@ namespace webrtc {
TEST(DelayPeakDetector, CreateAndDestroy) {
TickTimer tick_timer;
DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer);
DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer, false);
EXPECT_FALSE(detector->peak_found());
delete detector;
}
TEST(DelayPeakDetector, EmptyHistory) {
TickTimer tick_timer;
DelayPeakDetector detector(&tick_timer);
DelayPeakDetector detector(&tick_timer, false);
EXPECT_EQ(-1, detector.MaxPeakHeight());
EXPECT_EQ(0u, detector.MaxPeakPeriod());
}
@ -35,7 +35,7 @@ TEST(DelayPeakDetector, EmptyHistory) {
// start. This should then continue until it is disengaged due to lack of peaks.
TEST(DelayPeakDetector, TriggerPeakMode) {
TickTimer tick_timer;
DelayPeakDetector detector(&tick_timer);
DelayPeakDetector detector(&tick_timer, false);
const int kPacketSizeMs = 30;
detector.SetPacketAudioLength(kPacketSizeMs);
@ -69,9 +69,9 @@ TEST(DelayPeakDetector, TriggerPeakMode) {
(arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
const int kTargetBufferLevel = 1; // Define peaks to be iat > 2.
if (time < peak_mode_start_ms || time > peak_mode_end_ms) {
EXPECT_FALSE(detector.Update(iat_packets, kTargetBufferLevel));
EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
} else {
EXPECT_TRUE(detector.Update(iat_packets, kTargetBufferLevel));
EXPECT_TRUE(detector.Update(iat_packets, false, kTargetBufferLevel));
EXPECT_EQ(kWorstPeakPeriod, detector.MaxPeakPeriod());
EXPECT_EQ(kPeakDelayMs / kPacketSizeMs + 1, detector.MaxPeakHeight());
}
@ -87,7 +87,7 @@ TEST(DelayPeakDetector, TriggerPeakMode) {
// The delay pattern has peaks with delay = 3, thus should not trigger.
TEST(DelayPeakDetector, DoNotTriggerPeakMode) {
TickTimer tick_timer;
DelayPeakDetector detector(&tick_timer);
DelayPeakDetector detector(&tick_timer, false);
const int kPacketSizeMs = 30;
detector.SetPacketAudioLength(kPacketSizeMs);
@ -115,7 +115,7 @@ TEST(DelayPeakDetector, DoNotTriggerPeakMode) {
int iat_packets =
(arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
const int kTargetBufferLevel = 2; // Define peaks to be iat > 4.
EXPECT_FALSE(detector.Update(iat_packets, kTargetBufferLevel));
EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
++next;
}
tick_timer.Increment();
@ -129,15 +129,33 @@ TEST(DelayPeakDetector, DoNotTriggerPeakMode) {
// problems.
TEST(DelayPeakDetector, ZeroDistancePeaks) {
TickTimer tick_timer;
DelayPeakDetector detector(&tick_timer);
DelayPeakDetector detector(&tick_timer, false);
const int kPacketSizeMs = 30;
detector.SetPacketAudioLength(kPacketSizeMs);
const int kTargetBufferLevel = 2; // Define peaks to be iat > 4.
const int kInterArrivalTime = 3 * kTargetBufferLevel; // Will trigger a peak.
EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
const int kInterArrivalTime =
3 * kTargetBufferLevel; // Above peak threshold.
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
tick_timer.Increment();
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
// The following would fail if there were non-zero time between the updates.
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
}
TEST(DelayPeakDetector, IgnoreReorderedPacket) {
TickTimer tick_timer;
DelayPeakDetector detector(&tick_timer, true);
const int kTargetBufferLevel = 2; // Define peaks to be iat > 4.
const int kInterArrivalTime =
3 * kTargetBufferLevel; // Above peak threshold.
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
tick_timer.Increment();
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
tick_timer.Increment();
// The following would fail if the packet was not reordered.
EXPECT_FALSE(detector.Update(kInterArrivalTime, true, kTargetBufferLevel));
}
} // namespace webrtc

View File

@ -117,6 +117,7 @@ class NetEq {
int min_delay_ms = 0;
bool enable_fast_accelerate = false;
bool enable_muted_state = false;
bool enable_rtx_handling = false;
absl::optional<AudioCodecPairId> codec_pair_id;
bool for_test_no_time_stretching = false; // Use only for testing.
};

View File

@ -34,7 +34,7 @@ class MockDelayManager : public DelayManager {
int(uint16_t sequence_number,
uint32_t timestamp,
int sample_rate_hz));
MOCK_METHOD1(CalculateTargetLevel, int(int iat_packets));
MOCK_METHOD2(CalculateTargetLevel, int(int iat_packets, bool reordered));
MOCK_METHOD1(SetPacketAudioLength, int(int length_ms));
MOCK_METHOD0(Reset, void());
MOCK_CONST_METHOD0(PeakFound, bool());

View File

@ -19,8 +19,9 @@ namespace webrtc {
class MockDelayPeakDetector : public DelayPeakDetector {
public:
MockDelayPeakDetector(const TickTimer* tick_timer)
: DelayPeakDetector(tick_timer) {}
MockDelayPeakDetector(const TickTimer* tick_timer,
bool ignore_reordered_packets)
: DelayPeakDetector(tick_timer, ignore_reordered_packets) {}
virtual ~MockDelayPeakDetector() { Die(); }
MOCK_METHOD0(Die, void());
MOCK_METHOD0(Reset, void());
@ -28,7 +29,8 @@ class MockDelayPeakDetector : public DelayPeakDetector {
MOCK_METHOD0(peak_found, bool());
MOCK_CONST_METHOD0(MaxPeakHeight, int());
MOCK_CONST_METHOD0(MaxPeakPeriod, uint64_t());
MOCK_METHOD2(Update, bool(int inter_arrival_time, int target_level));
MOCK_METHOD3(Update,
bool(int inter_arrival_time, bool reordered, int target_level));
};
} // namespace webrtc

View File

@ -28,9 +28,10 @@ std::string NetEq::Config::ToString() const {
ss << "sample_rate_hz=" << sample_rate_hz << ", enable_post_decode_vad="
<< (enable_post_decode_vad ? "true" : "false")
<< ", max_packets_in_buffer=" << max_packets_in_buffer
<< ", enable_fast_accelerate="
<< (enable_fast_accelerate ? " true" : "false")
<< ", enable_muted_state=" << (enable_muted_state ? " true" : "false");
<< ", min_delay_ms=" << min_delay_ms << ", enable_fast_accelerate="
<< (enable_fast_accelerate ? "true" : "false")
<< ", enable_muted_state=" << (enable_muted_state ? "true" : "false")
<< ", enable_rtx_handling=" << (enable_rtx_handling ? "true" : "false");
return ss.str();
}

View File

@ -61,7 +61,8 @@ NetEqImpl::Dependencies::Dependencies(
buffer_level_filter(new BufferLevelFilter),
decoder_database(
new DecoderDatabase(decoder_factory, config.codec_pair_id)),
delay_peak_detector(new DelayPeakDetector(tick_timer.get())),
delay_peak_detector(
new DelayPeakDetector(tick_timer.get(), config.enable_rtx_handling)),
delay_manager(new DelayManager(config.max_packets_in_buffer,
config.min_delay_ms,
delay_peak_detector.get(),
@ -112,7 +113,8 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config,
speech_expand_uma_logger_("WebRTC.Audio.SpeechExpandRatePercent",
10, // Report once every 10 s.
tick_timer_.get()),
no_time_stretching_(config.for_test_no_time_stretching) {
no_time_stretching_(config.for_test_no_time_stretching),
enable_rtx_handling_(config.enable_rtx_handling) {
RTC_LOG(LS_INFO) << "NetEq config: " << config.ToString();
int fs = config.sample_rate_hz;
if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) {
@ -737,9 +739,11 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
}
// Update statistics.
if ((int32_t)(main_timestamp - timestamp_) >= 0 && !new_codec_) {
if ((enable_rtx_handling_ || (int32_t)(main_timestamp - timestamp_) >= 0) &&
!new_codec_) {
// Only update statistics if incoming packet is not older than last played
// out packet, and if new codec flag is not set.
// out packet or RTX handling is enabled, and if new codec flag is not
// set.
delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz_);
}
} else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {

View File

@ -408,6 +408,7 @@ class NetEqImpl : public webrtc::NetEq {
ExpandUmaLogger speech_expand_uma_logger_ RTC_GUARDED_BY(crit_sect_);
bool no_time_stretching_ RTC_GUARDED_BY(crit_sect_); // Only used for test.
rtc::BufferT<int16_t> concealment_audio_ RTC_GUARDED_BY(crit_sect_);
const bool enable_rtx_handling_ RTC_GUARDED_BY(crit_sect_);
private:
RTC_DISALLOW_COPY_AND_ASSIGN(NetEqImpl);

View File

@ -87,7 +87,7 @@ class NetEqImplTest : public ::testing::Test {
if (use_mock_delay_peak_detector_) {
std::unique_ptr<MockDelayPeakDetector> mock(
new MockDelayPeakDetector(tick_timer_));
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);
@ -1301,6 +1301,43 @@ TEST_F(NetEqImplTest, InsertEmptyPacket) {
neteq_->InsertEmptyPacket(rtp_header);
}
TEST_F(NetEqImplTest, EnableRtxHandling) {
UseNoMocks();
use_mock_delay_manager_ = true;
config_.enable_rtx_handling = true;
CreateInstance();
EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<0>(0), SetArgPointee<1>(0)));
const int kPayloadLengthSamples = 80;
const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples; // PCM 16-bit.
const uint8_t kPayloadType = 17; // Just an arbitrary number.
const uint32_t kReceiveTime = 17;
uint8_t payload[kPayloadLengthBytes] = {0};
RTPHeader rtp_header;
rtp_header.payloadType = kPayloadType;
rtp_header.sequenceNumber = 0x1234;
rtp_header.timestamp = 0x12345678;
rtp_header.ssrc = 0x87654321;
EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
EXPECT_EQ(NetEq::kOK,
neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
AudioFrame output;
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &muted));
// 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_EQ(NetEq::kOK,
neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
}
class Decoder120ms : public AudioDecoder {
public:
Decoder120ms(int sample_rate_hz, SpeechType speech_type)