blob: b1a9b64193bf75b79a70c76e20f2012e89f5308a [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/rtp_rtcp/include/rtp_header_parser.h"
18#include "rtc_base/checks.h"
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000019
20namespace webrtc {
21namespace test {
22
23Packet::Packet(uint8_t* packet_memory,
24 size_t allocated_bytes,
25 double time_ms,
26 const RtpHeaderParser& parser)
27 : payload_memory_(packet_memory),
28 payload_(NULL),
29 packet_length_bytes_(allocated_bytes),
30 payload_length_bytes_(0),
31 virtual_packet_length_bytes_(allocated_bytes),
32 virtual_payload_length_bytes_(0),
33 time_ms_(time_ms) {
34 valid_header_ = ParseHeader(parser);
35}
36
37Packet::Packet(uint8_t* packet_memory,
38 size_t allocated_bytes,
39 size_t virtual_packet_length_bytes,
40 double time_ms,
41 const RtpHeaderParser& parser)
42 : payload_memory_(packet_memory),
43 payload_(NULL),
44 packet_length_bytes_(allocated_bytes),
45 payload_length_bytes_(0),
46 virtual_packet_length_bytes_(virtual_packet_length_bytes),
47 virtual_payload_length_bytes_(0),
48 time_ms_(time_ms) {
49 valid_header_ = ParseHeader(parser);
50}
51
52Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
53 : payload_memory_(packet_memory),
54 payload_(NULL),
55 packet_length_bytes_(allocated_bytes),
56 payload_length_bytes_(0),
57 virtual_packet_length_bytes_(allocated_bytes),
58 virtual_payload_length_bytes_(0),
59 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080060 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000061 valid_header_ = ParseHeader(*parser);
62}
63
64Packet::Packet(uint8_t* packet_memory,
65 size_t allocated_bytes,
66 size_t virtual_packet_length_bytes,
67 double time_ms)
68 : payload_memory_(packet_memory),
69 payload_(NULL),
70 packet_length_bytes_(allocated_bytes),
71 payload_length_bytes_(0),
72 virtual_packet_length_bytes_(virtual_packet_length_bytes),
73 virtual_payload_length_bytes_(0),
74 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080075 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000076 valid_header_ = ParseHeader(*parser);
77}
78
kwibergb8e56ee2016-08-29 06:37:33 -070079Packet::~Packet() = default;
80
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000081bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
82 //
83 // 0 1 2 3
84 // 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
85 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 // |1| block PT | timestamp offset | block length |
87 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88 // |1| ... |
89 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 // |0| block PT |
91 // +-+-+-+-+-+-+-+-+
92 //
93
94 assert(payload_);
95 const uint8_t* payload_ptr = payload_;
96 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
97
98 // Find all RED headers with the extension bit set to 1. That is, all headers
99 // but the last one.
100 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
101 RTPHeader* header = new RTPHeader;
102 CopyToHeader(header);
103 header->payloadType = payload_ptr[0] & 0x7F;
104 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
105 header->timestamp -= offset;
106 headers->push_front(header);
107 payload_ptr += 4;
108 }
109 // Last header.
110 assert(payload_ptr < payload_end_ptr);
111 if (payload_ptr >= payload_end_ptr) {
112 return false; // Payload too short.
113 }
114 RTPHeader* header = new RTPHeader;
115 CopyToHeader(header);
116 header->payloadType = payload_ptr[0] & 0x7F;
117 headers->push_front(header);
118 return true;
119}
120
121void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
122 while (!headers->empty()) {
123 delete headers->front();
124 headers->pop_front();
125 }
126}
127
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000128bool Packet::ParseHeader(const RtpHeaderParser& parser) {
129 bool valid_header = parser.Parse(
130 payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
henrik.lundin7a2862a2017-06-01 07:41:11 -0700131 // Special case for dummy packets that have padding marked in the RTP header.
132 // This causes the RTP header parser to report failure, but is fine in this
133 // context.
134 const bool header_only_with_padding =
135 (header_.headerLength == packet_length_bytes_ &&
136 header_.paddingLength > 0);
137 if (!valid_header && !header_only_with_padding) {
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000138 return false;
139 }
140 assert(header_.headerLength <= packet_length_bytes_);
141 payload_ = &payload_memory_[header_.headerLength];
142 assert(packet_length_bytes_ >= header_.headerLength);
143 payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
henrik.lundind1a10a02016-08-24 10:58:54 -0700144 RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000145 assert(virtual_packet_length_bytes_ >= header_.headerLength);
146 virtual_payload_length_bytes_ =
147 virtual_packet_length_bytes_ - header_.headerLength;
148 return true;
149}
150
151void Packet::CopyToHeader(RTPHeader* destination) const {
152 destination->markerBit = header_.markerBit;
153 destination->payloadType = header_.payloadType;
154 destination->sequenceNumber = header_.sequenceNumber;
155 destination->timestamp = header_.timestamp;
156 destination->ssrc = header_.ssrc;
157 destination->numCSRCs = header_.numCSRCs;
158 destination->paddingLength = header_.paddingLength;
159 destination->headerLength = header_.headerLength;
160 destination->payload_type_frequency = header_.payload_type_frequency;
Yves Gerey665174f2018-06-19 15:03:05 +0200161 memcpy(&destination->arrOfCSRCs, &header_.arrOfCSRCs,
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000162 sizeof(header_.arrOfCSRCs));
Yves Gerey665174f2018-06-19 15:03:05 +0200163 memcpy(&destination->extension, &header_.extension,
164 sizeof(header_.extension));
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000165}
166
167} // namespace test
168} // namespace webrtc