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

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: . 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;
nisse-webrtc 2017/04/03 09:38:00 Why is this needed? (And not part of this cl, bu
danilchap 2017/04/03 10:57:00 In theory - to make program well-formed. In practi
nisse-webrtc 2017/04/03 11:21:19 The FAQ entry talks about static const, but here w
danilchap 2017/04/03 12:10:53 longer story: you can get away without this constr
35
33 // 0 1 2 3 36 // 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 37 // 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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 38 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 // |V=2|P|X| CC |M| PT | sequence number | 39 // |V=2|P|X| CC |M| PT | sequence number |
37 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 // | timestamp | 41 // | timestamp |
39 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 // | synchronization source (SSRC) identifier | 43 // | synchronization source (SSRC) identifier |
41 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 44 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
42 // | Contributing source (CSRC) identifiers | 45 // | Contributing source (CSRC) identifiers |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size(); 269 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();
267 WriteAt(0, (data()[0] & 0xF0) | csrcs.size()); 270 WriteAt(0, (data()[0] & 0xF0) | csrcs.size());
268 size_t offset = kFixedHeaderSize; 271 size_t offset = kFixedHeaderSize;
269 for (uint32_t csrc : csrcs) { 272 for (uint32_t csrc : csrcs) {
270 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc); 273 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc);
271 offset += 4; 274 offset += 4;
272 } 275 }
273 buffer_.SetSize(payload_offset_); 276 buffer_.SetSize(payload_offset_);
274 } 277 }
275 278
279 bool Packet::HasRawExtension(int id) const {
280 RTC_DCHECK_GT(id, 0);
nisse-webrtc 2017/04/03 09:38:00 I think it's unusual and confusing with a exclusiv
danilchap 2017/04/03 10:57:00 Good point. It is also bad idea to use kMaxExtensi
281 RTC_DCHECK_LE(id, kMaxExtensionHeaders);
282 return extension_entries_[id - 1].offset != 0;
283 }
284
285 rtc::ArrayView<const uint8_t> Packet::GetRawExtension(int id) const {
286 RTC_DCHECK_GT(id, 0);
287 RTC_DCHECK_LE(id, kMaxExtensionHeaders);
288 const ExtensionInfo& extension = extension_entries_[id - 1];
289 if (extension.offset == 0)
290 return nullptr;
291 return rtc::MakeArrayView(data() + extension.offset, extension.length);
292 }
293
294 bool Packet::SetRawExtension(int id, rtc::ArrayView<const uint8_t> data) {
295 auto buffer = AllocateRawExtension(id, data.size());
296 if (buffer.empty())
297 return false;
298 RTC_DCHECK_EQ(buffer.size(), data.size());
299 memcpy(buffer.data(), data.data(), data.size());
300 return true;
301 }
302
303 rtc::ArrayView<uint8_t> Packet::AllocateRawExtension(int id, size_t length) {
304 RTC_DCHECK_GT(id, 0);
305 RTC_DCHECK_LE(id, kMaxExtensionHeaders);
306 RTC_DCHECK_GT(length, 0);
307 RTC_DCHECK_LE(length, 16);
308
309 ExtensionInfo* extension_entry = &extension_entries_[id - 1];
310 if (extension_entry->offset != 0) {
311 // Extension already reserved. Check if same length is used.
312 if (extension_entry->length == length)
313 return rtc::MakeArrayView(WriteAt(extension_entry->offset), length);
314
315 LOG(LS_ERROR) << "Length mismatch for extension id " << id << " type "
316 << static_cast<int>(extension_entry->type) << ": expected "
317 << static_cast<int>(extension_entry->length) << ". received "
318 << length;
319 return nullptr;
320 }
321 if (payload_size_ > 0) {
322 LOG(LS_ERROR) << "Can't add new extension id " << id
323 << " after payload was set.";
324 return nullptr;
325 }
326 if (padding_size_ > 0) {
327 LOG(LS_ERROR) << "Can't add new extension id " << id
328 << " after padding was set.";
329 return nullptr;
330 }
331
332 size_t num_csrc = data()[0] & 0x0F;
333 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
334 size_t new_extensions_size = extensions_size_ + kOneByteHeaderSize + length;
335 if (extensions_offset + new_extensions_size > capacity()) {
336 LOG(LS_ERROR)
337 << "Extension cannot be registered: Not enough space left in buffer.";
338 return nullptr;
339 }
340
341 // All checks passed, write down the extension headers.
342 if (extensions_size_ == 0) {
343 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4));
344 WriteAt(0, data()[0] | 0x10); // Set extension bit.
345 // Profile specific ID always set to OneByteExtensionHeader.
346 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
347 kOneByteExtensionId);
348 }
349
350 WriteAt(extensions_offset + extensions_size_, (id << 4) | (length - 1));
351
352 extension_entry->offset =
353 extensions_offset + extensions_size_ + kOneByteHeaderSize;
354 extension_entry->length = length;
355 extensions_size_ = new_extensions_size;
356
357 // Update header length field.
358 uint16_t extensions_words = (extensions_size_ + 3) / 4; // Wrap up to 32bit.
359 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2),
360 extensions_words);
361 // Fill extension padding place with zeroes.
362 size_t extension_padding_size = 4 * extensions_words - extensions_size_;
363 memset(WriteAt(extensions_offset + extensions_size_), 0,
364 extension_padding_size);
365 payload_offset_ = extensions_offset + 4 * extensions_words;
366 buffer_.SetSize(payload_offset_);
367 return rtc::MakeArrayView(WriteAt(extension_entry->offset), length);
368 }
369
276 uint8_t* Packet::AllocatePayload(size_t size_bytes) { 370 uint8_t* Packet::AllocatePayload(size_t size_bytes) {
277 // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause 371 // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause
278 // reallocation and memcpy. Keeping just header reduces memcpy size. 372 // reallocation and memcpy. Keeping just header reduces memcpy size.
279 SetPayloadSize(0); 373 SetPayloadSize(0);
280 return SetPayloadSize(size_bytes); 374 return SetPayloadSize(size_bytes);
281 } 375 }
282 376
283 uint8_t* Packet::SetPayloadSize(size_t size_bytes) { 377 uint8_t* Packet::SetPayloadSize(size_t size_bytes) {
284 RTC_DCHECK_EQ(padding_size_, 0); 378 RTC_DCHECK_EQ(padding_size_, 0);
285 if (payload_offset_ + size_bytes > capacity()) { 379 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); 547 << ", received " << static_cast<int>(extension.length);
454 return false; 548 return false;
455 } 549 }
456 *offset = extension.offset; 550 *offset = extension.offset;
457 return true; 551 return true;
458 } 552 }
459 } 553 }
460 return false; 554 return false;
461 } 555 }
462 556
463 bool Packet::AllocateExtension(ExtensionType type, 557 bool Packet::AllocateExtension(ExtensionType type,
nisse-webrtc 2017/04/03 09:38:00 For consistency, add an AllocateExtension method w
danilchap 2017/04/03 10:57:00 this is a private function, so can just replace it
464 uint8_t length, 558 uint8_t length,
465 uint16_t* offset) { 559 uint16_t* offset) {
466 uint8_t extension_id = ExtensionManager::kInvalidId;
467 ExtensionInfo* extension_entry = nullptr;
468 for (size_t i = 0; i < kMaxExtensionHeaders; ++i) { 560 for (size_t i = 0; i < kMaxExtensionHeaders; ++i) {
469 if (extension_entries_[i].type == type) { 561 if (extension_entries_[i].type == type) {
470 extension_id = i + 1; 562 int extension_id = i + 1;
471 extension_entry = &extension_entries_[i]; 563 auto buffer = AllocateRawExtension(extension_id, length);
472 break; 564 if (buffer.empty())
565 return false;
566 *offset = buffer.data() - WriteAt(0);
567 return true;
473 } 568 }
474 } 569 }
475 570 // Extension not registered.
476 if (!extension_entry) // Extension not registered. 571 return false;
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 } 572 }
544 573
545 uint8_t* Packet::WriteAt(size_t offset) { 574 uint8_t* Packet::WriteAt(size_t offset) {
546 return buffer_.data() + offset; 575 return buffer_.data() + offset;
547 } 576 }
548 577
549 void Packet::WriteAt(size_t offset, uint8_t byte) { 578 void Packet::WriteAt(size_t offset, uint8_t byte) {
550 buffer_.data()[offset] = byte; 579 buffer_.data()[offset] = byte;
551 } 580 }
552 581
553 } // namespace rtp 582 } // namespace rtp
554 } // namespace webrtc 583 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698