blob: 8c8fa0e79ad62d47cff2dc3dfd0b6c9fc70e260e [file] [log] [blame]
danilchap1edb7ab2016-04-20 05:25:10 -07001/*
2 * Copyright (c) 2016 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 "webrtc/modules/rtp_rtcp/source/rtp_packet.h"
12
13#include <cstring>
14
15#include "webrtc/base/checks.h"
16#include "webrtc/base/logging.h"
17#include "webrtc/base/random.h"
18#include "webrtc/common_types.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
21#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
22
23namespace webrtc {
24namespace rtp {
25namespace {
26constexpr size_t kFixedHeaderSize = 12;
27constexpr uint8_t kRtpVersion = 2;
28constexpr uint16_t kOneByteExtensionId = 0xBEDE;
29constexpr size_t kOneByteHeaderSize = 1;
30constexpr size_t kDefaultPacketSize = 1500;
31} // namespace
32// 0 1 2 3
33// 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
34// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35// |V=2|P|X| CC |M| PT | sequence number |
36// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37// | timestamp |
38// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39// | synchronization source (SSRC) identifier |
40// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
41// | Contributing source (CSRC) identifiers |
42// | .... |
43// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
44// |One-byte eXtensions id = 0xbede| length in 32bits |
45// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46// | Extensions |
47// | .... |
48// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
49// | Payload |
50// | .... : padding... |
51// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52// | padding | Padding size |
53// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54Packet::Packet(const ExtensionManager* extensions)
55 : extensions_(extensions), buffer_(kDefaultPacketSize) {
56 Clear();
57}
58
59Packet::Packet(const ExtensionManager* extensions, size_t capacity)
60 : extensions_(extensions), buffer_(capacity) {
61 RTC_DCHECK_GE(capacity, kFixedHeaderSize);
62 Clear();
63}
64
65Packet::~Packet() {}
66
67void Packet::IdentifyExtensions(const ExtensionManager* extensions) {
68 RTC_DCHECK(extensions);
69 extensions_ = extensions;
70 for (size_t i = 0; i < num_extensions_; ++i) {
71 uint8_t id = data()[extension_entries_[i].offset - 1] >> 4;
72 extension_entries_[i].type = extensions_->GetType(id);
73 }
74}
75
76bool Packet::Parse(const uint8_t* buffer, size_t buffer_size) {
77 if (!ParseBuffer(buffer, buffer_size)) {
78 Clear();
79 return false;
80 }
danilchap1edb7ab2016-04-20 05:25:10 -070081 buffer_.SetData(buffer, buffer_size);
Danil Chapovalov31e4e802016-08-03 18:27:40 +020082 RTC_DCHECK_EQ(size(), buffer_size);
danilchap1edb7ab2016-04-20 05:25:10 -070083 return true;
84}
85
Danil Chapovalov31e4e802016-08-03 18:27:40 +020086bool Packet::Parse(rtc::CopyOnWriteBuffer buffer) {
87 if (!ParseBuffer(buffer.cdata(), buffer.size())) {
danilchap1edb7ab2016-04-20 05:25:10 -070088 Clear();
89 return false;
90 }
Danil Chapovalov31e4e802016-08-03 18:27:40 +020091 size_t buffer_size = buffer.size();
danilchap1edb7ab2016-04-20 05:25:10 -070092 buffer_ = std::move(buffer);
Danil Chapovalov31e4e802016-08-03 18:27:40 +020093 RTC_DCHECK_EQ(size(), buffer_size);
danilchap1edb7ab2016-04-20 05:25:10 -070094 return true;
95}
96
97bool Packet::Marker() const {
98 RTC_DCHECK_EQ(marker_, (data()[1] & 0x80) != 0);
99 return marker_;
100}
101
102uint8_t Packet::PayloadType() const {
103 RTC_DCHECK_EQ(payload_type_, data()[1] & 0x7f);
104 return payload_type_;
105}
106
107uint16_t Packet::SequenceNumber() const {
108 RTC_DCHECK_EQ(sequence_number_,
109 ByteReader<uint16_t>::ReadBigEndian(data() + 2));
110 return sequence_number_;
111}
112
113uint32_t Packet::Timestamp() const {
114 RTC_DCHECK_EQ(timestamp_, ByteReader<uint32_t>::ReadBigEndian(data() + 4));
115 return timestamp_;
116}
117
118uint32_t Packet::Ssrc() const {
119 RTC_DCHECK_EQ(ssrc_, ByteReader<uint32_t>::ReadBigEndian(data() + 8));
120 return ssrc_;
121}
122
123std::vector<uint32_t> Packet::Csrcs() const {
124 size_t num_csrc = data()[0] & 0x0F;
125 RTC_DCHECK_GE(capacity(), kFixedHeaderSize + num_csrc * 4);
126 std::vector<uint32_t> csrcs(num_csrc);
127 for (size_t i = 0; i < num_csrc; ++i) {
128 csrcs[i] =
129 ByteReader<uint32_t>::ReadBigEndian(&data()[kFixedHeaderSize + i * 4]);
130 }
131 return csrcs;
132}
133
134void Packet::GetHeader(RTPHeader* header) const {
135 header->markerBit = Marker();
136 header->payloadType = PayloadType();
137 header->sequenceNumber = SequenceNumber();
138 header->timestamp = Timestamp();
139 header->ssrc = Ssrc();
140 std::vector<uint32_t> csrcs = Csrcs();
141 header->numCSRCs = csrcs.size();
142 for (size_t i = 0; i < csrcs.size(); ++i) {
143 header->arrOfCSRCs[i] = csrcs[i];
144 }
145 header->paddingLength = padding_size();
146 header->headerLength = headers_size();
147 header->payload_type_frequency = 0;
148 header->extension.hasTransmissionTimeOffset =
149 GetExtension<TransmissionOffset>(
150 &header->extension.transmissionTimeOffset);
151 header->extension.hasAbsoluteSendTime =
152 GetExtension<AbsoluteSendTime>(&header->extension.absoluteSendTime);
153 header->extension.hasTransportSequenceNumber =
154 GetExtension<TransportSequenceNumber>(
155 &header->extension.transportSequenceNumber);
156 header->extension.hasAudioLevel = GetExtension<AudioLevel>(
157 &header->extension.voiceActivity, &header->extension.audioLevel);
158 header->extension.hasVideoRotation =
159 GetExtension<VideoOrientation>(&header->extension.videoRotation);
160}
161
162size_t Packet::headers_size() const {
163 return payload_offset_;
164}
165
166size_t Packet::payload_size() const {
167 return payload_size_;
168}
169
170size_t Packet::padding_size() const {
171 return padding_size_;
172}
173
174const uint8_t* Packet::payload() const {
175 return data() + payload_offset_;
176}
177
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200178rtc::CopyOnWriteBuffer Packet::Buffer() const {
179 return buffer_;
180}
181
danilchap1edb7ab2016-04-20 05:25:10 -0700182size_t Packet::capacity() const {
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200183 return buffer_.capacity();
danilchap1edb7ab2016-04-20 05:25:10 -0700184}
185
186size_t Packet::size() const {
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200187 size_t ret = payload_offset_ + payload_size_ + padding_size_;
188 RTC_DCHECK_EQ(buffer_.size(), ret);
189 return ret;
danilchap1edb7ab2016-04-20 05:25:10 -0700190}
191
192const uint8_t* Packet::data() const {
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200193 return buffer_.cdata();
danilchap1edb7ab2016-04-20 05:25:10 -0700194}
195
196size_t Packet::FreeCapacity() const {
197 return capacity() - size();
198}
199
200size_t Packet::MaxPayloadSize() const {
201 return capacity() - payload_offset_;
202}
203
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200204void Packet::CopyHeaderFrom(const Packet& packet) {
danilchap1edb7ab2016-04-20 05:25:10 -0700205 RTC_DCHECK_GE(capacity(), packet.headers_size());
206
207 marker_ = packet.marker_;
208 payload_type_ = packet.payload_type_;
209 sequence_number_ = packet.sequence_number_;
210 timestamp_ = packet.timestamp_;
211 ssrc_ = packet.ssrc_;
212 payload_offset_ = packet.payload_offset_;
213 num_extensions_ = packet.num_extensions_;
214 for (size_t i = 0; i < num_extensions_; ++i) {
215 extension_entries_[i] = packet.extension_entries_[i];
216 }
217 extensions_size_ = packet.extensions_size_;
218 buffer_.SetData(packet.data(), packet.headers_size());
219 // Reset payload and padding.
220 payload_size_ = 0;
221 padding_size_ = 0;
222}
223
224void Packet::SetMarker(bool marker_bit) {
225 marker_ = marker_bit;
226 if (marker_) {
227 WriteAt(1, data()[1] | 0x80);
228 } else {
229 WriteAt(1, data()[1] & 0x7F);
230 }
231}
232
233void Packet::SetPayloadType(uint8_t payload_type) {
234 RTC_DCHECK_LE(payload_type, 0x7Fu);
235 payload_type_ = payload_type;
236 WriteAt(1, (data()[1] & 0x80) | payload_type);
237}
238
239void Packet::SetSequenceNumber(uint16_t seq_no) {
240 sequence_number_ = seq_no;
241 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(2), seq_no);
242}
243
244void Packet::SetTimestamp(uint32_t timestamp) {
245 timestamp_ = timestamp;
246 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(4), timestamp);
247}
248
249void Packet::SetSsrc(uint32_t ssrc) {
250 ssrc_ = ssrc;
251 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(8), ssrc);
252}
253
254void Packet::SetCsrcs(const std::vector<uint32_t>& csrcs) {
255 RTC_DCHECK_EQ(num_extensions_, 0u);
256 RTC_DCHECK_EQ(payload_size_, 0u);
257 RTC_DCHECK_EQ(padding_size_, 0u);
258 RTC_DCHECK_LE(csrcs.size(), 0x0fu);
259 RTC_DCHECK_LE(kFixedHeaderSize + 4 * csrcs.size(), capacity());
260 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();
261 WriteAt(0, (data()[0] & 0xF0) | csrcs.size());
262 size_t offset = kFixedHeaderSize;
263 for (uint32_t csrc : csrcs) {
264 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc);
265 offset += 4;
266 }
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200267 buffer_.SetSize(payload_offset_);
danilchap1edb7ab2016-04-20 05:25:10 -0700268}
269
270uint8_t* Packet::AllocatePayload(size_t size_bytes) {
271 RTC_DCHECK_EQ(padding_size_, 0u);
272 if (payload_offset_ + size_bytes > capacity()) {
273 LOG(LS_WARNING) << "Cannot set payload, not enough space in buffer.";
274 return nullptr;
275 }
276 payload_size_ = size_bytes;
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200277 buffer_.SetSize(payload_offset_ + payload_size_);
danilchap1edb7ab2016-04-20 05:25:10 -0700278 return WriteAt(payload_offset_);
279}
280
281void Packet::SetPayloadSize(size_t size_bytes) {
282 RTC_DCHECK_EQ(padding_size_, 0u);
283 RTC_DCHECK_LE(size_bytes, payload_size_);
284 payload_size_ = size_bytes;
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200285 buffer_.SetSize(payload_offset_ + payload_size_);
danilchap1edb7ab2016-04-20 05:25:10 -0700286}
287
288bool Packet::SetPadding(uint8_t size_bytes, Random* random) {
289 RTC_DCHECK(random);
290 if (payload_offset_ + payload_size_ + size_bytes > capacity()) {
291 LOG(LS_WARNING) << "Cannot set padding size " << size_bytes << ", only "
292 << (capacity() - payload_offset_ - payload_size_)
293 << " bytes left in buffer.";
294 return false;
295 }
296 padding_size_ = size_bytes;
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200297 buffer_.SetSize(payload_offset_ + payload_size_ + padding_size_);
danilchap1edb7ab2016-04-20 05:25:10 -0700298 if (padding_size_ > 0) {
299 size_t padding_offset = payload_offset_ + payload_size_;
300 size_t padding_end = padding_offset + padding_size_;
301 for (size_t offset = padding_offset; offset < padding_end - 1; ++offset) {
302 WriteAt(offset, random->Rand<uint8_t>());
303 }
304 WriteAt(padding_end - 1, padding_size_);
305 WriteAt(0, data()[0] | 0x20); // Set padding bit.
306 } else {
307 WriteAt(0, data()[0] & ~0x20); // Clear padding bit.
308 }
309 return true;
310}
311
312void Packet::Clear() {
313 marker_ = false;
314 payload_type_ = 0;
315 sequence_number_ = 0;
316 timestamp_ = 0;
317 ssrc_ = 0;
318 payload_offset_ = kFixedHeaderSize;
319 payload_size_ = 0;
320 padding_size_ = 0;
321 num_extensions_ = 0;
322 extensions_size_ = 0;
323
324 memset(WriteAt(0), 0, kFixedHeaderSize);
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200325 buffer_.SetSize(kFixedHeaderSize);
danilchap1edb7ab2016-04-20 05:25:10 -0700326 WriteAt(0, kRtpVersion << 6);
327}
328
329bool Packet::ParseBuffer(const uint8_t* buffer, size_t size) {
330 if (size < kFixedHeaderSize) {
331 return false;
332 }
333 const uint8_t version = buffer[0] >> 6;
334 if (version != kRtpVersion) {
335 return false;
336 }
337 const bool has_padding = (buffer[0] & 0x20) != 0;
338 const bool has_extension = (buffer[0] & 0x10) != 0;
339 const uint8_t number_of_crcs = buffer[0] & 0x0f;
340 marker_ = (buffer[1] & 0x80) != 0;
341 payload_type_ = buffer[1] & 0x7f;
342
343 sequence_number_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]);
344 timestamp_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
345 ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
346 if (size < kFixedHeaderSize + number_of_crcs * 4) {
347 return false;
348 }
349 payload_offset_ = kFixedHeaderSize + number_of_crcs * 4;
350
351 if (has_padding) {
352 padding_size_ = buffer[size - 1];
353 if (padding_size_ == 0) {
354 LOG(LS_WARNING) << "Padding was set, but padding size is zero";
355 return false;
356 }
357 } else {
358 padding_size_ = 0;
359 }
360
361 num_extensions_ = 0;
362 extensions_size_ = 0;
363 if (has_extension) {
364 /* RTP header extension, RFC 3550.
365 0 1 2 3
366 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
367 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
368 | defined by profile | length |
369 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
370 | header extension |
371 | .... |
372 */
373 size_t extension_offset = payload_offset_ + 4;
374 if (extension_offset > size) {
375 return false;
376 }
377 uint16_t profile =
378 ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_]);
379 size_t extensions_capacity =
380 ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_ + 2]);
381 extensions_capacity *= 4;
382 if (extension_offset + extensions_capacity > size) {
383 return false;
384 }
385 if (profile != kOneByteExtensionId) {
386 LOG(LS_WARNING) << "Unsupported rtp extension " << profile;
387 } else {
388 constexpr uint8_t kPaddingId = 0;
389 constexpr uint8_t kReservedId = 15;
390 while (extensions_size_ + kOneByteHeaderSize < extensions_capacity) {
391 uint8_t id = buffer[extension_offset + extensions_size_] >> 4;
392 if (id == kReservedId) {
393 break;
394 } else if (id == kPaddingId) {
395 extensions_size_++;
396 continue;
397 }
398 uint8_t length =
399 1 + (buffer[extension_offset + extensions_size_] & 0xf);
400 extensions_size_ += kOneByteHeaderSize;
401 if (num_extensions_ >= kMaxExtensionHeaders) {
402 LOG(LS_WARNING) << "Too many extensions.";
403 return false;
404 }
405 extension_entries_[num_extensions_].type =
406 extensions_ ? extensions_->GetType(id)
407 : ExtensionManager::kInvalidType;
408 extension_entries_[num_extensions_].length = length;
409 extension_entries_[num_extensions_].offset =
410 extension_offset + extensions_size_;
411 num_extensions_++;
412 extensions_size_ += length;
413 }
414 }
415 payload_offset_ = extension_offset + extensions_capacity;
416 }
417
418 if (payload_offset_ + padding_size_ > size) {
419 return false;
420 }
421 payload_size_ = size - payload_offset_ - padding_size_;
422 return true;
423}
424
425bool Packet::FindExtension(ExtensionType type,
426 uint8_t length,
427 uint16_t* offset) const {
428 RTC_DCHECK(offset);
429 for (size_t i = 0; i < num_extensions_; ++i) {
430 if (extension_entries_[i].type == type) {
danilchap07ec26d2016-06-17 04:18:54 -0700431 if (length != extension_entries_[i].length) {
432 LOG(LS_WARNING) << "Length mismatch for extension '" << type
433 << "': expected " << static_cast<int>(length)
434 << ", received "
435 << static_cast<int>(extension_entries_[i].length);
436 return false;
437 }
danilchap1edb7ab2016-04-20 05:25:10 -0700438 *offset = extension_entries_[i].offset;
439 return true;
440 }
441 }
442 return false;
443}
444
445bool Packet::AllocateExtension(ExtensionType type,
446 uint8_t length,
447 uint16_t* offset) {
448 if (!extensions_) {
449 return false;
450 }
451 if (FindExtension(type, length, offset)) {
452 return true;
453 }
454
455 // Can't add new extension after payload/padding was set.
456 if (payload_size_ > 0) {
457 return false;
458 }
459 if (padding_size_ > 0) {
460 return false;
461 }
462
463 uint8_t extension_id = extensions_->GetId(type);
464 if (extension_id == ExtensionManager::kInvalidId) {
465 return false;
466 }
467 RTC_DCHECK_GT(length, 0u);
468 RTC_DCHECK_LE(length, 16u);
469
470 size_t num_csrc = data()[0] & 0x0F;
471 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
472 if (extensions_offset + extensions_size_ + kOneByteHeaderSize + length >
473 capacity()) {
474 LOG(LS_WARNING) << "Extension cannot be registered: "
475 "Not enough space left in buffer.";
476 return false;
477 }
478
479 uint16_t new_extensions_size =
480 extensions_size_ + kOneByteHeaderSize + length;
481 uint16_t extensions_words =
482 (new_extensions_size + 3) / 4; // Wrap up to 32bit.
483
484 // All checks passed, write down the extension.
485 if (num_extensions_ == 0) {
486 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4));
487 RTC_DCHECK_EQ(extensions_size_, 0);
488 WriteAt(0, data()[0] | 0x10); // Set extension bit.
489 // Profile specific ID always set to OneByteExtensionHeader.
490 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
491 kOneByteExtensionId);
492 }
493
494 WriteAt(extensions_offset + extensions_size_,
495 (extension_id << 4) | (length - 1));
496 RTC_DCHECK(num_extensions_ < kMaxExtensionHeaders);
497 extension_entries_[num_extensions_].type = type;
498 extension_entries_[num_extensions_].length = length;
499 *offset = extensions_offset + kOneByteHeaderSize + extensions_size_;
500 extension_entries_[num_extensions_].offset = *offset;
501 ++num_extensions_;
502 extensions_size_ = new_extensions_size;
503
504 // Update header length field.
505 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2),
506 extensions_words);
507 // Fill extension padding place with zeroes.
508 size_t extension_padding_size = 4 * extensions_words - extensions_size_;
509 memset(WriteAt(extensions_offset + extensions_size_), 0,
510 extension_padding_size);
511 payload_offset_ = extensions_offset + 4 * extensions_words;
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200512 buffer_.SetSize(payload_offset_);
danilchap1edb7ab2016-04-20 05:25:10 -0700513 return true;
514}
515
516uint8_t* Packet::WriteAt(size_t offset) {
517 return buffer_.data() + offset;
518}
519
520void Packet::WriteAt(size_t offset, uint8_t byte) {
521 buffer_.data()[offset] = byte;
522}
523
524} // namespace rtp
525} // namespace webrtc