blob: 6e0778b3875e7187ae3023e7cdae2911a31b443b [file] [log] [blame]
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +00001/*
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#include "webrtc/modules/audio_coding/neteq4/tools/packet.h"
12#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
13
14namespace webrtc {
15namespace test {
16
17Packet::Packet(uint8_t* packet_memory,
18 size_t allocated_bytes,
19 double time_ms,
20 const RtpHeaderParser& parser)
21 : payload_memory_(packet_memory),
22 payload_(NULL),
23 packet_length_bytes_(allocated_bytes),
24 payload_length_bytes_(0),
25 virtual_packet_length_bytes_(allocated_bytes),
26 virtual_payload_length_bytes_(0),
27 time_ms_(time_ms) {
28 valid_header_ = ParseHeader(parser);
29}
30
31Packet::Packet(uint8_t* packet_memory,
32 size_t allocated_bytes,
33 size_t virtual_packet_length_bytes,
34 double time_ms,
35 const RtpHeaderParser& parser)
36 : payload_memory_(packet_memory),
37 payload_(NULL),
38 packet_length_bytes_(allocated_bytes),
39 payload_length_bytes_(0),
40 virtual_packet_length_bytes_(virtual_packet_length_bytes),
41 virtual_payload_length_bytes_(0),
42 time_ms_(time_ms) {
43 valid_header_ = ParseHeader(parser);
44}
45
46Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
47 : payload_memory_(packet_memory),
48 payload_(NULL),
49 packet_length_bytes_(allocated_bytes),
50 payload_length_bytes_(0),
51 virtual_packet_length_bytes_(allocated_bytes),
52 virtual_payload_length_bytes_(0),
53 time_ms_(time_ms) {
54 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
55 valid_header_ = ParseHeader(*parser);
56}
57
58Packet::Packet(uint8_t* packet_memory,
59 size_t allocated_bytes,
60 size_t virtual_packet_length_bytes,
61 double time_ms)
62 : payload_memory_(packet_memory),
63 payload_(NULL),
64 packet_length_bytes_(allocated_bytes),
65 payload_length_bytes_(0),
66 virtual_packet_length_bytes_(virtual_packet_length_bytes),
67 virtual_payload_length_bytes_(0),
68 time_ms_(time_ms) {
69 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
70 valid_header_ = ParseHeader(*parser);
71}
72
73bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
74 //
75 // 0 1 2 3
76 // 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
77 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78 // |1| block PT | timestamp offset | block length |
79 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 // |1| ... |
81 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 // |0| block PT |
83 // +-+-+-+-+-+-+-+-+
84 //
85
86 assert(payload_);
87 const uint8_t* payload_ptr = payload_;
88 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
89
90 // Find all RED headers with the extension bit set to 1. That is, all headers
91 // but the last one.
92 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
93 RTPHeader* header = new RTPHeader;
94 CopyToHeader(header);
95 header->payloadType = payload_ptr[0] & 0x7F;
96 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
97 header->timestamp -= offset;
98 headers->push_front(header);
99 payload_ptr += 4;
100 }
101 // Last header.
102 assert(payload_ptr < payload_end_ptr);
103 if (payload_ptr >= payload_end_ptr) {
104 return false; // Payload too short.
105 }
106 RTPHeader* header = new RTPHeader;
107 CopyToHeader(header);
108 header->payloadType = payload_ptr[0] & 0x7F;
109 headers->push_front(header);
110 return true;
111}
112
113void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
114 while (!headers->empty()) {
115 delete headers->front();
116 headers->pop_front();
117 }
118}
119
120bool Packet::ParseHeader(const RtpHeaderParser& parser) {
121 bool valid_header = parser.Parse(
122 payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
123 assert(valid_header);
124 if (!valid_header) {
125 return false;
126 }
127 assert(header_.headerLength <= packet_length_bytes_);
128 payload_ = &payload_memory_[header_.headerLength];
129 assert(packet_length_bytes_ >= header_.headerLength);
130 payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
131 assert(virtual_packet_length_bytes_ >= header_.headerLength);
132 virtual_payload_length_bytes_ =
133 virtual_packet_length_bytes_ - header_.headerLength;
134 return true;
135}
136
137void Packet::CopyToHeader(RTPHeader* destination) const {
138 destination->markerBit = header_.markerBit;
139 destination->payloadType = header_.payloadType;
140 destination->sequenceNumber = header_.sequenceNumber;
141 destination->timestamp = header_.timestamp;
142 destination->ssrc = header_.ssrc;
143 destination->numCSRCs = header_.numCSRCs;
144 destination->paddingLength = header_.paddingLength;
145 destination->headerLength = header_.headerLength;
146 destination->payload_type_frequency = header_.payload_type_frequency;
147 memcpy(&destination->arrOfCSRCs,
148 &header_.arrOfCSRCs,
149 sizeof(header_.arrOfCSRCs));
150 memcpy(
151 &destination->extension, &header_.extension, sizeof(header_.extension));
152}
153
154} // namespace test
155} // namespace webrtc