OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 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 #define RETURN_FALSE_ON_ERROR(x) \ | 23 #define RETURN_FALSE_ON_ERROR(x) \ |
24 if (!(x)) { \ | 24 if (!(x)) { \ |
25 return false; \ | 25 return false; \ |
26 } | 26 } |
27 | 27 |
28 namespace webrtc { | 28 namespace webrtc { |
29 namespace { | 29 namespace { |
30 // Length of VP9 payload descriptors' fixed part. | 30 // Length of VP9 payload descriptors' fixed part. |
31 const size_t kFixedPayloadDescriptorBytes = 1; | 31 const size_t kFixedPayloadDescriptorBytes = 1; |
32 | 32 |
33 // Packet fragmentation mode. If true, packets are split into (almost) equal | |
34 // sizes. Otherwise, as many bytes as possible are fit into one packet. | |
35 const bool kBalancedMode = true; | |
36 | |
37 const uint32_t kReservedBitValue0 = 0; | 33 const uint32_t kReservedBitValue0 = 0; |
38 | 34 |
39 uint8_t TemporalIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { | 35 uint8_t TemporalIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { |
40 return (hdr.temporal_idx == kNoTemporalIdx) ? def : hdr.temporal_idx; | 36 return (hdr.temporal_idx == kNoTemporalIdx) ? def : hdr.temporal_idx; |
41 } | 37 } |
42 | 38 |
43 uint8_t SpatialIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { | 39 uint8_t SpatialIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { |
44 return (hdr.spatial_idx == kNoSpatialIdx) ? def : hdr.spatial_idx; | 40 return (hdr.spatial_idx == kNoSpatialIdx) ? def : hdr.spatial_idx; |
45 } | 41 } |
46 | 42 |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
455 vp9->gof.num_ref_pics[i] = r; | 451 vp9->gof.num_ref_pics[i] = r; |
456 | 452 |
457 for (uint8_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) { | 453 for (uint8_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) { |
458 uint8_t p_diff; | 454 uint8_t p_diff; |
459 RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&p_diff)); | 455 RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&p_diff)); |
460 vp9->gof.pid_diff[i][p] = p_diff; | 456 vp9->gof.pid_diff[i][p] = p_diff; |
461 } | 457 } |
462 } | 458 } |
463 return true; | 459 return true; |
464 } | 460 } |
465 | |
466 // Gets the size of next payload chunk to send. Returns 0 on error. | |
467 size_t CalcNextSize(size_t max_length, size_t rem_bytes) { | |
468 if (max_length == 0 || rem_bytes == 0) { | |
469 return 0; | |
470 } | |
471 if (kBalancedMode) { | |
472 size_t num_frags = std::ceil(static_cast<double>(rem_bytes) / max_length); | |
473 return static_cast<size_t>( | |
474 static_cast<double>(rem_bytes) / num_frags + 0.5); | |
475 } | |
476 return max_length >= rem_bytes ? rem_bytes : max_length; | |
477 } | |
478 } // namespace | 461 } // namespace |
479 | 462 |
480 | |
481 RtpPacketizerVp9::RtpPacketizerVp9(const RTPVideoHeaderVP9& hdr, | 463 RtpPacketizerVp9::RtpPacketizerVp9(const RTPVideoHeaderVP9& hdr, |
482 size_t max_payload_length) | 464 size_t max_payload_length, |
465 size_t last_packet_reduction_len) | |
483 : hdr_(hdr), | 466 : hdr_(hdr), |
484 max_payload_length_(max_payload_length), | 467 max_payload_length_(max_payload_length), |
485 payload_(nullptr), | 468 payload_(nullptr), |
486 payload_size_(0) { | 469 payload_size_(0), |
487 } | 470 last_packet_reduction_len_(last_packet_reduction_len) {} |
488 | 471 |
489 RtpPacketizerVp9::~RtpPacketizerVp9() { | 472 RtpPacketizerVp9::~RtpPacketizerVp9() { |
490 } | 473 } |
491 | 474 |
492 ProtectionType RtpPacketizerVp9::GetProtectionType() { | 475 ProtectionType RtpPacketizerVp9::GetProtectionType() { |
493 bool protect = | 476 bool protect = |
494 hdr_.temporal_idx == 0 || hdr_.temporal_idx == kNoTemporalIdx; | 477 hdr_.temporal_idx == 0 || hdr_.temporal_idx == kNoTemporalIdx; |
495 return protect ? kProtectedPacket : kUnprotectedPacket; | 478 return protect ? kProtectedPacket : kUnprotectedPacket; |
496 } | 479 } |
497 | 480 |
498 StorageType RtpPacketizerVp9::GetStorageType(uint32_t retransmission_settings) { | 481 StorageType RtpPacketizerVp9::GetStorageType(uint32_t retransmission_settings) { |
499 StorageType storage = kAllowRetransmission; | 482 StorageType storage = kAllowRetransmission; |
500 if (hdr_.temporal_idx == 0 && | 483 if (hdr_.temporal_idx == 0 && |
501 !(retransmission_settings & kRetransmitBaseLayer)) { | 484 !(retransmission_settings & kRetransmitBaseLayer)) { |
502 storage = kDontRetransmit; | 485 storage = kDontRetransmit; |
503 } else if (hdr_.temporal_idx != kNoTemporalIdx && hdr_.temporal_idx > 0 && | 486 } else if (hdr_.temporal_idx != kNoTemporalIdx && hdr_.temporal_idx > 0 && |
504 !(retransmission_settings & kRetransmitHigherLayers)) { | 487 !(retransmission_settings & kRetransmitHigherLayers)) { |
505 storage = kDontRetransmit; | 488 storage = kDontRetransmit; |
506 } | 489 } |
507 return storage; | 490 return storage; |
508 } | 491 } |
509 | 492 |
510 std::string RtpPacketizerVp9::ToString() { | 493 std::string RtpPacketizerVp9::ToString() { |
511 return "RtpPacketizerVp9"; | 494 return "RtpPacketizerVp9"; |
512 } | 495 } |
513 | 496 |
514 void RtpPacketizerVp9::SetPayloadData( | 497 size_t RtpPacketizerVp9::SetPayloadData( |
515 const uint8_t* payload, | 498 const uint8_t* payload, |
516 size_t payload_size, | 499 size_t payload_size, |
517 const RTPFragmentationHeader* fragmentation) { | 500 const RTPFragmentationHeader* fragmentation) { |
518 payload_ = payload; | 501 payload_ = payload; |
519 payload_size_ = payload_size; | 502 payload_size_ = payload_size; |
520 GeneratePackets(); | 503 GeneratePackets(); |
504 return packets_.size(); | |
521 } | 505 } |
522 | 506 |
507 // Splits payload in minimal number of roughly equal in size packets. | |
523 void RtpPacketizerVp9::GeneratePackets() { | 508 void RtpPacketizerVp9::GeneratePackets() { |
524 if (max_payload_length_ < PayloadDescriptorLength(hdr_) + 1) { | 509 if (max_payload_length_ < PayloadDescriptorLength(hdr_) + 1) { |
525 LOG(LS_ERROR) << "Payload header and one payload byte won't fit."; | 510 LOG(LS_ERROR) << "Payload header and one payload byte won't fit in the " |
511 "first packet."; | |
526 return; | 512 return; |
527 } | 513 } |
514 if (max_payload_length_ < PayloadDescriptorLengthMinusSsData(hdr_) + 1 + | |
515 last_packet_reduction_len_) { | |
516 LOG(LS_ERROR) << "Payload header and one payload byte won't fit in the last" | |
517 " packet."; | |
518 return; | |
519 } | |
520 if (payload_size_ == 1 && | |
521 max_payload_length_ < | |
522 PayloadDescriptorLength(hdr_) + 1 + last_packet_reduction_len_) { | |
523 LOG(LS_ERROR) << "Can't fit header and payload into single packet, but " | |
524 "payload size is one: no way to generate packets with " | |
525 "nonzero payload."; | |
526 return; | |
527 } | |
528 | |
529 // Instead of making last packet smaller, we pretend that we must write | |
530 // additional data into it. We account for this virtual payload while | |
531 // calculating packets number and sizes. We also pretend that all packets | |
532 // headers are the same length and extra SS header data in the fits packet | |
533 // is also treated as a payload here. | |
534 | |
535 size_t ss_data_len = SsDataLength(hdr_); | |
536 // Payload, virtual payload and SS hdr data in the first packet together. | |
537 size_t total_bytes = ss_data_len + payload_size_ + last_packet_reduction_len_; | |
538 // Now all packets will have the same lenght of vp9 headers. | |
539 size_t per_packet_capacity = | |
540 max_payload_length_ - PayloadDescriptorLengthMinusSsData(hdr_); | |
541 // Integer division rounding up. | |
542 size_t num_packets = | |
543 (total_bytes + per_packet_capacity - 1) / per_packet_capacity; | |
544 // Average rounded down. | |
545 size_t per_packet_bytes = total_bytes / num_packets; | |
546 // Several last packets are 1 byte smaller than the rest. | |
danilchap
2017/05/23 15:55:03
1 byte larger
ilnik
2017/05/23 16:14:30
Done.
| |
547 // i.e. if 14 bytes were split between 4 packets, it would be 3+3+4+4. | |
548 size_t num_larger_packets = total_bytes % num_packets; | |
528 size_t bytes_processed = 0; | 549 size_t bytes_processed = 0; |
550 size_t num_packets_left = num_packets; | |
529 while (bytes_processed < payload_size_) { | 551 while (bytes_processed < payload_size_) { |
552 if (num_packets_left == num_larger_packets) | |
553 ++per_packet_bytes; | |
554 size_t packet_bytes = per_packet_bytes; | |
555 // First packet also has SS hdr data. | |
556 if (bytes_processed == 0) { | |
557 // Must write at least one byte of the real payload to the packet. | |
558 if (packet_bytes > ss_data_len) { | |
559 packet_bytes -= ss_data_len; | |
560 } else { | |
561 packet_bytes = 1; | |
562 } | |
563 } | |
530 size_t rem_bytes = payload_size_ - bytes_processed; | 564 size_t rem_bytes = payload_size_ - bytes_processed; |
531 size_t rem_payload_len = max_payload_length_ - | 565 if (packet_bytes >= rem_bytes) { |
532 (bytes_processed ? PayloadDescriptorLengthMinusSsData(hdr_) | 566 // All remaining payload fits into this packet. |
533 : PayloadDescriptorLength(hdr_)); | 567 packet_bytes = rem_bytes; |
534 | 568 // If this is the penultimate packet, leave at least 1 byte of payload for |
535 size_t packet_bytes = CalcNextSize(rem_payload_len, rem_bytes); | 569 // the last packet. |
536 if (packet_bytes == 0) { | 570 if (num_packets_left == 2) |
537 LOG(LS_ERROR) << "Failed to generate VP9 packets."; | 571 --packet_bytes; |
538 while (!packets_.empty()) | |
539 packets_.pop(); | |
540 return; | |
541 } | 572 } |
542 QueuePacket(bytes_processed, packet_bytes, bytes_processed == 0, | 573 QueuePacket(bytes_processed, packet_bytes, bytes_processed == 0, |
543 rem_bytes == packet_bytes, &packets_); | 574 rem_bytes == packet_bytes, &packets_); |
575 --num_packets_left; | |
544 bytes_processed += packet_bytes; | 576 bytes_processed += packet_bytes; |
577 // Last packet should be smaller | |
578 RTC_DCHECK(num_packets_left > 0 || | |
579 per_packet_capacity >= | |
580 packet_bytes + last_packet_reduction_len_); | |
545 } | 581 } |
546 assert(bytes_processed == payload_size_); | 582 RTC_CHECK_EQ(bytes_processed, payload_size_); |
547 } | 583 } |
548 | 584 |
549 bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet, bool* last_packet) { | 585 bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet) { |
550 RTC_DCHECK(packet); | 586 RTC_DCHECK(packet); |
551 RTC_DCHECK(last_packet); | |
552 if (packets_.empty()) { | 587 if (packets_.empty()) { |
553 return false; | 588 return false; |
554 } | 589 } |
555 PacketInfo packet_info = packets_.front(); | 590 PacketInfo packet_info = packets_.front(); |
556 packets_.pop(); | 591 packets_.pop(); |
557 | 592 |
558 if (!WriteHeaderAndPayload(packet_info, packet)) { | 593 if (!WriteHeaderAndPayload(packet_info, packet, packets_.empty())) { |
559 return false; | 594 return false; |
560 } | 595 } |
561 *last_packet = packets_.empty(); | |
562 packet->SetMarker(packets_.empty() && | 596 packet->SetMarker(packets_.empty() && |
563 (hdr_.spatial_idx == kNoSpatialIdx || | 597 (hdr_.spatial_idx == kNoSpatialIdx || |
564 hdr_.spatial_idx == hdr_.num_spatial_layers - 1)); | 598 hdr_.spatial_idx == hdr_.num_spatial_layers - 1)); |
565 return true; | 599 return true; |
566 } | 600 } |
567 | 601 |
568 // VP9 format: | 602 // VP9 format: |
569 // | 603 // |
570 // Payload descriptor for F = 1 (flexible mode) | 604 // Payload descriptor for F = 1 (flexible mode) |
571 // 0 1 2 3 4 5 6 7 | 605 // 0 1 2 3 4 5 6 7 |
(...skipping 23 matching lines...) Expand all Loading... | |
595 // +-+-+-+-+-+-+-+-+ | 629 // +-+-+-+-+-+-+-+-+ |
596 // L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) | 630 // L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) |
597 // +-+-+-+-+-+-+-+-+ | 631 // +-+-+-+-+-+-+-+-+ |
598 // | TL0PICIDX | (CONDITIONALLY REQUIRED) | 632 // | TL0PICIDX | (CONDITIONALLY REQUIRED) |
599 // +-+-+-+-+-+-+-+-+ | 633 // +-+-+-+-+-+-+-+-+ |
600 // V: | SS | | 634 // V: | SS | |
601 // | .. | | 635 // | .. | |
602 // +-+-+-+-+-+-+-+-+ | 636 // +-+-+-+-+-+-+-+-+ |
603 | 637 |
604 bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info, | 638 bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info, |
605 RtpPacketToSend* packet) const { | 639 RtpPacketToSend* packet, |
606 uint8_t* buffer = packet->AllocatePayload(max_payload_length_); | 640 bool last) const { |
641 uint8_t* buffer = packet->AllocatePayload( | |
642 last ? max_payload_length_ - last_packet_reduction_len_ | |
643 : max_payload_length_); | |
607 RTC_DCHECK(buffer); | 644 RTC_DCHECK(buffer); |
608 size_t header_length; | 645 size_t header_length; |
609 if (!WriteHeader(packet_info, buffer, &header_length)) | 646 if (!WriteHeader(packet_info, buffer, &header_length)) |
610 return false; | 647 return false; |
611 | 648 |
612 // Copy payload data. | 649 // Copy payload data. |
613 memcpy(&buffer[header_length], | 650 memcpy(&buffer[header_length], |
614 &payload_[packet_info.payload_start_pos], packet_info.size); | 651 &payload_[packet_info.payload_start_pos], packet_info.size); |
615 | 652 |
616 packet->SetPayloadSize(header_length + packet_info.size); | 653 packet->SetPayloadSize(header_length + packet_info.size); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
737 if (parsed_payload->payload_length == 0) { | 774 if (parsed_payload->payload_length == 0) { |
738 LOG(LS_ERROR) << "Failed parsing VP9 payload data."; | 775 LOG(LS_ERROR) << "Failed parsing VP9 payload data."; |
739 return false; | 776 return false; |
740 } | 777 } |
741 parsed_payload->payload = | 778 parsed_payload->payload = |
742 payload + payload_length - parsed_payload->payload_length; | 779 payload + payload_length - parsed_payload->payload_length; |
743 | 780 |
744 return true; | 781 return true; |
745 } | 782 } |
746 } // namespace webrtc | 783 } // namespace webrtc |
OLD | NEW |