| 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 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 | 391 |
| 392 UnwrapPictureIds(frame); | 392 UnwrapPictureIds(frame); |
| 393 } | 393 } |
| 394 | 394 |
| 395 RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9( | 395 RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9( |
| 396 RtpFrameObject* frame) { | 396 RtpFrameObject* frame) { |
| 397 rtc::Optional<RTPVideoTypeHeader> rtp_codec_header = frame->GetCodecHeader(); | 397 rtc::Optional<RTPVideoTypeHeader> rtp_codec_header = frame->GetCodecHeader(); |
| 398 RTC_DCHECK(rtp_codec_header); | 398 RTC_DCHECK(rtp_codec_header); |
| 399 const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9; | 399 const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9; |
| 400 | 400 |
| 401 bool old_frame = Vp9PidTl0Fix(*frame, &rtp_codec_header->VP9.picture_id, | |
| 402 &rtp_codec_header->VP9.tl0_pic_idx); | |
| 403 if (old_frame) | |
| 404 return kDrop; | |
| 405 | |
| 406 if (codec_header.picture_id == kNoPictureId || | 401 if (codec_header.picture_id == kNoPictureId || |
| 407 codec_header.temporal_idx == kNoTemporalIdx) { | 402 codec_header.temporal_idx == kNoTemporalIdx) { |
| 408 return ManageFrameGeneric(std::move(frame), codec_header.picture_id); | 403 return ManageFrameGeneric(std::move(frame), codec_header.picture_id); |
| 409 } | 404 } |
| 410 | 405 |
| 411 frame->spatial_layer = codec_header.spatial_idx; | 406 frame->spatial_layer = codec_header.spatial_idx; |
| 412 frame->inter_layer_predicted = codec_header.inter_layer_predicted; | 407 frame->inter_layer_predicted = codec_header.inter_layer_predicted; |
| 413 frame->picture_id = codec_header.picture_id % kPicIdLength; | 408 frame->picture_id = codec_header.picture_id % kPicIdLength; |
| 414 | 409 |
| 415 if (last_unwrap_ == -1) | 410 if (last_unwrap_ == -1) |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 uint16_t diff = MinDiff<uint16_t, kPicIdLength>(unwrap_truncated, picture_id); | 597 uint16_t diff = MinDiff<uint16_t, kPicIdLength>(unwrap_truncated, picture_id); |
| 603 | 598 |
| 604 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) | 599 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) |
| 605 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); | 600 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); |
| 606 else | 601 else |
| 607 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); | 602 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); |
| 608 | 603 |
| 609 return last_unwrap_; | 604 return last_unwrap_; |
| 610 } | 605 } |
| 611 | 606 |
| 612 bool RtpFrameReferenceFinder::Vp9PidTl0Fix(const RtpFrameObject& frame, | |
| 613 int16_t* picture_id, | |
| 614 int16_t* tl0_pic_idx) { | |
| 615 const int kTl0PicIdLength = 256; | |
| 616 const uint8_t kMaxPidDiff = 128; | |
| 617 | |
| 618 // We are currently receiving VP9 without PID, nothing to fix. | |
| 619 if (*picture_id == kNoPictureId) | |
| 620 return false; | |
| 621 | |
| 622 // If |vp9_fix_jump_timestamp_| != -1 then a jump has occurred recently. | |
| 623 if (vp9_fix_jump_timestamp_ != -1) { | |
| 624 // If this frame has a timestamp older than |vp9_fix_jump_timestamp_| then | |
| 625 // this frame is old (more previous than the frame where we detected the | |
| 626 // jump) and should be dropped. | |
| 627 if (AheadOf<uint32_t>(vp9_fix_jump_timestamp_, frame.timestamp)) | |
| 628 return true; | |
| 629 | |
| 630 // After 60 seconds, reset |vp9_fix_jump_timestamp_| in order to not | |
| 631 // discard old frames when the timestamp wraps. | |
| 632 int diff_ms = | |
| 633 ForwardDiff<uint32_t>(vp9_fix_jump_timestamp_, frame.timestamp) / 90; | |
| 634 if (diff_ms > 60 * 1000) | |
| 635 vp9_fix_jump_timestamp_ = -1; | |
| 636 } | |
| 637 | |
| 638 // Update |vp9_fix_last_timestamp_| with the most recent timestamp. | |
| 639 if (vp9_fix_last_timestamp_ == -1) | |
| 640 vp9_fix_last_timestamp_ = frame.timestamp; | |
| 641 if (AheadOf<uint32_t>(frame.timestamp, vp9_fix_last_timestamp_)) | |
| 642 vp9_fix_last_timestamp_ = frame.timestamp; | |
| 643 | |
| 644 uint16_t fixed_pid = Add<kPicIdLength>(*picture_id, vp9_fix_pid_offset_); | |
| 645 if (vp9_fix_last_picture_id_ == -1) | |
| 646 vp9_fix_last_picture_id_ = *picture_id; | |
| 647 | |
| 648 int16_t fixed_tl0 = kNoTl0PicIdx; | |
| 649 if (*tl0_pic_idx != kNoTl0PicIdx) { | |
| 650 fixed_tl0 = Add<kTl0PicIdLength>(*tl0_pic_idx, vp9_fix_tl0_pic_idx_offset_); | |
| 651 // Update |vp9_fix_last_tl0_pic_idx_| with the most recent tl0 pic index. | |
| 652 if (vp9_fix_last_tl0_pic_idx_ == -1) | |
| 653 vp9_fix_last_tl0_pic_idx_ = *tl0_pic_idx; | |
| 654 if (AheadOf<uint8_t>(fixed_tl0, vp9_fix_last_tl0_pic_idx_)) | |
| 655 vp9_fix_last_tl0_pic_idx_ = fixed_tl0; | |
| 656 } | |
| 657 | |
| 658 bool has_jumped = DetectVp9PicIdJump(fixed_pid, fixed_tl0, frame.timestamp); | |
| 659 if (!has_jumped) | |
| 660 has_jumped = DetectVp9Tl0PicIdxJump(fixed_tl0, frame.timestamp); | |
| 661 | |
| 662 if (has_jumped) { | |
| 663 // First we calculate the offset to get to the previous picture id, and then | |
| 664 // we add kMaxPid to avoid accidently referencing any previous | |
| 665 // frames that was inserted into the FrameBuffer. | |
| 666 vp9_fix_pid_offset_ = ForwardDiff<uint16_t, kPicIdLength>( | |
| 667 *picture_id, vp9_fix_last_picture_id_); | |
| 668 vp9_fix_pid_offset_ += kMaxPidDiff; | |
| 669 | |
| 670 fixed_pid = Add<kPicIdLength>(*picture_id, vp9_fix_pid_offset_); | |
| 671 vp9_fix_last_picture_id_ = fixed_pid; | |
| 672 vp9_fix_jump_timestamp_ = frame.timestamp; | |
| 673 gof_info_.clear(); | |
| 674 | |
| 675 if (fixed_tl0 != kNoTl0PicIdx) { | |
| 676 vp9_fix_tl0_pic_idx_offset_ = | |
| 677 ForwardDiff<uint8_t>(*tl0_pic_idx, vp9_fix_last_tl0_pic_idx_); | |
| 678 vp9_fix_tl0_pic_idx_offset_ += kMaxGofSaved; | |
| 679 fixed_tl0 = | |
| 680 Add<kTl0PicIdLength>(*tl0_pic_idx, vp9_fix_tl0_pic_idx_offset_); | |
| 681 vp9_fix_last_tl0_pic_idx_ = fixed_tl0; | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 // Update |vp9_fix_last_picture_id_| with the most recent picture id. | |
| 686 if (AheadOf<uint16_t, kPicIdLength>(fixed_pid, vp9_fix_last_picture_id_)) | |
| 687 vp9_fix_last_picture_id_ = fixed_pid; | |
| 688 | |
| 689 *picture_id = fixed_pid; | |
| 690 *tl0_pic_idx = fixed_tl0; | |
| 691 | |
| 692 return false; | |
| 693 } | |
| 694 | |
| 695 bool RtpFrameReferenceFinder::DetectVp9PicIdJump(int fixed_pid, | |
| 696 int fixed_tl0, | |
| 697 uint32_t timestamp) const { | |
| 698 // Test if there has been a jump backwards in the picture id. | |
| 699 if (AheadOrAt<uint32_t>(timestamp, vp9_fix_last_timestamp_) && | |
| 700 AheadOf<uint16_t, kPicIdLength>(vp9_fix_last_picture_id_, fixed_pid)) { | |
| 701 return true; | |
| 702 } | |
| 703 | |
| 704 // Test if we have jumped forward too much. The reason we have to do this | |
| 705 // is because the FrameBuffer holds history of old frames and inserting | |
| 706 // frames with a much advanced picture id can result in the frame buffer | |
| 707 // holding more than half of the interval of picture ids. | |
| 708 if (AheadOrAt<uint32_t>(timestamp, vp9_fix_last_timestamp_) && | |
| 709 ForwardDiff<uint16_t, kPicIdLength>(vp9_fix_last_picture_id_, fixed_pid) > | |
| 710 128) { | |
| 711 return true; | |
| 712 } | |
| 713 | |
| 714 // Special case where the picture id jump forward but not by much and the | |
| 715 // tl0 jumps to the id of an already saved gof for that id. In order to | |
| 716 // detect this we check if the picture id span over the length of the GOF. | |
| 717 if (fixed_tl0 != kNoTl0PicIdx) { | |
| 718 auto info_it = gof_info_.find(fixed_tl0); | |
| 719 if (info_it != gof_info_.end()) { | |
| 720 int last_pid_gof_idx_0 = | |
| 721 Subtract<kPicIdLength>(info_it->second.last_picture_id, | |
| 722 info_it->second.last_picture_id % | |
| 723 info_it->second.gof->num_frames_in_gof); | |
| 724 int pif_gof_end = Add<kPicIdLength>( | |
| 725 last_pid_gof_idx_0, info_it->second.gof->num_frames_in_gof); | |
| 726 if (AheadOf<uint16_t, kPicIdLength>(fixed_pid, pif_gof_end)) | |
| 727 return true; | |
| 728 } | |
| 729 } | |
| 730 | |
| 731 return false; | |
| 732 } | |
| 733 | |
| 734 bool RtpFrameReferenceFinder::DetectVp9Tl0PicIdxJump(int fixed_tl0, | |
| 735 uint32_t timestamp) const { | |
| 736 if (fixed_tl0 != kNoTl0PicIdx) { | |
| 737 // Test if there has been a jump backwards in tl0 pic index. | |
| 738 if (AheadOrAt<uint32_t>(timestamp, vp9_fix_last_timestamp_) && | |
| 739 AheadOf<uint8_t>(vp9_fix_last_tl0_pic_idx_, fixed_tl0)) { | |
| 740 return true; | |
| 741 } | |
| 742 | |
| 743 // Test if there has been a jump forward. If the jump forward results | |
| 744 // in the tl0 pic index for this frame to be considered smaller than the | |
| 745 // smallest item in |gof_info_| then we have jumped forward far enough to | |
| 746 // wrap. | |
| 747 if (!gof_info_.empty() && | |
| 748 AheadOf<uint8_t>(gof_info_.begin()->first, fixed_tl0)) { | |
| 749 return true; | |
| 750 } | |
| 751 } | |
| 752 return false; | |
| 753 } | |
| 754 | |
| 755 } // namespace video_coding | 607 } // namespace video_coding |
| 756 } // namespace webrtc | 608 } // namespace webrtc |
| OLD | NEW |