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 #include "modules/audio_coding/neteq/tools/packet.h"
12
13 #include <string.h>
14
15 #include <memory>
16
17 #include "modules/rtp_rtcp/source/rtp_utility.h"
18 #include "rtc_base/checks.h"
19
20 namespace webrtc {
21 namespace test {
22
23 using webrtc::RtpUtility::RtpHeaderParser;
24
Packet(uint8_t * packet_memory,size_t allocated_bytes,size_t virtual_packet_length_bytes,double time_ms,const RtpUtility::RtpHeaderParser & parser,const RtpHeaderExtensionMap * extension_map)25 Packet::Packet(uint8_t* packet_memory,
26 size_t allocated_bytes,
27 size_t virtual_packet_length_bytes,
28 double time_ms,
29 const RtpUtility::RtpHeaderParser& parser,
30 const RtpHeaderExtensionMap* extension_map /*= nullptr*/)
31 : payload_memory_(packet_memory),
32 packet_length_bytes_(allocated_bytes),
33 virtual_packet_length_bytes_(virtual_packet_length_bytes),
34 virtual_payload_length_bytes_(0),
35 time_ms_(time_ms),
36 valid_header_(ParseHeader(parser, extension_map)) {}
37
Packet(const RTPHeader & header,size_t virtual_packet_length_bytes,size_t virtual_payload_length_bytes,double time_ms)38 Packet::Packet(const RTPHeader& header,
39 size_t virtual_packet_length_bytes,
40 size_t virtual_payload_length_bytes,
41 double time_ms)
42 : header_(header),
43 virtual_packet_length_bytes_(virtual_packet_length_bytes),
44 virtual_payload_length_bytes_(virtual_payload_length_bytes),
45 time_ms_(time_ms),
46 valid_header_(true) {}
47
Packet(uint8_t * packet_memory,size_t allocated_bytes,double time_ms)48 Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
49 : Packet(packet_memory,
50 allocated_bytes,
51 allocated_bytes,
52 time_ms,
53 RtpUtility::RtpHeaderParser(packet_memory, allocated_bytes)) {}
54
Packet(uint8_t * packet_memory,size_t allocated_bytes,size_t virtual_packet_length_bytes,double time_ms)55 Packet::Packet(uint8_t* packet_memory,
56 size_t allocated_bytes,
57 size_t virtual_packet_length_bytes,
58 double time_ms)
59 : Packet(packet_memory,
60 allocated_bytes,
61 virtual_packet_length_bytes,
62 time_ms,
63 RtpUtility::RtpHeaderParser(packet_memory, allocated_bytes)) {}
64
65 Packet::~Packet() = default;
66
ExtractRedHeaders(std::list<RTPHeader * > * headers) const67 bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
68 //
69 // 0 1 2 3
70 // 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
71 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 // |1| block PT | timestamp offset | block length |
73 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74 // |1| ... |
75 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76 // |0| block PT |
77 // +-+-+-+-+-+-+-+-+
78 //
79
80 RTC_DCHECK(payload_);
81 const uint8_t* payload_ptr = payload_;
82 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
83
84 // Find all RED headers with the extension bit set to 1. That is, all headers
85 // but the last one.
86 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
87 RTPHeader* header = new RTPHeader;
88 CopyToHeader(header);
89 header->payloadType = payload_ptr[0] & 0x7F;
90 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
91 header->timestamp -= offset;
92 headers->push_front(header);
93 payload_ptr += 4;
94 }
95 // Last header.
96 RTC_DCHECK_LT(payload_ptr, payload_end_ptr);
97 if (payload_ptr >= payload_end_ptr) {
98 return false; // Payload too short.
99 }
100 RTPHeader* header = new RTPHeader;
101 CopyToHeader(header);
102 header->payloadType = payload_ptr[0] & 0x7F;
103 headers->push_front(header);
104 return true;
105 }
106
DeleteRedHeaders(std::list<RTPHeader * > * headers)107 void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
108 while (!headers->empty()) {
109 delete headers->front();
110 headers->pop_front();
111 }
112 }
113
ParseHeader(const RtpHeaderParser & parser,const RtpHeaderExtensionMap * extension_map)114 bool Packet::ParseHeader(const RtpHeaderParser& parser,
115 const RtpHeaderExtensionMap* extension_map) {
116 bool valid_header = parser.Parse(&header_, extension_map);
117
118 // Special case for dummy packets that have padding marked in the RTP header.
119 // This causes the RTP header parser to report failure, but is fine in this
120 // context.
121 const bool header_only_with_padding =
122 (header_.headerLength == packet_length_bytes_ &&
123 header_.paddingLength > 0);
124 if (!valid_header && !header_only_with_padding) {
125 return false;
126 }
127 RTC_DCHECK_LE(header_.headerLength, packet_length_bytes_);
128 payload_ = &payload_memory_[header_.headerLength];
129 RTC_DCHECK_GE(packet_length_bytes_, header_.headerLength);
130 payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
131 RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
132 RTC_DCHECK_GE(virtual_packet_length_bytes_, header_.headerLength);
133 virtual_payload_length_bytes_ =
134 virtual_packet_length_bytes_ - header_.headerLength;
135 return true;
136 }
137
CopyToHeader(RTPHeader * destination) const138 void Packet::CopyToHeader(RTPHeader* destination) const {
139 *destination = header_;
140 }
141
142 } // namespace test
143 } // namespace webrtc
144