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