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 "api/array_view.h"
14 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
15 #include "rtc_base/checks.h"
16 #include "rtc_base/copy_on_write_buffer.h"
17
18 namespace webrtc {
19 namespace test {
20
Packet(rtc::CopyOnWriteBuffer packet,size_t virtual_packet_length_bytes,double time_ms,const RtpHeaderExtensionMap * extension_map)21 Packet::Packet(rtc::CopyOnWriteBuffer packet,
22 size_t virtual_packet_length_bytes,
23 double time_ms,
24 const RtpHeaderExtensionMap* extension_map)
25 : packet_(std::move(packet)),
26 virtual_packet_length_bytes_(virtual_packet_length_bytes),
27 time_ms_(time_ms),
28 valid_header_(ParseHeader(extension_map)) {}
29
Packet(const RTPHeader & header,size_t virtual_packet_length_bytes,size_t virtual_payload_length_bytes,double time_ms)30 Packet::Packet(const RTPHeader& header,
31 size_t virtual_packet_length_bytes,
32 size_t virtual_payload_length_bytes,
33 double time_ms)
34 : header_(header),
35 virtual_packet_length_bytes_(virtual_packet_length_bytes),
36 virtual_payload_length_bytes_(virtual_payload_length_bytes),
37 time_ms_(time_ms),
38 valid_header_(true) {}
39
40 Packet::~Packet() = default;
41
ExtractRedHeaders(std::list<RTPHeader * > * headers) const42 bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
43 //
44 // 0 1 2 3
45 // 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
46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 // |1| block PT | timestamp offset | block length |
48 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 // |1| ... |
50 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 // |0| block PT |
52 // +-+-+-+-+-+-+-+-+
53 //
54
55 const uint8_t* payload_ptr = payload();
56 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes();
57
58 // Find all RED headers with the extension bit set to 1. That is, all headers
59 // but the last one.
60 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
61 RTPHeader* header = new RTPHeader;
62 CopyToHeader(header);
63 header->payloadType = payload_ptr[0] & 0x7F;
64 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
65 header->timestamp -= offset;
66 headers->push_front(header);
67 payload_ptr += 4;
68 }
69 // Last header.
70 RTC_DCHECK_LT(payload_ptr, payload_end_ptr);
71 if (payload_ptr >= payload_end_ptr) {
72 return false; // Payload too short.
73 }
74 RTPHeader* header = new RTPHeader;
75 CopyToHeader(header);
76 header->payloadType = payload_ptr[0] & 0x7F;
77 headers->push_front(header);
78 return true;
79 }
80
DeleteRedHeaders(std::list<RTPHeader * > * headers)81 void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
82 while (!headers->empty()) {
83 delete headers->front();
84 headers->pop_front();
85 }
86 }
87
ParseHeader(const RtpHeaderExtensionMap * extension_map)88 bool Packet::ParseHeader(const RtpHeaderExtensionMap* extension_map) {
89 // Use RtpPacketReceived instead of RtpPacket because former already has a
90 // converter into legacy RTPHeader.
91 webrtc::RtpPacketReceived rtp_packet(extension_map);
92
93 // Because of the special case of dummy packets that have padding marked in
94 // the RTP header, but do not have rtp payload with the padding size, handle
95 // padding manually. Regular RTP packet parser reports failure, but it is fine
96 // in this context.
97 bool padding = (packet_[0] & 0b0010'0000);
98 size_t padding_size = 0;
99 if (padding) {
100 // Clear the padding bit to prevent failure when rtp payload is omited.
101 rtc::CopyOnWriteBuffer packet(packet_);
102 packet.MutableData()[0] &= ~0b0010'0000;
103 if (!rtp_packet.Parse(std::move(packet))) {
104 return false;
105 }
106 if (rtp_packet.payload_size() > 0) {
107 padding_size = rtp_packet.data()[rtp_packet.size() - 1];
108 }
109 if (padding_size > rtp_packet.payload_size()) {
110 return false;
111 }
112 } else {
113 if (!rtp_packet.Parse(packet_)) {
114 return false;
115 }
116 }
117 rtp_payload_ = rtc::MakeArrayView(packet_.data() + rtp_packet.headers_size(),
118 rtp_packet.payload_size() - padding_size);
119 rtp_packet.GetHeader(&header_);
120
121 RTC_CHECK_GE(virtual_packet_length_bytes_, rtp_packet.size());
122 RTC_DCHECK_GE(virtual_packet_length_bytes_, rtp_packet.headers_size());
123 virtual_payload_length_bytes_ =
124 virtual_packet_length_bytes_ - rtp_packet.headers_size();
125 return true;
126 }
127
CopyToHeader(RTPHeader * destination) const128 void Packet::CopyToHeader(RTPHeader* destination) const {
129 *destination = header_;
130 }
131
132 } // namespace test
133 } // namespace webrtc
134