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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
364 } | 364 } |
365 | 365 |
366 void RtpFrameReferenceFinder::ManageFrameVp9( | 366 void RtpFrameReferenceFinder::ManageFrameVp9( |
367 std::unique_ptr<RtpFrameObject> frame) { | 367 std::unique_ptr<RtpFrameObject> frame) { |
368 rtc::Optional<RTPVideoTypeHeader> rtp_codec_header = frame->GetCodecHeader(); | 368 rtc::Optional<RTPVideoTypeHeader> rtp_codec_header = frame->GetCodecHeader(); |
369 if (!rtp_codec_header) | 369 if (!rtp_codec_header) |
370 return; | 370 return; |
371 | 371 |
372 const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9; | 372 const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9; |
373 | 373 |
374 bool old_frame = Vp9PidTl0Fix(*frame, &rtp_codec_header->VP9.picture_id, | |
375 &rtp_codec_header->VP9.tl0_pic_idx); | |
376 if (old_frame) | |
377 return; | |
378 | |
374 if (codec_header.picture_id == kNoPictureId || | 379 if (codec_header.picture_id == kNoPictureId || |
375 codec_header.temporal_idx == kNoTemporalIdx) { | 380 codec_header.temporal_idx == kNoTemporalIdx) { |
376 ManageFrameGeneric(std::move(frame), codec_header.picture_id); | 381 ManageFrameGeneric(std::move(frame), codec_header.picture_id); |
377 return; | 382 return; |
378 } | 383 } |
379 | 384 |
380 frame->spatial_layer = codec_header.spatial_idx; | 385 frame->spatial_layer = codec_header.spatial_idx; |
381 frame->inter_layer_predicted = codec_header.inter_layer_predicted; | 386 frame->inter_layer_predicted = codec_header.inter_layer_predicted; |
382 frame->picture_id = codec_header.picture_id % kPicIdLength; | 387 frame->picture_id = codec_header.picture_id % kPicIdLength; |
383 | 388 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 uint16_t diff = MinDiff<uint16_t, kPicIdLength>(unwrap_truncated, picture_id); | 583 uint16_t diff = MinDiff<uint16_t, kPicIdLength>(unwrap_truncated, picture_id); |
579 | 584 |
580 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) | 585 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) |
581 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); | 586 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); |
582 else | 587 else |
583 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); | 588 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); |
584 | 589 |
585 return last_unwrap_; | 590 return last_unwrap_; |
586 } | 591 } |
587 | 592 |
593 bool RtpFrameReferenceFinder::Vp9PidTl0Fix(const RtpFrameObject& frame, | |
stefan-webrtc
2016/11/14 12:00:26
I think we'll have to add tests to make sure these
philipel
2016/11/14 15:31:04
Done.
| |
594 int16_t* picture_id, | |
595 int16_t* tl0_pic_idx) { | |
596 // We are currently receiving VP9 without PID, nothing to fix. | |
597 if (*picture_id == kNoPictureId) | |
598 return false; | |
599 | |
600 // If |vp9_fix_jump_timestamp_| != -1 then a jump has occurred recently. | |
601 if (vp9_fix_jump_timestamp_ != -1) { | |
602 // If this frame has a timestamp older than |vp9_fix_jump_timestamp_| then | |
603 // this frame is old (more previous than the frame where we detected the | |
604 // jump) and should be dropped. | |
605 if (AheadOf<uint32_t>(vp9_fix_jump_timestamp_, frame.timestamp)) | |
606 return true; | |
607 | |
608 // After 60 seconds, reset |vp9_fix_jump_timestamp_| in order to not | |
609 // discard old frames when the timestamp wraps. | |
610 int diff_ms = | |
611 ForwardDiff<uint32_t>(vp9_fix_jump_timestamp_, frame.timestamp) / 90; | |
612 if (diff_ms > 60 * 1000) | |
613 vp9_fix_jump_timestamp_ = -1; | |
stefan-webrtc
2016/11/14 12:00:26
Should vp9_fix_last_picture_id_ be reset here too?
philipel
2016/11/14 15:31:03
Not needed since |vp9_fix_last_picture_id_| is con
| |
614 } | |
615 | |
616 uint16_t fixed_pid = Add<kPicIdLength>(*picture_id, vp9_fix_pid_offset_); | |
617 | |
618 // Update |vp9_fix_last_timestamp_| with the most recent timestamp. | |
619 if (vp9_fix_last_timestamp_ == -1) | |
620 vp9_fix_last_timestamp_ = frame.timestamp; | |
621 if (AheadOf<uint32_t>(frame.timestamp, vp9_fix_last_timestamp_)) | |
622 vp9_fix_last_timestamp_ = frame.timestamp; | |
623 | |
624 if (vp9_fix_last_picture_id_ == -1) | |
625 vp9_fix_last_picture_id_ = *picture_id; | |
626 | |
627 bool has_jumped = false; | |
628 | |
629 if (AheadOrAt<uint32_t>(frame.timestamp, vp9_fix_last_timestamp_) && | |
stefan-webrtc
2016/11/14 12:00:26
I think it could have been good to split this meth
philipel
2016/11/14 15:31:03
Done, but not CorrectForJump (annoying to return m
| |
630 AheadOf<uint16_t, kPicIdLength>(vp9_fix_last_picture_id_, fixed_pid)) { | |
631 // Test if there has been a jump backwards in the picture id. | |
632 has_jumped = true; | |
633 } else if (AheadOrAt<uint32_t>(frame.timestamp, vp9_fix_last_timestamp_) && | |
634 ForwardDiff<uint16_t, kPicIdLength>(vp9_fix_last_picture_id_, | |
635 fixed_pid) > 128) { | |
636 // Test if we have jump forward too much. The reason we have to do this | |
stefan-webrtc
2016/11/14 12:00:26
jumped forward
philipel
2016/11/14 15:31:03
Done.
| |
637 // is because the FrameBuffer holds history of old frames and inserting | |
638 // frames with a much advanced picture id can result in the frame buffer | |
639 // holding more than half of the interval of picture ids. | |
640 has_jumped = true; | |
641 } else { | |
642 // Special case where the picture id jump forward but not by much and the | |
643 // tl0 jumps to the id of an already saved gof for that id. In order to | |
644 // detect this we check if the picture id span over the length of the GOF. | |
645 auto info_it = gof_info_.find(*tl0_pic_idx); | |
646 if (info_it != gof_info_.end()) { | |
647 int last_pid_gof_idx_0 = | |
648 Subtract<kPicIdLength>(info_it->second.last_picture_id, | |
649 info_it->second.last_picture_id % | |
650 info_it->second.gof->num_frames_in_gof); | |
651 int pif_gof_end = Add<kPicIdLength>( | |
652 last_pid_gof_idx_0, info_it->second.gof->num_frames_in_gof); | |
653 if (AheadOf<uint16_t, kPicIdLength>(fixed_pid, pif_gof_end)) | |
654 has_jumped = true; | |
655 } | |
656 } | |
657 | |
658 uint8_t fixed_tl0 = kNoTl0PicIdx; | |
659 if (*tl0_pic_idx != kNoTl0PicIdx) { | |
660 fixed_tl0 = Add<256>(*tl0_pic_idx, vp9_fix_tl0_pic_idx_offset_); | |
stefan-webrtc
2016/11/14 12:00:26
Should we have a named constant 256?
philipel
2016/11/14 15:31:03
Done.
| |
661 | |
662 // Update |vp9_fix_last_tl0_pic_idx_| with the most recent tl0 pic index. | |
663 if (vp9_fix_last_tl0_pic_idx_ == -1) | |
664 vp9_fix_last_tl0_pic_idx_ = *tl0_pic_idx; | |
665 if (AheadOf<uint8_t>(fixed_tl0, vp9_fix_last_tl0_pic_idx_)) | |
666 vp9_fix_last_tl0_pic_idx_ = fixed_tl0; | |
stefan-webrtc
2016/11/14 12:00:26
Should we break out these 4 lines into a function
philipel
2016/11/14 15:31:03
Not really feasible...
| |
667 | |
668 // Test if there has been a jump backwards in tl0 pic index. | |
stefan-webrtc
2016/11/14 12:00:26
Can there be a jump in tl0 pic index but not in pi
philipel
2016/11/14 15:31:03
I guess picture id might be enough but I think it'
| |
669 if (AheadOrAt<uint32_t>(frame.timestamp, vp9_fix_last_timestamp_) && | |
670 AheadOf<uint8_t>(vp9_fix_last_tl0_pic_idx_, fixed_tl0)) { | |
671 has_jumped = true; | |
672 } | |
673 | |
674 // Test if there has been a jump forward. If the jump forward results | |
675 // in the tl0 pic index for this frame to be considered smaller than the | |
676 // smallest item in |gof_info_| then we have jumped forward far enough to | |
677 // wrap. | |
678 if (!gof_info_.empty() && | |
679 AheadOf<uint8_t>(gof_info_.begin()->first, fixed_tl0)) { | |
680 has_jumped = true; | |
681 } | |
682 } | |
683 | |
684 if (has_jumped) { | |
685 // First we calculate the offset to get to the previous picture id, and then | |
686 // we add 128 (max pid_diff) to avoid accidently referencing any previous | |
687 // frames that was inserted into the FrameBuffer. | |
688 vp9_fix_pid_offset_ = ForwardDiff<uint16_t, kPicIdLength>( | |
689 *picture_id, vp9_fix_last_picture_id_); | |
690 vp9_fix_pid_offset_ += 128; | |
stefan-webrtc
2016/11/14 12:00:26
Can we name this constant in a good way? Maybe it'
philipel
2016/11/14 15:31:03
Done.
| |
691 | |
692 fixed_pid = Add<kPicIdLength>(*picture_id, vp9_fix_pid_offset_); | |
693 vp9_fix_last_picture_id_ = fixed_pid; | |
694 vp9_fix_jump_timestamp_ = frame.timestamp; | |
695 gof_info_.clear(); | |
696 | |
697 vp9_fix_tl0_pic_idx_offset_ = | |
698 ForwardDiff<uint8_t>(*tl0_pic_idx, vp9_fix_last_tl0_pic_idx_); | |
699 vp9_fix_tl0_pic_idx_offset_ += kMaxGofSaved; | |
700 fixed_tl0 = Add<256>(*tl0_pic_idx, vp9_fix_tl0_pic_idx_offset_); | |
701 vp9_fix_last_tl0_pic_idx_ = fixed_tl0; | |
702 } | |
703 | |
704 // Update |vp9_fix_last_picture_id_| with the most recent picture id. | |
705 if (AheadOf<uint16_t, kPicIdLength>(fixed_pid, vp9_fix_last_picture_id_)) | |
706 vp9_fix_last_picture_id_ = fixed_pid; | |
707 | |
708 *picture_id = fixed_pid; | |
709 *tl0_pic_idx = fixed_tl0; | |
710 | |
711 return false; | |
712 } | |
713 | |
588 } // namespace video_coding | 714 } // namespace video_coding |
589 } // namespace webrtc | 715 } // namespace webrtc |
OLD | NEW |