Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_packet.cc

Issue 2789773004: Add functions to get/set rtp header extension by id. (Closed)
Patch Set: nits Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 12 matching lines...) Expand all
23 23
24 namespace webrtc { 24 namespace webrtc {
25 namespace rtp { 25 namespace rtp {
26 namespace { 26 namespace {
27 constexpr size_t kFixedHeaderSize = 12; 27 constexpr size_t kFixedHeaderSize = 12;
28 constexpr uint8_t kRtpVersion = 2; 28 constexpr uint8_t kRtpVersion = 2;
29 constexpr uint16_t kOneByteExtensionId = 0xBEDE; 29 constexpr uint16_t kOneByteExtensionId = 0xBEDE;
30 constexpr size_t kOneByteHeaderSize = 1; 30 constexpr size_t kOneByteHeaderSize = 1;
31 constexpr size_t kDefaultPacketSize = 1500; 31 constexpr size_t kDefaultPacketSize = 1500;
32 } // namespace 32 } // namespace
33
34 constexpr size_t Packet::kMaxExtensionHeaders;
35 constexpr int Packet::kMinExtensionId;
36 constexpr int Packet::kMaxExtensionId;
37
33 // 0 1 2 3 38 // 0 1 2 3
34 // 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 39 // 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
35 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 // |V=2|P|X| CC |M| PT | sequence number | 41 // |V=2|P|X| CC |M| PT | sequence number |
37 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 // | timestamp | 43 // | timestamp |
39 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 // | synchronization source (SSRC) identifier | 45 // | synchronization source (SSRC) identifier |
41 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 46 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
42 // | Contributing source (CSRC) identifiers | 47 // | Contributing source (CSRC) identifiers |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size(); 271 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();
267 WriteAt(0, (data()[0] & 0xF0) | csrcs.size()); 272 WriteAt(0, (data()[0] & 0xF0) | csrcs.size());
268 size_t offset = kFixedHeaderSize; 273 size_t offset = kFixedHeaderSize;
269 for (uint32_t csrc : csrcs) { 274 for (uint32_t csrc : csrcs) {
270 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc); 275 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc);
271 offset += 4; 276 offset += 4;
272 } 277 }
273 buffer_.SetSize(payload_offset_); 278 buffer_.SetSize(payload_offset_);
274 } 279 }
275 280
281 bool Packet::HasRawExtension(int id) const {
282 RTC_DCHECK_GE(id, kMinExtensionId);
283 RTC_DCHECK_LE(id, kMaxExtensionId);
284 return extension_entries_[id - 1].offset != 0;
285 }
286
287 rtc::ArrayView<const uint8_t> Packet::GetRawExtension(int id) const {
288 RTC_DCHECK_GE(id, kMinExtensionId);
289 RTC_DCHECK_LE(id, kMaxExtensionId);
290 const ExtensionInfo& extension = extension_entries_[id - 1];
291 if (extension.offset == 0)
292 return nullptr;
293 return rtc::MakeArrayView(data() + extension.offset, extension.length);
294 }
295
296 bool Packet::SetRawExtension(int id, rtc::ArrayView<const uint8_t> data) {
297 auto buffer = AllocateRawExtension(id, data.size());
298 if (buffer.empty())
299 return false;
300 RTC_DCHECK_EQ(buffer.size(), data.size());
301 memcpy(buffer.data(), data.data(), data.size());
302 return true;
303 }
304
305 rtc::ArrayView<uint8_t> Packet::AllocateRawExtension(int id, size_t length) {
306 RTC_DCHECK_GE(id, kMinExtensionId);
307 RTC_DCHECK_LE(id, kMaxExtensionId);
308 RTC_DCHECK_GE(length, 1);
309 RTC_DCHECK_LE(length, 16);
310
311 ExtensionInfo* extension_entry = &extension_entries_[id - 1];
312 if (extension_entry->offset != 0) {
313 // Extension already reserved. Check if same length is used.
314 if (extension_entry->length == length)
315 return rtc::MakeArrayView(WriteAt(extension_entry->offset), length);
316
317 LOG(LS_ERROR) << "Length mismatch for extension id " << id << " type "
318 << static_cast<int>(extension_entry->type) << ": expected "
319 << static_cast<int>(extension_entry->length) << ". received "
320 << length;
321 return nullptr;
322 }
323 if (payload_size_ > 0) {
324 LOG(LS_ERROR) << "Can't add new extension id " << id
325 << " after payload was set.";
326 return nullptr;
327 }
328 if (padding_size_ > 0) {
329 LOG(LS_ERROR) << "Can't add new extension id " << id
330 << " after padding was set.";
331 return nullptr;
332 }
333
334 size_t num_csrc = data()[0] & 0x0F;
335 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
336 size_t new_extensions_size = extensions_size_ + kOneByteHeaderSize + length;
337 if (extensions_offset + new_extensions_size > capacity()) {
338 LOG(LS_ERROR)
339 << "Extension cannot be registered: Not enough space left in buffer.";
340 return nullptr;
341 }
342
343 // All checks passed, write down the extension headers.
344 if (extensions_size_ == 0) {
345 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4));
346 WriteAt(0, data()[0] | 0x10); // Set extension bit.
347 // Profile specific ID always set to OneByteExtensionHeader.
348 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
349 kOneByteExtensionId);
350 }
351
352 WriteAt(extensions_offset + extensions_size_, (id << 4) | (length - 1));
353
354 extension_entry->offset =
355 extensions_offset + extensions_size_ + kOneByteHeaderSize;
356 extension_entry->length = length;
357 extensions_size_ = new_extensions_size;
358
359 // Update header length field.
360 uint16_t extensions_words = (extensions_size_ + 3) / 4; // Wrap up to 32bit.
361 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2),
362 extensions_words);
363 // Fill extension padding place with zeroes.
364 size_t extension_padding_size = 4 * extensions_words - extensions_size_;
365 memset(WriteAt(extensions_offset + extensions_size_), 0,
366 extension_padding_size);
367 payload_offset_ = extensions_offset + 4 * extensions_words;
368 buffer_.SetSize(payload_offset_);
369 return rtc::MakeArrayView(WriteAt(extension_entry->offset), length);
370 }
371
276 uint8_t* Packet::AllocatePayload(size_t size_bytes) { 372 uint8_t* Packet::AllocatePayload(size_t size_bytes) {
277 // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause 373 // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause
278 // reallocation and memcpy. Keeping just header reduces memcpy size. 374 // reallocation and memcpy. Keeping just header reduces memcpy size.
279 SetPayloadSize(0); 375 SetPayloadSize(0);
280 return SetPayloadSize(size_bytes); 376 return SetPayloadSize(size_bytes);
281 } 377 }
282 378
283 uint8_t* Packet::SetPayloadSize(size_t size_bytes) { 379 uint8_t* Packet::SetPayloadSize(size_t size_bytes) {
284 RTC_DCHECK_EQ(padding_size_, 0); 380 RTC_DCHECK_EQ(padding_size_, 0);
285 if (payload_offset_ + size_bytes > capacity()) { 381 if (payload_offset_ + size_bytes > capacity()) {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 << ", received " << static_cast<int>(extension.length); 549 << ", received " << static_cast<int>(extension.length);
454 return false; 550 return false;
455 } 551 }
456 *offset = extension.offset; 552 *offset = extension.offset;
457 return true; 553 return true;
458 } 554 }
459 } 555 }
460 return false; 556 return false;
461 } 557 }
462 558
463 bool Packet::AllocateExtension(ExtensionType type, 559 rtc::ArrayView<uint8_t> Packet::AllocateExtension(ExtensionType type,
464 uint8_t length, 560 size_t length) {
465 uint16_t* offset) {
466 uint8_t extension_id = ExtensionManager::kInvalidId;
467 ExtensionInfo* extension_entry = nullptr;
468 for (size_t i = 0; i < kMaxExtensionHeaders; ++i) { 561 for (size_t i = 0; i < kMaxExtensionHeaders; ++i) {
469 if (extension_entries_[i].type == type) { 562 if (extension_entries_[i].type == type) {
470 extension_id = i + 1; 563 int extension_id = i + 1;
471 extension_entry = &extension_entries_[i]; 564 return AllocateRawExtension(extension_id, length);
472 break;
473 } 565 }
474 } 566 }
475 567 // Extension not registered.
476 if (!extension_entry) // Extension not registered. 568 return nullptr;
477 return false;
478
479 if (extension_entry->length != 0) { // Already allocated.
480 if (length != extension_entry->length) {
481 LOG(LS_WARNING) << "Length mismatch for extension '" << type
482 << "': expected " << static_cast<int>(length)
483 << ", received "
484 << static_cast<int>(extension_entry->length);
485 return false;
486 }
487 *offset = extension_entry->offset;
488 return true;
489 }
490
491 // Can't add new extension after payload/padding was set.
492 if (payload_size_ > 0) {
493 return false;
494 }
495 if (padding_size_ > 0) {
496 return false;
497 }
498
499 RTC_DCHECK_GT(length, 0);
500 RTC_DCHECK_LE(length, 16);
501
502 size_t num_csrc = data()[0] & 0x0F;
503 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
504 if (extensions_offset + extensions_size_ + kOneByteHeaderSize + length >
505 capacity()) {
506 LOG(LS_WARNING) << "Extension cannot be registered: "
507 "Not enough space left in buffer.";
508 return false;
509 }
510
511 uint16_t new_extensions_size =
512 extensions_size_ + kOneByteHeaderSize + length;
513 uint16_t extensions_words =
514 (new_extensions_size + 3) / 4; // Wrap up to 32bit.
515
516 // All checks passed, write down the extension.
517 if (extensions_size_ == 0) {
518 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4));
519 WriteAt(0, data()[0] | 0x10); // Set extension bit.
520 // Profile specific ID always set to OneByteExtensionHeader.
521 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
522 kOneByteExtensionId);
523 }
524
525 WriteAt(extensions_offset + extensions_size_,
526 (extension_id << 4) | (length - 1));
527
528 extension_entry->length = length;
529 *offset = extensions_offset + kOneByteHeaderSize + extensions_size_;
530 extension_entry->offset = *offset;
531 extensions_size_ = new_extensions_size;
532
533 // Update header length field.
534 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2),
535 extensions_words);
536 // Fill extension padding place with zeroes.
537 size_t extension_padding_size = 4 * extensions_words - extensions_size_;
538 memset(WriteAt(extensions_offset + extensions_size_), 0,
539 extension_padding_size);
540 payload_offset_ = extensions_offset + 4 * extensions_words;
541 buffer_.SetSize(payload_offset_);
542 return true;
543 } 569 }
544 570
545 uint8_t* Packet::WriteAt(size_t offset) { 571 uint8_t* Packet::WriteAt(size_t offset) {
546 return buffer_.data() + offset; 572 return buffer_.data() + offset;
547 } 573 }
548 574
549 void Packet::WriteAt(size_t offset, uint8_t byte) { 575 void Packet::WriteAt(size_t offset, uint8_t byte) {
550 buffer_.data()[offset] = byte; 576 buffer_.data()[offset] = byte;
551 } 577 }
552 578
553 } // namespace rtp 579 } // namespace rtp
554 } // namespace webrtc 580 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_packet.h ('k') | webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698