blob: 4e2102da2d17a2a467a5e7aa8137f4abe40908ea [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
Bjorn Terelius5350d1c2018-10-11 16:51:23 +020052Packet::Packet(const RTPHeader& header,
53 size_t virtual_packet_length_bytes,
54 size_t virtual_payload_length_bytes,
55 double time_ms)
56 : header_(header),
57 payload_memory_(),
58 payload_(NULL),
59 packet_length_bytes_(0),
60 payload_length_bytes_(0),
61 virtual_packet_length_bytes_(virtual_packet_length_bytes),
62 virtual_payload_length_bytes_(virtual_payload_length_bytes),
63 time_ms_(time_ms),
64 valid_header_(true) {}
65
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000066Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
67 : payload_memory_(packet_memory),
68 payload_(NULL),
69 packet_length_bytes_(allocated_bytes),
70 payload_length_bytes_(0),
71 virtual_packet_length_bytes_(allocated_bytes),
72 virtual_payload_length_bytes_(0),
73 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080074 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000075 valid_header_ = ParseHeader(*parser);
76}
77
78Packet::Packet(uint8_t* packet_memory,
79 size_t allocated_bytes,
80 size_t virtual_packet_length_bytes,
81 double time_ms)
82 : payload_memory_(packet_memory),
83 payload_(NULL),
84 packet_length_bytes_(allocated_bytes),
85 payload_length_bytes_(0),
86 virtual_packet_length_bytes_(virtual_packet_length_bytes),
87 virtual_payload_length_bytes_(0),
88 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080089 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000090 valid_header_ = ParseHeader(*parser);
91}
92
kwibergb8e56ee2016-08-29 06:37:33 -070093Packet::~Packet() = default;
94
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000095bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
96 //
97 // 0 1 2 3
98 // 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
99 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 // |1| block PT | timestamp offset | block length |
101 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 // |1| ... |
103 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 // |0| block PT |
105 // +-+-+-+-+-+-+-+-+
106 //
107
108 assert(payload_);
109 const uint8_t* payload_ptr = payload_;
110 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
111
112 // Find all RED headers with the extension bit set to 1. That is, all headers
113 // but the last one.
114 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
115 RTPHeader* header = new RTPHeader;
116 CopyToHeader(header);
117 header->payloadType = payload_ptr[0] & 0x7F;
118 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
119 header->timestamp -= offset;
120 headers->push_front(header);
121 payload_ptr += 4;
122 }
123 // Last header.
124 assert(payload_ptr < payload_end_ptr);
125 if (payload_ptr >= payload_end_ptr) {
126 return false; // Payload too short.
127 }
128 RTPHeader* header = new RTPHeader;
129 CopyToHeader(header);
130 header->payloadType = payload_ptr[0] & 0x7F;
131 headers->push_front(header);
132 return true;
133}
134
135void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
136 while (!headers->empty()) {
137 delete headers->front();
138 headers->pop_front();
139 }
140}
141
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000142bool Packet::ParseHeader(const RtpHeaderParser& parser) {
143 bool valid_header = parser.Parse(
144 payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
henrik.lundin7a2862a2017-06-01 07:41:11 -0700145 // Special case for dummy packets that have padding marked in the RTP header.
146 // This causes the RTP header parser to report failure, but is fine in this
147 // context.
148 const bool header_only_with_padding =
149 (header_.headerLength == packet_length_bytes_ &&
150 header_.paddingLength > 0);
151 if (!valid_header && !header_only_with_padding) {
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000152 return false;
153 }
154 assert(header_.headerLength <= packet_length_bytes_);
155 payload_ = &payload_memory_[header_.headerLength];
156 assert(packet_length_bytes_ >= header_.headerLength);
157 payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
henrik.lundind1a10a02016-08-24 10:58:54 -0700158 RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000159 assert(virtual_packet_length_bytes_ >= header_.headerLength);
160 virtual_payload_length_bytes_ =
161 virtual_packet_length_bytes_ - header_.headerLength;
162 return true;
163}
164
165void Packet::CopyToHeader(RTPHeader* destination) const {
Niels Möllera533e002019-03-26 13:14:30 +0100166 *destination = header_;
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000167}
168
169} // namespace test
170} // namespace webrtc