blob: 0ed1be1b0288e5e683f1d910f3333381ce699a59 [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
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000011#include "webrtc/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
henrik.lundind1a10a02016-08-24 10:58:54 -070017#include "webrtc/base/checks.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010018#include "webrtc/modules/include/module_common_types.h"
19#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000020
21namespace webrtc {
22namespace test {
23
24Packet::Packet(uint8_t* packet_memory,
25 size_t allocated_bytes,
26 double time_ms,
27 const RtpHeaderParser& parser)
28 : payload_memory_(packet_memory),
29 payload_(NULL),
30 packet_length_bytes_(allocated_bytes),
31 payload_length_bytes_(0),
32 virtual_packet_length_bytes_(allocated_bytes),
33 virtual_payload_length_bytes_(0),
34 time_ms_(time_ms) {
35 valid_header_ = ParseHeader(parser);
36}
37
38Packet::Packet(uint8_t* packet_memory,
39 size_t allocated_bytes,
40 size_t virtual_packet_length_bytes,
41 double time_ms,
42 const RtpHeaderParser& parser)
43 : payload_memory_(packet_memory),
44 payload_(NULL),
45 packet_length_bytes_(allocated_bytes),
46 payload_length_bytes_(0),
47 virtual_packet_length_bytes_(virtual_packet_length_bytes),
48 virtual_payload_length_bytes_(0),
49 time_ms_(time_ms) {
50 valid_header_ = ParseHeader(parser);
51}
52
53Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
54 : payload_memory_(packet_memory),
55 payload_(NULL),
56 packet_length_bytes_(allocated_bytes),
57 payload_length_bytes_(0),
58 virtual_packet_length_bytes_(allocated_bytes),
59 virtual_payload_length_bytes_(0),
60 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080061 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000062 valid_header_ = ParseHeader(*parser);
63}
64
65Packet::Packet(uint8_t* packet_memory,
66 size_t allocated_bytes,
67 size_t virtual_packet_length_bytes,
68 double time_ms)
69 : payload_memory_(packet_memory),
70 payload_(NULL),
71 packet_length_bytes_(allocated_bytes),
72 payload_length_bytes_(0),
73 virtual_packet_length_bytes_(virtual_packet_length_bytes),
74 virtual_payload_length_bytes_(0),
75 time_ms_(time_ms) {
kwiberg2d0c3322016-02-14 09:28:33 -080076 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000077 valid_header_ = ParseHeader(*parser);
78}
79
kwibergb8e56ee2016-08-29 06:37:33 -070080Packet::~Packet() = default;
81
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000082bool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
83 //
84 // 0 1 2 3
85 // 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
86 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 // |1| block PT | timestamp offset | block length |
88 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 // |1| ... |
90 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 // |0| block PT |
92 // +-+-+-+-+-+-+-+-+
93 //
94
95 assert(payload_);
96 const uint8_t* payload_ptr = payload_;
97 const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
98
99 // Find all RED headers with the extension bit set to 1. That is, all headers
100 // but the last one.
101 while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
102 RTPHeader* header = new RTPHeader;
103 CopyToHeader(header);
104 header->payloadType = payload_ptr[0] & 0x7F;
105 uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
106 header->timestamp -= offset;
107 headers->push_front(header);
108 payload_ptr += 4;
109 }
110 // Last header.
111 assert(payload_ptr < payload_end_ptr);
112 if (payload_ptr >= payload_end_ptr) {
113 return false; // Payload too short.
114 }
115 RTPHeader* header = new RTPHeader;
116 CopyToHeader(header);
117 header->payloadType = payload_ptr[0] & 0x7F;
118 headers->push_front(header);
119 return true;
120}
121
122void Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
123 while (!headers->empty()) {
124 delete headers->front();
125 headers->pop_front();
126 }
127}
128
henrik.lundin@webrtc.org1c839122014-08-11 12:29:38 +0000129void Packet::ConvertHeader(WebRtcRTPHeader* copy_to) const {
130 memcpy(&copy_to->header, &header_, sizeof(header_));
131 copy_to->frameType = kAudioFrameSpeech;
132 copy_to->type.Audio.numEnergy = 0;
133 copy_to->type.Audio.channel = 1;
134 copy_to->type.Audio.isCNG = false;
135}
136
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000137bool Packet::ParseHeader(const RtpHeaderParser& parser) {
138 bool valid_header = parser.Parse(
139 payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
140 assert(valid_header);
141 if (!valid_header) {
142 return false;
143 }
144 assert(header_.headerLength <= packet_length_bytes_);
145 payload_ = &payload_memory_[header_.headerLength];
146 assert(packet_length_bytes_ >= header_.headerLength);
147 payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
henrik.lundind1a10a02016-08-24 10:58:54 -0700148 RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000149 assert(virtual_packet_length_bytes_ >= header_.headerLength);
150 virtual_payload_length_bytes_ =
151 virtual_packet_length_bytes_ - header_.headerLength;
152 return true;
153}
154
155void Packet::CopyToHeader(RTPHeader* destination) const {
156 destination->markerBit = header_.markerBit;
157 destination->payloadType = header_.payloadType;
158 destination->sequenceNumber = header_.sequenceNumber;
159 destination->timestamp = header_.timestamp;
160 destination->ssrc = header_.ssrc;
161 destination->numCSRCs = header_.numCSRCs;
162 destination->paddingLength = header_.paddingLength;
163 destination->headerLength = header_.headerLength;
164 destination->payload_type_frequency = header_.payload_type_frequency;
165 memcpy(&destination->arrOfCSRCs,
166 &header_.arrOfCSRCs,
167 sizeof(header_.arrOfCSRCs));
168 memcpy(
169 &destination->extension, &header_.extension, sizeof(header_.extension));
170}
171
172} // namespace test
173} // namespace webrtc