blob: 71337b6e68b560220c3e4c1b95d69eaf330610de [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/tools/packet.h"
henrik.lundin@webrtc.org1c839122014-08-11 12:29:38 +000012
13#include <string.h>
14
kwiberg2d0c3322016-02-14 09:28:33 -080015#include <memory>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/include/module_common_types.h"
18#include "modules/rtp_rtcp/include/rtp_header_parser.h"
19#include "rtc_base/checks.h"
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000020
21namespace webrtc {
22namespace test {
23
24Packet::Packet(uint8_t* packet_memory,
25 size_t allocated_bytes,
26 double time_ms,
27 const RtpHeaderParser& parser)
28 : payload_memory_(packet_memory),
29 payload_(NULL),
30 packet_length_bytes_(allocated_bytes),
31 payload_length_bytes_(0),
32 virtual_packet_length_bytes_(allocated_bytes),
33 virtual_payload_length_bytes_(0),
34 time_ms_(time_ms) {
35 valid_header_ = ParseHeader(parser);
36}
37
38Packet::Packet(uint8_t* packet_memory,
39 size_t allocated_bytes,
40 size_t virtual_packet_length_bytes,
41 double time_ms,
42 const RtpHeaderParser& parser)
43 : payload_memory_(packet_memory),
44 payload_(NULL),
45 packet_length_bytes_(allocated_bytes),
46 payload_length_bytes_(0),
47 virtual_packet_length_bytes_(virtual_packet_length_bytes),
48 virtual_payload_length_bytes_(0),
49 time_ms_(time_ms) {
50 valid_header_ = ParseHeader(parser);
51}
52
53Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
54 : payload_memory_(packet_memory),
55 payload_(NULL),
56 packet_length_bytes_(allocated_bytes),
57 payload_length_bytes_(0),
58 virtual_packet_length_bytes_(allocated_bytes),
59 virtual_payload_length_bytes_(0),
60 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080061 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000062 valid_header_ = ParseHeader(*parser);
63}
64
65Packet::Packet(uint8_t* packet_memory,
66 size_t allocated_bytes,
67 size_t virtual_packet_length_bytes,
68 double time_ms)
69 : payload_memory_(packet_memory),
70 payload_(NULL),
71 packet_length_bytes_(allocated_bytes),
72 payload_length_bytes_(0),
73 virtual_packet_length_bytes_(virtual_packet_length_bytes),
74 virtual_payload_length_bytes_(0),
75 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080076 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000077 valid_header_ = ParseHeader(*parser);
78}
79
kwibergb8e56ee2016-08-29 06:37:33 -070080Packet::~Packet() = default;
81
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000082bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
83 //
84 // 0 1 2 3
85 // 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
86 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 // |1| block PT | timestamp offset | block length |
88 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 // |1| ... |
90 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 // |0| block PT |
92 // +-+-+-+-+-+-+-+-+
93 //
94
95 assert(payload_);
96 const uint8_t* payload_ptr = payload_;
97 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
98
99 // Find all RED headers with the extension bit set to 1. That is, all headers
100 // but the last one.
101 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
102 RTPHeader* header = new RTPHeader;
103 CopyToHeader(header);
104 header->payloadType = payload_ptr[0] & 0x7F;
105 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
106 header->timestamp -= offset;
107 headers->push_front(header);
108 payload_ptr += 4;
109 }
110 // Last header.
111 assert(payload_ptr < payload_end_ptr);
112 if (payload_ptr >= payload_end_ptr) {
113 return false; // Payload too short.
114 }
115 RTPHeader* header = new RTPHeader;
116 CopyToHeader(header);
117 header->payloadType = payload_ptr[0] & 0x7F;
118 headers->push_front(header);
119 return true;
120}
121
122void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
123 while (!headers->empty()) {
124 delete headers->front();
125 headers->pop_front();
126 }
127}
128
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000129bool Packet::ParseHeader(const RtpHeaderParser& parser) {
130 bool valid_header = parser.Parse(
131 payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
henrik.lundin7a2862a2017-06-01 07:41:11 -0700132 // Special case for dummy packets that have padding marked in the RTP header.
133 // This causes the RTP header parser to report failure, but is fine in this
134 // context.
135 const bool header_only_with_padding =
136 (header_.headerLength == packet_length_bytes_ &&
137 header_.paddingLength > 0);
138 if (!valid_header && !header_only_with_padding) {
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000139 return false;
140 }
141 assert(header_.headerLength <= packet_length_bytes_);
142 payload_ = &payload_memory_[header_.headerLength];
143 assert(packet_length_bytes_ >= header_.headerLength);
144 payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
henrik.lundind1a10a02016-08-24 10:58:54 -0700145 RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000146 assert(virtual_packet_length_bytes_ >= header_.headerLength);
147 virtual_payload_length_bytes_ =
148 virtual_packet_length_bytes_ - header_.headerLength;
149 return true;
150}
151
152void Packet::CopyToHeader(RTPHeader* destination) const {
153 destination->markerBit = header_.markerBit;
154 destination->payloadType = header_.payloadType;
155 destination->sequenceNumber = header_.sequenceNumber;
156 destination->timestamp = header_.timestamp;
157 destination->ssrc = header_.ssrc;
158 destination->numCSRCs = header_.numCSRCs;
159 destination->paddingLength = header_.paddingLength;
160 destination->headerLength = header_.headerLength;
161 destination->payload_type_frequency = header_.payload_type_frequency;
162 memcpy(&destination->arrOfCSRCs,
163 &header_.arrOfCSRCs,
164 sizeof(header_.arrOfCSRCs));
165 memcpy(
166 &destination->extension, &header_.extension, sizeof(header_.extension));
167}
168
169} // namespace test
170} // namespace webrtc