1/*
2 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11// Unit tests for test Packet class.
12
13#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
14
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace webrtc {
18namespace test {
19
20namespace {
21const int kHeaderLengthBytes = 12;
22
23void MakeRtpHeader(int payload_type,
24                   int seq_number,
25                   uint32_t timestamp,
26                   uint32_t ssrc,
27                   uint8_t* rtp_data) {
28  rtp_data[0] = 0x80;
29  rtp_data[1] = payload_type & 0xFF;
30  rtp_data[2] = (seq_number >> 8) & 0xFF;
31  rtp_data[3] = (seq_number) & 0xFF;
32  rtp_data[4] = (timestamp >> 24) & 0xFF;
33  rtp_data[5] = (timestamp >> 16) & 0xFF;
34  rtp_data[6] = (timestamp >> 8) & 0xFF;
35  rtp_data[7] = timestamp & 0xFF;
36  rtp_data[8] = (ssrc >> 24) & 0xFF;
37  rtp_data[9] = (ssrc >> 16) & 0xFF;
38  rtp_data[10] = (ssrc >> 8) & 0xFF;
39  rtp_data[11] = ssrc & 0xFF;
40}
41}  // namespace
42
43TEST(TestPacket, RegularPacket) {
44  const size_t kPacketLengthBytes = 100;
45  uint8_t* packet_memory = new uint8_t[kPacketLengthBytes];
46  const uint8_t kPayloadType = 17;
47  const uint16_t kSequenceNumber = 4711;
48  const uint32_t kTimestamp = 47114711;
49  const uint32_t kSsrc = 0x12345678;
50  MakeRtpHeader(
51      kPayloadType, kSequenceNumber, kTimestamp, kSsrc, packet_memory);
52  const double kPacketTime = 1.0;
53  // Hand over ownership of |packet_memory| to |packet|.
54  Packet packet(packet_memory, kPacketLengthBytes, kPacketTime);
55  ASSERT_TRUE(packet.valid_header());
56  EXPECT_EQ(kPayloadType, packet.header().payloadType);
57  EXPECT_EQ(kSequenceNumber, packet.header().sequenceNumber);
58  EXPECT_EQ(kTimestamp, packet.header().timestamp);
59  EXPECT_EQ(kSsrc, packet.header().ssrc);
60  EXPECT_EQ(0, packet.header().numCSRCs);
61  EXPECT_EQ(kPacketLengthBytes, packet.packet_length_bytes());
62  EXPECT_EQ(kPacketLengthBytes - kHeaderLengthBytes,
63            packet.payload_length_bytes());
64  EXPECT_EQ(kPacketLengthBytes, packet.virtual_packet_length_bytes());
65  EXPECT_EQ(kPacketLengthBytes - kHeaderLengthBytes,
66            packet.virtual_payload_length_bytes());
67  EXPECT_EQ(kPacketTime, packet.time_ms());
68}
69
70TEST(TestPacket, DummyPacket) {
71  const size_t kPacketLengthBytes = kHeaderLengthBytes;  // Only RTP header.
72  const size_t kVirtualPacketLengthBytes = 100;
73  uint8_t* packet_memory = new uint8_t[kPacketLengthBytes];
74  const uint8_t kPayloadType = 17;
75  const uint16_t kSequenceNumber = 4711;
76  const uint32_t kTimestamp = 47114711;
77  const uint32_t kSsrc = 0x12345678;
78  MakeRtpHeader(
79      kPayloadType, kSequenceNumber, kTimestamp, kSsrc, packet_memory);
80  const double kPacketTime = 1.0;
81  // Hand over ownership of |packet_memory| to |packet|.
82  Packet packet(packet_memory,
83                kPacketLengthBytes,
84                kVirtualPacketLengthBytes,
85                kPacketTime);
86  ASSERT_TRUE(packet.valid_header());
87  EXPECT_EQ(kPayloadType, packet.header().payloadType);
88  EXPECT_EQ(kSequenceNumber, packet.header().sequenceNumber);
89  EXPECT_EQ(kTimestamp, packet.header().timestamp);
90  EXPECT_EQ(kSsrc, packet.header().ssrc);
91  EXPECT_EQ(0, packet.header().numCSRCs);
92  EXPECT_EQ(kPacketLengthBytes, packet.packet_length_bytes());
93  EXPECT_EQ(kPacketLengthBytes - kHeaderLengthBytes,
94            packet.payload_length_bytes());
95  EXPECT_EQ(kVirtualPacketLengthBytes, packet.virtual_packet_length_bytes());
96  EXPECT_EQ(kVirtualPacketLengthBytes - kHeaderLengthBytes,
97            packet.virtual_payload_length_bytes());
98  EXPECT_EQ(kPacketTime, packet.time_ms());
99}
100
101namespace {
102// Writes one RED block header starting at |rtp_data|, according to RFC 2198.
103// returns the number of bytes written (1 or 4).
104//
105// Format if |last_payoad| is false:
106// 0                   1                    2                   3
107// 0 1 2 3 4 5 6 7 8 9 0 1 2 3  4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
108// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109// |1|   block PT  |  timestamp offset         |   block length    |
110// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111//
112// Format if |last_payoad| is true:
113// 0 1 2 3 4 5 6 7
114// +-+-+-+-+-+-+-+-+
115// |0|   Block PT  |
116// +-+-+-+-+-+-+-+-+
117
118int MakeRedHeader(int payload_type,
119                  uint32_t timestamp_offset,
120                  int block_length,
121                  bool last_payload,
122                  uint8_t* rtp_data) {
123  rtp_data[0] = 0x80 | (payload_type & 0x7F);  // Set the first bit to 1.
124  if (last_payload) {
125    rtp_data[0] &= 0x7F;  // Reset the first but to 0 to indicate last block.
126    return 1;
127  }
128  rtp_data[1] = timestamp_offset >> 6;
129  rtp_data[2] = (timestamp_offset & 0x3F) << 2;
130  rtp_data[2] |= block_length >> 8;
131  rtp_data[3] = block_length & 0xFF;
132  return 4;
133}
134}  // namespace
135
136TEST(TestPacket, RED) {
137  const size_t kPacketLengthBytes = 100;
138  uint8_t* packet_memory = new uint8_t[kPacketLengthBytes];
139  const uint8_t kRedPayloadType = 17;
140  const uint16_t kSequenceNumber = 4711;
141  const uint32_t kTimestamp = 47114711;
142  const uint32_t kSsrc = 0x12345678;
143  MakeRtpHeader(
144      kRedPayloadType, kSequenceNumber, kTimestamp, kSsrc, packet_memory);
145  // Create four RED headers.
146  // Payload types are just the same as the block index the offset is 100 times
147  // the block index.
148  const int kRedBlocks = 4;
149  uint8_t* payload_ptr =
150      &packet_memory[kHeaderLengthBytes];  // First byte after header.
151  for (int i = 0; i < kRedBlocks; ++i) {
152    int payload_type = i;
153    // Offset value is not used for the last block.
154    uint32_t timestamp_offset = 100 * i;
155    int block_length = 10 * i;
156    bool last_block = (i == kRedBlocks - 1) ? true : false;
157    payload_ptr += MakeRedHeader(
158        payload_type, timestamp_offset, block_length, last_block, payload_ptr);
159  }
160  const double kPacketTime = 1.0;
161  // Hand over ownership of |packet_memory| to |packet|.
162  Packet packet(packet_memory, kPacketLengthBytes, kPacketTime);
163  ASSERT_TRUE(packet.valid_header());
164  EXPECT_EQ(kRedPayloadType, packet.header().payloadType);
165  EXPECT_EQ(kSequenceNumber, packet.header().sequenceNumber);
166  EXPECT_EQ(kTimestamp, packet.header().timestamp);
167  EXPECT_EQ(kSsrc, packet.header().ssrc);
168  EXPECT_EQ(0, packet.header().numCSRCs);
169  EXPECT_EQ(kPacketLengthBytes, packet.packet_length_bytes());
170  EXPECT_EQ(kPacketLengthBytes - kHeaderLengthBytes,
171            packet.payload_length_bytes());
172  EXPECT_EQ(kPacketLengthBytes, packet.virtual_packet_length_bytes());
173  EXPECT_EQ(kPacketLengthBytes - kHeaderLengthBytes,
174            packet.virtual_payload_length_bytes());
175  EXPECT_EQ(kPacketTime, packet.time_ms());
176  std::list<RTPHeader*> red_headers;
177  EXPECT_TRUE(packet.ExtractRedHeaders(&red_headers));
178  EXPECT_EQ(kRedBlocks, static_cast<int>(red_headers.size()));
179  int block_index = 0;
180  for (std::list<RTPHeader*>::reverse_iterator it = red_headers.rbegin();
181       it != red_headers.rend();
182       ++it) {
183    // Reading list from the back, since the extraction puts the main payload
184    // (which is the last one on wire) first.
185    RTPHeader* red_block = *it;
186    EXPECT_EQ(block_index, red_block->payloadType);
187    EXPECT_EQ(kSequenceNumber, red_block->sequenceNumber);
188    if (block_index == kRedBlocks - 1) {
189      // Last block has zero offset per definition.
190      EXPECT_EQ(kTimestamp, red_block->timestamp);
191    } else {
192      EXPECT_EQ(kTimestamp - 100 * block_index, red_block->timestamp);
193    }
194    EXPECT_EQ(kSsrc, red_block->ssrc);
195    EXPECT_EQ(0, red_block->numCSRCs);
196    ++block_index;
197  }
198  Packet::DeleteRedHeaders(&red_headers);
199}
200
201}  // namespace test
202}  // namespace webrtc
203