Removing useless packets when inserting them (NetEq)

This is to save the buffer.

Some old code may become unnecessary, and will be removed in a separate CL.

BUG=
R=henrik.lundin@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/27669004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7406 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
minyue@webrtc.org 2014-10-09 10:49:54 +00:00
parent 0b0ac8236b
commit c803907d87
2 changed files with 99 additions and 87 deletions

View File

@ -71,7 +71,28 @@ int PacketBuffer::InsertPacket(Packet* packet) {
PacketList::reverse_iterator rit = std::find_if(
buffer_.rbegin(), buffer_.rend(),
NewTimestampIsLarger(packet));
buffer_.insert(rit.base(), packet); // Insert the packet at that position.
// The new packet is to be inserted to the right of |rit|. If it has the same
// timestamp as |rit|, which has a higher priority, do not insert the new
// packet to list.
if (rit != buffer_.rend() &&
packet->header.timestamp == (*rit)->header.timestamp) {
delete [] packet->payload;
delete packet;
return return_val;
}
// The new packet is to be inserted to the left of |it|. If it has the same
// timestamp as |it|, which has a lower priority, replace |it| with the new
// packet.
PacketList::iterator it = rit.base();
if (it != buffer_.end() &&
packet->header.timestamp == (*it)->header.timestamp) {
delete [] (*it)->payload;
delete *it;
it = buffer_.erase(it);
}
buffer_.insert(it, packet); // Insert the packet at that position.
return return_val;
}
@ -163,20 +184,24 @@ Packet* PacketBuffer::GetNextPacket(int* discard_count) {
// Assert that the packet sanity checks in InsertPacket method works.
assert(packet && packet->payload);
buffer_.pop_front();
// Discard other packets with the same timestamp. These are duplicates or
// redundant payloads that should not be used.
if (discard_count) {
*discard_count = 0;
}
int discards = 0;
while (!Empty() &&
buffer_.front()->header.timestamp == packet->header.timestamp) {
if (DiscardNextPacket() != kOK) {
assert(false); // Must be ok by design.
}
if (discard_count) {
++(*discard_count);
}
++discards;
}
// The way of inserting packet should not cause any packet discarding here.
// TODO(minyue): remove |discard_count|.
assert(discards == 0);
if (discard_count)
*discard_count = discards;
return packet;
}

View File

