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