Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(826)

Side by Side Diff: webrtc/modules/video_coding/main/source/jitter_buffer.cc

Issue 1211873004: Request keyframe if too many packets are missing and NACK is disabled. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Brought back code removed in prev. change, fixes failing EndToEndTests. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 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 #include "webrtc/modules/video_coding/main/source/jitter_buffer.h" 10 #include "webrtc/modules/video_coding/main/source/jitter_buffer.h"
(...skipping 20 matching lines...) Expand all
31 #include "webrtc/system_wrappers/include/metrics.h" 31 #include "webrtc/system_wrappers/include/metrics.h"
32 32
33 namespace webrtc { 33 namespace webrtc {
34 34
35 // Interval for updating SS data. 35 // Interval for updating SS data.
36 static const uint32_t kSsCleanupIntervalSec = 60; 36 static const uint32_t kSsCleanupIntervalSec = 60;
37 37
38 // Use this rtt if no value has been reported. 38 // Use this rtt if no value has been reported.
39 static const int64_t kDefaultRtt = 200; 39 static const int64_t kDefaultRtt = 200;
40 40
41 // Request a keyframe if no continuous frame has been received for this
42 // number of milliseconds and NACKs are disabled.
43 static const int64_t kMaxDiscontinuousFramesTime = 10000;
44
41 typedef std::pair<uint32_t, VCMFrameBuffer*> FrameListPair; 45 typedef std::pair<uint32_t, VCMFrameBuffer*> FrameListPair;
42 46
43 bool IsKeyFrame(FrameListPair pair) { 47 bool IsKeyFrame(FrameListPair pair) {
44 return pair.second->FrameType() == kVideoFrameKey; 48 return pair.second->FrameType() == kVideoFrameKey;
45 } 49 }
46 50
47 bool HasNonEmptyState(FrameListPair pair) { 51 bool HasNonEmptyState(FrameListPair pair) {
48 return pair.second->GetState() != kStateEmpty; 52 return pair.second->GetState() != kStateEmpty;
49 } 53 }
50 54
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 if (!running_) { 524 if (!running_) {
521 return false; 525 return false;
522 } 526 }
523 if (decode_error_mode_ == kNoErrors) { 527 if (decode_error_mode_ == kNoErrors) {
524 // No point to continue, as we are not decoding with errors. 528 // No point to continue, as we are not decoding with errors.
525 return false; 529 return false;
526 } 530 }
527 531
528 CleanUpOldOrEmptyFrames(); 532 CleanUpOldOrEmptyFrames();
529 533
534 VCMFrameBuffer* oldest_frame;
530 if (decodable_frames_.empty()) { 535 if (decodable_frames_.empty()) {
531 return false; 536 if (nack_mode_ != kNoNack || incomplete_frames_.empty()) {
532 } 537 return false;
533 VCMFrameBuffer* oldest_frame = decodable_frames_.Front(); 538 }
534 // If we have exactly one frame in the buffer, release it only if it is 539 oldest_frame = incomplete_frames_.Front();
535 // complete. We know decodable_frames_ is not empty due to the previous 540 RTC_DCHECK(oldest_frame->GetState() != kStateComplete);
536 // check. 541 // Last frame will only be removed from buffer if it is complete.
537 if (decodable_frames_.size() == 1 && incomplete_frames_.empty() 542 if (incomplete_frames_.size() == 1 ||
538 && oldest_frame->GetState() != kStateComplete) { 543 oldest_frame->GetState() != kStateDecodable) {
539 return false; 544 return false;
545 }
546 } else {
547 oldest_frame = decodable_frames_.Front();
548 // If we have exactly one frame in the buffer, release it only if it is
549 // complete. We know decodable_frames_ is not empty due to the previous
550 // check.
551 if (decodable_frames_.size() == 1 && incomplete_frames_.empty()
552 && oldest_frame->GetState() != kStateComplete) {
stefan-webrtc 2015/11/16 17:52:15 Can we end up here without oldest_frame being comp
joachim 2015/11/16 21:58:11 Well, the condition was like that before, I just m
stefan-webrtc 2015/11/18 00:02:17 Acknowledged.
553 return false;
554 }
540 } 555 }
541 556
542 *timestamp = oldest_frame->TimeStamp(); 557 *timestamp = oldest_frame->TimeStamp();
543 return true; 558 return true;
544 } 559 }
545 560
546 VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) { 561 VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
547 CriticalSectionScoped cs(crit_sect_); 562 CriticalSectionScoped cs(crit_sect_);
548 if (!running_) { 563 if (!running_) {
549 return NULL; 564 return NULL;
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 packet.frameType != kVideoFrameKey) { 765 packet.frameType != kVideoFrameKey) {
751 buffer_state = kFlushIndicator; 766 buffer_state = kFlushIndicator;
752 } 767 }
753 768
754 latest_received_sequence_number_ = LatestSequenceNumber( 769 latest_received_sequence_number_ = LatestSequenceNumber(
755 latest_received_sequence_number_, packet.seqNum); 770 latest_received_sequence_number_, packet.seqNum);
756 } 771 }
757 } 772 }
758 773
759 // Is the frame already in the decodable list? 774 // Is the frame already in the decodable list?
760 bool continuous = IsContinuous(*frame); 775 bool continuous = IsContinuous(*frame, false);
776 bool continuous_for_decoding;
777 if (continuous &&
778 (decode_error_mode_ != kWithErrors || nack_mode_ != kNoNack)) {
779 // If NACKs are enabled missing data will be handled through them so it's
780 // fine to always assume frames that are continuous for decoding below.
781 continuous_for_decoding = true;
stefan-webrtc 2015/11/16 17:52:15 Does this make sure that we actually wait for the
joachim 2015/11/16 21:58:11 I don't think so as the behavior for enabled NACKs
782 } else {
783 continuous_for_decoding = IsContinuous(*frame, true);
stefan-webrtc 2015/11/16 17:52:15 Does this mean we require frames to be complete al
joachim 2015/11/16 21:58:11 For "decode_error_mode_ == kWithErrors", the actua
stefan-webrtc 2015/11/18 00:02:17 I'm trying to understand when and why it is necess
joachim 2015/11/18 00:35:14 The problem is, that with ignore_error_mode = true
joachim 2015/11/18 00:50:26 Btw, I did some more testing and you are right: if
stefan-webrtc 2015/11/18 20:51:57 Yes, but doesn't that mean that we don't decode wi
stefan-webrtc 2015/11/18 20:51:57 I'd say the common case is NACKs enabled and decod
joachim 2015/11/18 23:46:07 Acknowledged.
joachim 2015/11/18 23:46:07 Hmm. With the latest changes, decoding with errors
stefan-webrtc 2015/11/18 23:51:03 Right. What behavior is it that you want? We typic
stefan-webrtc 2015/11/19 00:04:17 I see, maybe if you increase the framerate (decrea
stefan-webrtc 2015/11/19 00:06:54 OK, in that case I suggest that we clean up the "d
joachim 2015/11/19 00:44:50 Another possibility would be to enable NACK for th
784 }
761 switch (buffer_state) { 785 switch (buffer_state) {
762 case kGeneralError: 786 case kGeneralError:
763 case kTimeStampError: 787 case kTimeStampError:
764 case kSizeError: { 788 case kSizeError: {
765 free_frames_.push_back(frame); 789 free_frames_.push_back(frame);
766 break; 790 break;
767 } 791 }
768 case kCompleteSession: { 792 case kCompleteSession: {
769 if (previous_state != kStateDecodable && 793 if (previous_state != kStateDecodable &&
770 previous_state != kStateComplete) { 794 previous_state != kStateComplete) {
771 CountFrame(*frame); 795 CountFrame(*frame);
772 if (continuous) { 796 if (continuous) {
773 // Signal that we have a complete session. 797 // Signal that we have a complete session.
774 frame_event_->Set(); 798 frame_event_->Set();
775 } 799 }
776 } 800 }
777 FALLTHROUGH(); 801 FALLTHROUGH();
778 } 802 }
779 // Note: There is no break here - continuing to kDecodableSession. 803 // Note: There is no break here - continuing to kDecodableSession.
780 case kDecodableSession: { 804 case kDecodableSession: {
781 *retransmitted = (frame->GetNackCount() > 0); 805 *retransmitted = (frame->GetNackCount() > 0);
782 if (continuous) { 806 if (continuous && continuous_for_decoding) {
783 decodable_frames_.InsertFrame(frame); 807 decodable_frames_.InsertFrame(frame);
784 FindAndInsertContinuousFrames(*frame); 808 FindAndInsertContinuousFrames(*frame);
785 } else { 809 } else {
786 incomplete_frames_.InsertFrame(frame); 810 incomplete_frames_.InsertFrame(frame);
811 // If NACKs are enabled, keyframes are triggered by |GetNackList|.
812 if (nack_mode_ == kNoNack && continuous && !continuous_for_decoding &&
813 NonContinuousOrIncompleteDuration() >
814 90 * kMaxDiscontinuousFramesTime) {
815 return kFlushIndicator;
816 }
787 } 817 }
788 break; 818 break;
789 } 819 }
790 case kIncomplete: { 820 case kIncomplete: {
791 if (frame->GetState() == kStateEmpty && 821 if (frame->GetState() == kStateEmpty &&
792 last_decoded_state_.UpdateEmptyFrame(frame)) { 822 last_decoded_state_.UpdateEmptyFrame(frame)) {
793 free_frames_.push_back(frame); 823 free_frames_.push_back(frame);
794 return kNoError; 824 return kNoError;
795 } else { 825 } else {
796 incomplete_frames_.InsertFrame(frame); 826 incomplete_frames_.InsertFrame(frame);
827 // If NACKs are enabled, keyframes are triggered by |GetNackList|.
828 if (nack_mode_ == kNoNack && NonContinuousOrIncompleteDuration() >
829 90 * kMaxDiscontinuousFramesTime) {
830 return kFlushIndicator;
831 }
797 } 832 }
798 break; 833 break;
799 } 834 }
800 case kNoError: 835 case kNoError:
801 case kOutOfBoundsPacket: 836 case kOutOfBoundsPacket:
802 case kDuplicatePacket: { 837 case kDuplicatePacket: {
803 // Put back the frame where it came from. 838 // Put back the frame where it came from.
804 if (frame_list != NULL) { 839 if (frame_list != NULL) {
805 frame_list->InsertFrame(frame); 840 frame_list->InsertFrame(frame);
806 } else { 841 } else {
807 free_frames_.push_back(frame); 842 free_frames_.push_back(frame);
808 } 843 }
809 ++num_duplicated_packets_; 844 ++num_duplicated_packets_;
810 break; 845 break;
811 } 846 }
812 case kFlushIndicator: 847 case kFlushIndicator:
813 free_frames_.push_back(frame); 848 free_frames_.push_back(frame);
814 return kFlushIndicator; 849 return kFlushIndicator;
815 default: assert(false); 850 default: assert(false);
816 } 851 }
817 return buffer_state; 852 return buffer_state;
818 } 853 }
819 854
820 bool VCMJitterBuffer::IsContinuousInState(const VCMFrameBuffer& frame, 855 bool VCMJitterBuffer::IsContinuousInState(const VCMFrameBuffer& frame,
821 const VCMDecodingState& decoding_state) const { 856 const VCMDecodingState& decoding_state, bool ignore_error_mode) const {
822 if (decode_error_mode_ == kWithErrors) 857 if (!ignore_error_mode && decode_error_mode_ == kWithErrors) {
823 return true; 858 return true;
859 }
860
824 // Is this frame (complete or decodable) and continuous? 861 // Is this frame (complete or decodable) and continuous?
825 // kStateDecodable will never be set when decode_error_mode_ is false 862 // kStateDecodable will never be set when decode_error_mode_ is false
826 // as SessionInfo determines this state based on the error mode (and frame 863 // as SessionInfo determines this state based on the error mode (and frame
827 // completeness). 864 // completeness).
828 return (frame.GetState() == kStateComplete || 865 return (frame.GetState() == kStateComplete ||
829 frame.GetState() == kStateDecodable) && 866 frame.GetState() == kStateDecodable) &&
830 decoding_state.ContinuousFrame(&frame); 867 decoding_state.ContinuousFrame(&frame);
831 } 868 }
832 869
833 bool VCMJitterBuffer::IsContinuous(const VCMFrameBuffer& frame) const { 870 bool VCMJitterBuffer::IsContinuous(const VCMFrameBuffer& frame,
834 if (IsContinuousInState(frame, last_decoded_state_)) { 871 bool ignore_error_mode) const {
872 if (IsContinuousInState(frame, last_decoded_state_, ignore_error_mode)) {
835 return true; 873 return true;
836 } 874 }
837 VCMDecodingState decoding_state; 875 VCMDecodingState decoding_state;
838 decoding_state.CopyFrom(last_decoded_state_); 876 decoding_state.CopyFrom(last_decoded_state_);
839 for (FrameList::const_iterator it = decodable_frames_.begin(); 877 for (FrameList::const_iterator it = decodable_frames_.begin();
840 it != decodable_frames_.end(); ++it) { 878 it != decodable_frames_.end(); ++it) {
841 VCMFrameBuffer* decodable_frame = it->second; 879 VCMFrameBuffer* decodable_frame = it->second;
842 if (IsNewerTimestamp(decodable_frame->TimeStamp(), frame.TimeStamp())) { 880 if (IsNewerTimestamp(decodable_frame->TimeStamp(), frame.TimeStamp())) {
843 break; 881 break;
844 } 882 }
845 decoding_state.SetState(decodable_frame); 883 decoding_state.SetState(decodable_frame);
846 if (IsContinuousInState(frame, decoding_state)) { 884 if (IsContinuousInState(frame, decoding_state, ignore_error_mode)) {
847 return true; 885 return true;
848 } 886 }
849 } 887 }
850 return false; 888 return false;
851 } 889 }
852 890
853 void VCMJitterBuffer::FindAndInsertContinuousFrames( 891 void VCMJitterBuffer::FindAndInsertContinuousFrames(
854 const VCMFrameBuffer& new_frame) { 892 const VCMFrameBuffer& new_frame) {
855 VCMDecodingState decoding_state; 893 VCMDecodingState decoding_state;
856 decoding_state.CopyFrom(last_decoded_state_); 894 decoding_state.CopyFrom(last_decoded_state_);
(...skipping 13 matching lines...) Expand all
870 // 1. Continuous base or sync layer. 908 // 1. Continuous base or sync layer.
871 // 2. The end of the list was reached. 909 // 2. The end of the list was reached.
872 for (FrameList::iterator it = incomplete_frames_.begin(); 910 for (FrameList::iterator it = incomplete_frames_.begin();
873 it != incomplete_frames_.end();) { 911 it != incomplete_frames_.end();) {
874 VCMFrameBuffer* frame = it->second; 912 VCMFrameBuffer* frame = it->second;
875 if (IsNewerTimestamp(original_decoded_state.time_stamp(), 913 if (IsNewerTimestamp(original_decoded_state.time_stamp(),
876 frame->TimeStamp())) { 914 frame->TimeStamp())) {
877 ++it; 915 ++it;
878 continue; 916 continue;
879 } 917 }
880 if (IsContinuousInState(*frame, decoding_state)) { 918 if (IsContinuousInState(*frame, decoding_state, false)) {
881 decodable_frames_.InsertFrame(frame); 919 decodable_frames_.InsertFrame(frame);
882 incomplete_frames_.erase(it++); 920 incomplete_frames_.erase(it++);
883 decoding_state.SetState(frame); 921 decoding_state.SetState(frame);
884 } else if (frame->TemporalId() <= 0) { 922 } else if (frame->TemporalId() <= 0) {
885 break; 923 break;
886 } else { 924 } else {
887 ++it; 925 ++it;
888 } 926 }
889 } 927 }
890 } 928 }
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 } 1356 }
1319 // Evaluate if the RTT is higher than |high_rtt_nack_threshold_ms_|, and in 1357 // Evaluate if the RTT is higher than |high_rtt_nack_threshold_ms_|, and in
1320 // that case we don't wait for retransmissions. 1358 // that case we don't wait for retransmissions.
1321 if (high_rtt_nack_threshold_ms_ >= 0 && 1359 if (high_rtt_nack_threshold_ms_ >= 0 &&
1322 rtt_ms_ >= high_rtt_nack_threshold_ms_) { 1360 rtt_ms_ >= high_rtt_nack_threshold_ms_) {
1323 return false; 1361 return false;
1324 } 1362 }
1325 return true; 1363 return true;
1326 } 1364 }
1327 } // namespace webrtc 1365 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/main/source/jitter_buffer.h ('k') | webrtc/video/end_to_end_tests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698