Adding test on GetSpanSamples() for NetEq PacketBuffer.
Bug: webrtc:10736
Change-Id: I4448c5c8e1ae8ea5e343415c4fc2c0fd095ca8ad
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/144560
Commit-Queue: Minyue Li <minyue@webrtc.org>
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28481}
diff --git a/modules/audio_coding/neteq/packet_buffer_unittest.cc b/modules/audio_coding/neteq/packet_buffer_unittest.cc
index 7a381ee..ca42222 100644
--- a/modules/audio_coding/neteq/packet_buffer_unittest.cc
+++ b/modules/audio_coding/neteq/packet_buffer_unittest.cc
@@ -11,6 +11,7 @@
// Unit tests for PacketBuffer class.
#include "modules/audio_coding/neteq/packet_buffer.h"
+#include "absl/memory/memory.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
#include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
@@ -25,7 +26,17 @@
using ::testing::InSequence;
using ::testing::MockFunction;
-namespace webrtc {
+namespace {
+class MockEncodedAudioFrame : public webrtc::AudioDecoder::EncodedAudioFrame {
+ public:
+ MOCK_CONST_METHOD0(Duration, size_t());
+
+ MOCK_CONST_METHOD0(IsDtxPacket, bool());
+
+ MOCK_CONST_METHOD1(
+ Decode,
+ absl::optional<DecodeResult>(rtc::ArrayView<int16_t> decoded));
+};
// Helper class to generate packets. Packets must be deleted by the user.
class PacketGenerator {
@@ -33,7 +44,9 @@
PacketGenerator(uint16_t seq_no, uint32_t ts, uint8_t pt, int frame_size);
virtual ~PacketGenerator() {}
void Reset(uint16_t seq_no, uint32_t ts, uint8_t pt, int frame_size);
- Packet NextPacket(int payload_size_bytes);
+ webrtc::Packet NextPacket(
+ int payload_size_bytes,
+ std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame);
uint16_t seq_no_;
uint32_t ts_;
@@ -54,14 +67,17 @@
frame_size_ = frame_size;
}
-Packet PacketGenerator::NextPacket(int payload_size_bytes) {
- Packet packet;
+webrtc::Packet PacketGenerator::NextPacket(
+ int payload_size_bytes,
+ std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame) {
+ webrtc::Packet packet;
packet.sequence_number = seq_no_;
packet.timestamp = ts_;
packet.payload_type = pt_;
packet.payload.SetSize(payload_size_bytes);
++seq_no_;
ts_ += frame_size_;
+ packet.frame = std::move(audio_frame);
return packet;
}
@@ -76,6 +92,10 @@
int extract_order;
};
+} // namespace
+
+namespace webrtc {
+
// Start of test definitions.
TEST(PacketBuffer, CreateAndDestroy) {
@@ -92,7 +112,7 @@
StrictMock<MockStatisticsCalculator> mock_stats;
const int payload_len = 100;
- const Packet packet = gen.NextPacket(payload_len);
+ const Packet packet = gen.NextPacket(payload_len, nullptr);
EXPECT_EQ(0, buffer.InsertPacket(packet.Clone(), &mock_stats));
uint32_t next_ts;
EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
@@ -116,8 +136,9 @@
// Insert 10 small packets; should be ok.
for (int i = 0; i < 10; ++i) {
- EXPECT_EQ(PacketBuffer::kOK,
- buffer.InsertPacket(gen.NextPacket(payload_len), &mock_stats));
+ EXPECT_EQ(
+ PacketBuffer::kOK,
+ buffer.InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats));
}
EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
EXPECT_FALSE(buffer.Empty());
@@ -139,15 +160,16 @@
const int payload_len = 10;
int i;
for (i = 0; i < 10; ++i) {
- EXPECT_EQ(PacketBuffer::kOK,
- buffer.InsertPacket(gen.NextPacket(payload_len), &mock_stats));
+ EXPECT_EQ(
+ PacketBuffer::kOK,
+ buffer.InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats));
}
EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
uint32_t next_ts;
EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
EXPECT_EQ(0u, next_ts); // Expect first inserted packet to be first in line.
- const Packet packet = gen.NextPacket(payload_len);
+ const Packet packet = gen.NextPacket(payload_len, nullptr);
// Insert 11th packet; should flush the buffer and insert it after flushing.
EXPECT_EQ(PacketBuffer::kFlushed,
buffer.InsertPacket(packet.Clone(), &mock_stats));
@@ -170,7 +192,7 @@
// Insert 10 small packets.
for (int i = 0; i < 10; ++i) {
- list.push_back(gen.NextPacket(payload_len));
+ list.push_back(gen.NextPacket(payload_len, nullptr));
}
MockDecoderDatabase decoder_database;
@@ -209,11 +231,11 @@
// Insert 10 small packets.
for (int i = 0; i < 10; ++i) {
- list.push_back(gen.NextPacket(payload_len));
+ list.push_back(gen.NextPacket(payload_len, nullptr));
}
// Insert 11th packet of another payload type (not CNG).
{
- Packet packet = gen.NextPacket(payload_len);
+ Packet packet = gen.NextPacket(payload_len, nullptr);
packet.payload_type = 1;
list.push_back(std::move(packet));
}
@@ -292,7 +314,7 @@
packet_facts[i].timestamp,
packet_facts[i].payload_type,
kFrameSize);
- Packet packet = gen.NextPacket(kPayloadLength);
+ Packet packet = gen.NextPacket(kPayloadLength, nullptr);
packet.priority.codec_level = packet_facts[i].primary ? 0 : 1;
if (packet_facts[i].extract_order < 0) {
if (packet.priority.codec_level > 0) {
@@ -333,7 +355,7 @@
constexpr int kTotalPackets = 10;
// Insert 10 small packets.
for (int i = 0; i < kTotalPackets; ++i) {
- buffer.InsertPacket(gen.NextPacket(payload_len), &mock_stats);
+ buffer.InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats);
}
EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
@@ -397,7 +419,7 @@
// a (rather strange) reordering.
PacketList list;
for (int i = 0; i < 10; ++i) {
- Packet packet = gen.NextPacket(payload_len);
+ Packet packet = gen.NextPacket(payload_len, nullptr);
if (i % 2) {
list.push_front(std::move(packet));
} else {
@@ -459,7 +481,7 @@
// Insert first packet, which is narrow-band CNG.
PacketGenerator gen(0, 0, kCngPt, 10);
PacketList list;
- list.push_back(gen.NextPacket(kPayloadLen));
+ list.push_back(gen.NextPacket(kPayloadLen, nullptr));
absl::optional<uint8_t> current_pt;
absl::optional<uint8_t> current_cng_pt;
@@ -477,7 +499,7 @@
// Insert second packet, which is wide-band speech.
{
- Packet packet = gen.NextPacket(kPayloadLen);
+ Packet packet = gen.NextPacket(kPayloadLen, nullptr);
packet.payload_type = kSpeechPt;
list.push_back(std::move(packet));
}
@@ -509,7 +531,7 @@
PacketBuffer* buffer = new PacketBuffer(100, &tick_timer); // 100 packets.
{
- Packet packet = gen.NextPacket(payload_len);
+ Packet packet = gen.NextPacket(payload_len, nullptr);
packet.payload.Clear();
EXPECT_EQ(PacketBuffer::kInvalidPacket,
buffer->InsertPacket(std::move(packet), &mock_stats));
@@ -528,8 +550,9 @@
buffer->DiscardAllOldPackets(0, &mock_stats);
// Insert one packet to make the buffer non-empty.
- EXPECT_EQ(PacketBuffer::kOK,
- buffer->InsertPacket(gen.NextPacket(payload_len), &mock_stats));
+ EXPECT_EQ(
+ PacketBuffer::kOK,
+ buffer->InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats));
EXPECT_EQ(PacketBuffer::kInvalidPointer, buffer->NextTimestamp(NULL));
EXPECT_EQ(PacketBuffer::kInvalidPointer,
buffer->NextHigherTimestamp(0, NULL));
@@ -540,13 +563,13 @@
// discarded.
buffer = new PacketBuffer(100, &tick_timer); // 100 packets.
PacketList list;
- list.push_back(gen.NextPacket(payload_len)); // Valid packet.
+ list.push_back(gen.NextPacket(payload_len, nullptr)); // Valid packet.
{
- Packet packet = gen.NextPacket(payload_len);
+ Packet packet = gen.NextPacket(payload_len, nullptr);
packet.payload.Clear(); // Invalid.
list.push_back(std::move(packet));
}
- list.push_back(gen.NextPacket(payload_len)); // Valid packet.
+ list.push_back(gen.NextPacket(payload_len, nullptr)); // Valid packet.
MockDecoderDatabase decoder_database;
auto factory = CreateBuiltinAudioDecoderFactory();
const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
@@ -568,8 +591,8 @@
// The function should return true if the first packet "goes before" the second.
TEST(PacketBuffer, ComparePackets) {
PacketGenerator gen(0, 0, 0, 10);
- Packet a(gen.NextPacket(10)); // SN = 0, TS = 0.
- Packet b(gen.NextPacket(10)); // SN = 1, TS = 10.
+ Packet a(gen.NextPacket(10, nullptr)); // SN = 0, TS = 0.
+ Packet b(gen.NextPacket(10, nullptr)); // SN = 1, TS = 10.
EXPECT_FALSE(a == b);
EXPECT_TRUE(a != b);
EXPECT_TRUE(a < b);
@@ -624,8 +647,8 @@
EXPECT_FALSE(a <= b);
EXPECT_TRUE(a >= b);
- Packet c(gen.NextPacket(0)); // SN = 2, TS = 20.
- Packet d(gen.NextPacket(0)); // SN = 3, TS = 20.
+ Packet c(gen.NextPacket(0, nullptr)); // SN = 2, TS = 20.
+ Packet d(gen.NextPacket(0, nullptr)); // SN = 3, TS = 20.
c.timestamp = b.timestamp;
d.timestamp = b.timestamp;
c.sequence_number = b.sequence_number;
@@ -673,6 +696,52 @@
EXPECT_TRUE(d >= b);
}
+TEST(PacketBuffer, GetSpanSamples) {
+ constexpr size_t kFrameSizeSamples = 10;
+ constexpr int kPayloadSizeBytes = 1; // Does not matter to this test;
+ constexpr uint32_t kStartTimeStamp = 0xFFFFFFFE; // Close to wrap around.
+ constexpr int kSampleRateHz = 48000;
+ constexpr bool KCountDtxWaitingTime = false;
+ TickTimer tick_timer;
+ PacketBuffer buffer(3, &tick_timer);
+ PacketGenerator gen(0, kStartTimeStamp, 0, kFrameSizeSamples);
+ StrictMock<MockStatisticsCalculator> mock_stats;
+
+ Packet packet_1 = gen.NextPacket(kPayloadSizeBytes, nullptr);
+
+ std::unique_ptr<MockEncodedAudioFrame> mock_audio_frame =
+ absl::make_unique<MockEncodedAudioFrame>();
+ EXPECT_CALL(*mock_audio_frame, Duration())
+ .WillRepeatedly(Return(kFrameSizeSamples));
+ Packet packet_2 =
+ gen.NextPacket(kPayloadSizeBytes, std::move(mock_audio_frame));
+
+ RTC_DCHECK_GT(packet_1.timestamp,
+ packet_2.timestamp); // Tmestamp wrapped around.
+
+ EXPECT_EQ(PacketBuffer::kOK,
+ buffer.InsertPacket(std::move(packet_1), &mock_stats));
+
+ constexpr size_t kLastDecodedSizeSamples = 2;
+ // packet_1 has no access to duration, and relies last decoded duration as
+ // input.
+ EXPECT_EQ(kLastDecodedSizeSamples,
+ buffer.GetSpanSamples(kLastDecodedSizeSamples, kSampleRateHz,
+ KCountDtxWaitingTime));
+
+ EXPECT_EQ(PacketBuffer::kOK,
+ buffer.InsertPacket(std::move(packet_2), &mock_stats));
+
+ EXPECT_EQ(kFrameSizeSamples * 2,
+ buffer.GetSpanSamples(0, kSampleRateHz, KCountDtxWaitingTime));
+
+ // packet_2 has access to duration, and ignores last decoded duration as
+ // input.
+ EXPECT_EQ(kFrameSizeSamples * 2,
+ buffer.GetSpanSamples(kLastDecodedSizeSamples, kSampleRateHz,
+ KCountDtxWaitingTime));
+}
+
namespace {
void TestIsObsoleteTimestamp(uint32_t limit_timestamp) {
// Check with zero horizon, which implies that the horizon is at 2^31, i.e.,
@@ -735,4 +804,5 @@
TestIsObsoleteTimestamp(0x80000001); // 2^31 + 1.
TestIsObsoleteTimestamp(0x7FFFFFFF); // 2^31 - 1.
}
+
} // namespace webrtc