@ -27,8 +27,8 @@ class PacketGenerator {
public:
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);
void SkipPacket();
uint16_t seq_no_;
uint32_t ts_;
@ -37,11 +37,16 @@ class PacketGenerator {
};
PacketGenerator::PacketGenerator(uint16_t seq_no, uint32_t ts, uint8_t pt,
int frame_size)
: seq_no_(seq_no),
ts_(ts),
pt_(pt),
frame_size_(frame_size) {
int frame_size) {
Reset(seq_no, ts, pt, frame_size);
}
void PacketGenerator::Reset(uint16_t seq_no, uint32_t ts, uint8_t pt,
int frame_size) {
seq_no_ = seq_no;
ts_ = ts;
pt_ = pt;
frame_size_ = frame_size;
}
Packet* PacketGenerator::NextPacket(int payload_size_bytes) {
@ -61,11 +66,16 @@ Packet* PacketGenerator::NextPacket(int payload_size_bytes) {
return packet;
}
void PacketGenerator::SkipPacket() {
++seq_no_;
ts_ += frame_size_;
}
struct PacketsToInsert {
uint16_t sequence_number;
uint32_t timestamp;
uint8_t payload_type;
bool primary;
// Order of this packet to appear upon extraction, after inserting a series
// of packets. A negative number means that it should have been discarded
// before extraction.
int extract_order;
};
// Start of test definitions.
@ -219,86 +229,63 @@ TEST(PacketBuffer, InsertPacketListChangePayloadType) {
EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
}
// Test inserting a number of packets, and verifying correct extraction order.
// The packets inserted are as follows:
// Packet no. Seq. no. Primary TS Secondary TS
// 0 0xFFFD 0xFFFFFFD7 -
// 1 0xFFFE 0xFFFFFFE1 0xFFFFFFD7
// 2 0xFFFF 0xFFFFFFEB 0xFFFFFFE1
// 3 0x0000 0xFFFFFFF5 0xFFFFFFEB
// 4 0x0001 0xFFFFFFFF 0xFFFFFFF5
// 5 0x0002 0x0000000A 0xFFFFFFFF
// 6 MISSING--0x0003------0x00000014----0x0000000A--MISSING
// 7 0x0004 0x0000001E 0x00000014
// 8 0x0005 0x00000028 0x0000001E
// 9 0x0006 0x00000032 0x00000028
TEST(PacketBuffer, ExtractOrderRedundancy) {
PacketBuffer buffer(100); // 100 packets.
const uint32_t ts_increment = 10; // Samples per packet.
const uint16_t start_seq_no = 0xFFFF - 2; // Wraps after 3 packets.
const uint32_t start_ts = 0xFFFFFFFF -
4 * ts_increment; // Wraps after 5 packets.
const uint8_t primary_pt = 0;
const uint8_t secondary_pt = 1;
PacketGenerator gen(start_seq_no, start_ts, primary_pt, ts_increment);
// Insert secondary payloads too. (Simulating RED.)
PacketGenerator red_gen(start_seq_no + 1, start_ts, secondary_pt,
ts_increment);
const int kPackets = 18;
const int kFrameSize = 10;
const int kPayloadLength = 10;
// Insert 9 small packets (skip one).
for (int i = 0; i < 10; ++i) {
const int payload_len = 10;
if (i == 6) {
// Skip this packet.
gen.SkipPacket();
red_gen.SkipPacket();
continue;
}
// Primary payload.
Packet* packet = gen.NextPacket(payload_len);
PacketsToInsert packet_facts[kPackets] = {
{0xFFFD, 0xFFFFFFD7, 0, true, 0},
{0xFFFE, 0xFFFFFFE1, 0, true, 1},
{0xFFFE, 0xFFFFFFD7, 1, false, -1},
{0xFFFF, 0xFFFFFFEB, 0, true, 2},
{0xFFFF, 0xFFFFFFE1, 1, false, -1},
{0x0000, 0xFFFFFFF5, 0, true, 3},
{0x0000, 0xFFFFFFEB, 1, false, -1},
{0x0001, 0xFFFFFFFF, 0, true, 4},
{0x0001, 0xFFFFFFF5, 1, false, -1},
{0x0002, 0x0000000A, 0, true, 5},
{0x0002, 0xFFFFFFFF, 1, false, -1},
{0x0003, 0x0000000A, 1, false, -1},
{0x0004, 0x0000001E, 0, true, 7},
{0x0004, 0x00000014, 1, false, 6},
{0x0005, 0x0000001E, 0, true, -1},
{0x0005, 0x00000014, 1, false, -1},
{0x0006, 0x00000028, 0, true, 8},
{0x0006, 0x0000001E, 1, false, -1},
};
const int kExpectPacketsInBuffer = 9;
std::vector<Packet*> expect_order(kExpectPacketsInBuffer);
PacketGenerator gen(0, 0, 0, kFrameSize);
for (int i = 0; i < kPackets; ++i) {
gen.Reset(packet_facts[i].sequence_number,
packet_facts[i].timestamp,
packet_facts[i].payload_type,
kFrameSize);
Packet* packet = gen.NextPacket(kPayloadLength);
packet->primary = packet_facts[i].primary;
EXPECT_EQ(PacketBuffer::kOK, buffer.InsertPacket(packet));
if (i >= 1) {
// Secondary payload.
packet = red_gen.NextPacket(payload_len);
packet->primary = false;
EXPECT_EQ(PacketBuffer::kOK, buffer.InsertPacket(packet));
if (packet_facts[i].extract_order >= 0) {
expect_order[packet_facts[i].extract_order] = packet;
}
}
EXPECT_EQ(17, buffer.NumPacketsInBuffer()); // 9 primary + 8 secondary
uint16_t current_seq_no = start_seq_no;
uint32_t current_ts = start_ts;
EXPECT_EQ(kExpectPacketsInBuffer, buffer.NumPacketsInBuffer());
for (int i = 0; i < 10; ++i) {
// Extract packets.
int drop_count = 0;
int drop_count;
for (int i = 0; i < kExpectPacketsInBuffer; ++i) {
Packet* packet = buffer.GetNextPacket(&drop_count);
ASSERT_FALSE(packet == NULL);
if (i == 6) {
// Special case for the dropped primary payload.
// Expect secondary payload, and one step higher sequence number.
EXPECT_EQ(current_seq_no + 1, packet->header.sequenceNumber);
EXPECT_EQ(current_ts, packet->header.timestamp);
EXPECT_FALSE(packet->primary);
EXPECT_EQ(1, packet->header.payloadType);
EXPECT_EQ(0, drop_count);
} else {
EXPECT_EQ(current_seq_no, packet->header.sequenceNumber);
EXPECT_EQ(current_ts, packet->header.timestamp);
EXPECT_TRUE(packet->primary);
EXPECT_EQ(0, packet->header.payloadType);
if (i == 5 || i == 9) {
// No duplicate TS for dropped packet or for last primary payload.
EXPECT_EQ(0, drop_count);
} else {
EXPECT_EQ(1, drop_count);
}
}
++current_seq_no;
current_ts += ts_increment;
delete [] packet->payload;
EXPECT_EQ(0, drop_count);
EXPECT_EQ(packet, expect_order[i]); // Compare pointer addresses.
delete[] packet->payload;
delete packet;
}
EXPECT_TRUE(buffer.Empty());
}
TEST(PacketBuffer, DiscardPackets) {