OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |