| 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_extension_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_extension_len_(last_packet_extension_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 packet."; |
| 526 return; | 511 return; |
| 527 } | 512 } |
| 513 if (max_payload_length_ < PayloadDescriptorLengthMinusSsData(hdr_) + 1 + |
| 514 last_packet_extension_len_) { |
| 515 LOG(LS_ERROR) << "Payload header, extensions, and one payload byte won't " |
| 516 "fit in the last packet."; |
| 517 return; |
| 518 } |
| 519 // Payload, extensions and SS hdr data in the first packet together. |
| 520 size_t total_bytes = |
| 521 payload_size_ + last_packet_extension_len_ + SsDataLength(hdr_); |
| 522 // Accounting for VP9 headers of the same length in each packet. |
| 523 size_t capacity = |
| 524 max_payload_length_ - PayloadDescriptorLengthMinusSsData(hdr_); |
| 525 // Integer divisions rounding up. |
| 526 size_t num_packets = (total_bytes + capacity - 1) / capacity; |
| 527 size_t per_packet_data = (total_bytes + num_packets - 1) / num_packets; |
| 528 // Last smaller_packets packets are 1 byte smaller than the rest. |
| 529 size_t smaller_packets = num_packets - total_bytes % num_packets; |
| 530 // If all packets are the same size, we assume 0 packets are smaller. |
| 531 if (smaller_packets == num_packets) |
| 532 smaller_packets = 0; |
| 528 size_t bytes_processed = 0; | 533 size_t bytes_processed = 0; |
| 534 size_t packets_left = num_packets; |
| 529 while (bytes_processed < payload_size_) { | 535 while (bytes_processed < payload_size_) { |
| 536 if (packets_left == smaller_packets) |
| 537 per_packet_data--; |
| 538 size_t packet_bytes = per_packet_data; |
| 539 // First packet also has SS hdr data. |
| 540 if (bytes_processed == 0) |
| 541 packet_bytes -= SsDataLength(hdr_); |
| 530 size_t rem_bytes = payload_size_ - bytes_processed; | 542 size_t rem_bytes = payload_size_ - bytes_processed; |
| 531 size_t rem_payload_len = max_payload_length_ - | 543 if (packet_bytes >= rem_bytes) { |
| 532 (bytes_processed ? PayloadDescriptorLengthMinusSsData(hdr_) | 544 packet_bytes = rem_bytes; |
| 533 : PayloadDescriptorLength(hdr_)); | 545 // All payload will fit into pre-last packet. Leave at least one byte for |
| 534 | 546 // the last packet. Should only happen if extensions take at least half |
| 535 size_t packet_bytes = CalcNextSize(rem_payload_len, rem_bytes); | 547 // of available capacity. |
| 536 if (packet_bytes == 0) { | 548 if (packets_left == 2) { |
| 537 LOG(LS_ERROR) << "Failed to generate VP9 packets."; | 549 RTC_DCHECK(last_packet_extension_len_ >= capacity / 2); |
| 538 while (!packets_.empty()) | 550 packet_bytes--; |
| 539 packets_.pop(); | 551 } |
| 540 return; | |
| 541 } | 552 } |
| 542 QueuePacket(bytes_processed, packet_bytes, bytes_processed == 0, | 553 QueuePacket(bytes_processed, packet_bytes, bytes_processed == 0, |
| 543 rem_bytes == packet_bytes, &packets_); | 554 rem_bytes == packet_bytes, &packets_); |
| 555 packets_left--; |
| 544 bytes_processed += packet_bytes; | 556 bytes_processed += packet_bytes; |
| 557 // Last packet should have enough space for extensions. |
| 558 assert(packets_left > 0 || |
| 559 capacity - packet_bytes >= last_packet_extension_len_); |
| 545 } | 560 } |
| 546 assert(bytes_processed == payload_size_); | 561 assert(bytes_processed == payload_size_); |
| 547 } | 562 } |
| 548 | 563 |
| 549 bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet, bool* last_packet) { | 564 bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet) { |
| 550 RTC_DCHECK(packet); | 565 RTC_DCHECK(packet); |
| 551 RTC_DCHECK(last_packet); | |
| 552 if (packets_.empty()) { | 566 if (packets_.empty()) { |
| 553 return false; | 567 return false; |
| 554 } | 568 } |
| 555 PacketInfo packet_info = packets_.front(); | 569 PacketInfo packet_info = packets_.front(); |
| 556 packets_.pop(); | 570 packets_.pop(); |
| 557 | 571 |
| 558 if (!WriteHeaderAndPayload(packet_info, packet)) { | 572 if (!WriteHeaderAndPayload(packet_info, packet, packets_.empty())) { |
| 559 return false; | 573 return false; |
| 560 } | 574 } |
| 561 *last_packet = packets_.empty(); | |
| 562 packet->SetMarker(packets_.empty() && | 575 packet->SetMarker(packets_.empty() && |
| 563 (hdr_.spatial_idx == kNoSpatialIdx || | 576 (hdr_.spatial_idx == kNoSpatialIdx || |
| 564 hdr_.spatial_idx == hdr_.num_spatial_layers - 1)); | 577 hdr_.spatial_idx == hdr_.num_spatial_layers - 1)); |
| 565 return true; | 578 return true; |
| 566 } | 579 } |
| 567 | 580 |
| 568 // VP9 format: | 581 // VP9 format: |
| 569 // | 582 // |
| 570 // Payload descriptor for F = 1 (flexible mode) | 583 // Payload descriptor for F = 1 (flexible mode) |
| 571 // 0 1 2 3 4 5 6 7 | 584 // 0 1 2 3 4 5 6 7 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 595 // +-+-+-+-+-+-+-+-+ | 608 // +-+-+-+-+-+-+-+-+ |
| 596 // L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) | 609 // L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) |
| 597 // +-+-+-+-+-+-+-+-+ | 610 // +-+-+-+-+-+-+-+-+ |
| 598 // | TL0PICIDX | (CONDITIONALLY REQUIRED) | 611 // | TL0PICIDX | (CONDITIONALLY REQUIRED) |
| 599 // +-+-+-+-+-+-+-+-+ | 612 // +-+-+-+-+-+-+-+-+ |
| 600 // V: | SS | | 613 // V: | SS | |
| 601 // | .. | | 614 // | .. | |
| 602 // +-+-+-+-+-+-+-+-+ | 615 // +-+-+-+-+-+-+-+-+ |
| 603 | 616 |
| 604 bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info, | 617 bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info, |
| 605 RtpPacketToSend* packet) const { | 618 RtpPacketToSend* packet, |
| 606 uint8_t* buffer = packet->AllocatePayload(max_payload_length_); | 619 bool last) const { |
| 620 uint8_t* buffer = packet->AllocatePayload( |
| 621 last ? max_payload_length_ - last_packet_extension_len_ |
| 622 : max_payload_length_); |
| 607 RTC_DCHECK(buffer); | 623 RTC_DCHECK(buffer); |
| 608 size_t header_length; | 624 size_t header_length; |
| 609 if (!WriteHeader(packet_info, buffer, &header_length)) | 625 if (!WriteHeader(packet_info, buffer, &header_length)) |
| 610 return false; | 626 return false; |
| 611 | 627 |
| 612 // Copy payload data. | 628 // Copy payload data. |
| 613 memcpy(&buffer[header_length], | 629 memcpy(&buffer[header_length], |
| 614 &payload_[packet_info.payload_start_pos], packet_info.size); | 630 &payload_[packet_info.payload_start_pos], packet_info.size); |
| 615 | 631 |
| 616 packet->SetPayloadSize(header_length + packet_info.size); | 632 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) { | 753 if (parsed_payload->payload_length == 0) { |
| 738 LOG(LS_ERROR) << "Failed parsing VP9 payload data."; | 754 LOG(LS_ERROR) << "Failed parsing VP9 payload data."; |
| 739 return false; | 755 return false; |
| 740 } | 756 } |
| 741 parsed_payload->payload = | 757 parsed_payload->payload = |
| 742 payload + payload_length - parsed_payload->payload_length; | 758 payload + payload_length - parsed_payload->payload_length; |
| 743 | 759 |
| 744 return true; | 760 return true; |
| 745 } | 761 } |
| 746 } // namespace webrtc | 762 } // namespace webrtc |
| OLD | NEW |