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

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: Updated how to request keyframes Created 5 years, 3 months 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 15 matching lines...) Expand all
26 #include "webrtc/system_wrappers/interface/event_wrapper.h" 26 #include "webrtc/system_wrappers/interface/event_wrapper.h"
27 #include "webrtc/system_wrappers/interface/logging.h" 27 #include "webrtc/system_wrappers/interface/logging.h"
28 #include "webrtc/system_wrappers/interface/metrics.h" 28 #include "webrtc/system_wrappers/interface/metrics.h"
29 #include "webrtc/system_wrappers/interface/trace_event.h" 29 #include "webrtc/system_wrappers/interface/trace_event.h"
30 30
31 namespace webrtc { 31 namespace webrtc {
32 32
33 // Use this rtt if no value has been reported. 33 // Use this rtt if no value has been reported.
34 static const int64_t kDefaultRtt = 200; 34 static const int64_t kDefaultRtt = 200;
35 35
36 // Request a keyframe if no continuous frame has been received for this
37 // number of milliseconds and NACKs are disabled.
38 static const int64_t kMaxDiscontinuousFramesTime = 10000;
joachim 2015/09/03 00:05:01 I based the timeout on the behaviour of "EndToEndT
stefan-webrtc 2015/09/18 14:22:41 Acknowledged.
39
36 typedef std::pair<uint32_t, VCMFrameBuffer*> FrameListPair; 40 typedef std::pair<uint32_t, VCMFrameBuffer*> FrameListPair;
37 41
38 bool IsKeyFrame(FrameListPair pair) { 42 bool IsKeyFrame(FrameListPair pair) {
39 return pair.second->FrameType() == kVideoFrameKey; 43 return pair.second->FrameType() == kVideoFrameKey;
40 } 44 }
41 45
42 bool HasNonEmptyState(FrameListPair pair) { 46 bool HasNonEmptyState(FrameListPair pair) {
43 return pair.second->GetState() != kStateEmpty; 47 return pair.second->GetState() != kStateEmpty;
44 } 48 }
45 49
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 stats_callback_(NULL), 134 stats_callback_(NULL),
131 incoming_frame_rate_(0), 135 incoming_frame_rate_(0),
132 incoming_frame_count_(0), 136 incoming_frame_count_(0),
133 time_last_incoming_frame_count_(0), 137 time_last_incoming_frame_count_(0),
134 incoming_bit_count_(0), 138 incoming_bit_count_(0),
135 incoming_bit_rate_(0), 139 incoming_bit_rate_(0),
136 num_consecutive_old_packets_(0), 140 num_consecutive_old_packets_(0),
137 num_packets_(0), 141 num_packets_(0),
138 num_duplicated_packets_(0), 142 num_duplicated_packets_(0),
139 num_discarded_packets_(0), 143 num_discarded_packets_(0),
144 time_last_decodable_frame_(-1),
140 time_first_packet_ms_(0), 145 time_first_packet_ms_(0),
141 jitter_estimate_(clock), 146 jitter_estimate_(clock),
142 inter_frame_delay_(clock_->TimeInMilliseconds()), 147 inter_frame_delay_(clock_->TimeInMilliseconds()),
143 rtt_ms_(kDefaultRtt), 148 rtt_ms_(kDefaultRtt),
144 nack_mode_(kNoNack), 149 nack_mode_(kNoNack),
145 low_rtt_nack_threshold_ms_(-1), 150 low_rtt_nack_threshold_ms_(-1),
146 high_rtt_nack_threshold_ms_(-1), 151 high_rtt_nack_threshold_ms_(-1),
147 missing_sequence_numbers_(SequenceNumberLessThan()), 152 missing_sequence_numbers_(SequenceNumberLessThan()),
148 max_nack_list_size_(0), 153 max_nack_list_size_(0),
149 max_packet_age_to_nack_(0), 154 max_packet_age_to_nack_(0),
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 incoming_frame_rate_ = 0; 211 incoming_frame_rate_ = 0;
207 incoming_bit_count_ = 0; 212 incoming_bit_count_ = 0;
208 incoming_bit_rate_ = 0; 213 incoming_bit_rate_ = 0;
209 time_last_incoming_frame_count_ = clock_->TimeInMilliseconds(); 214 time_last_incoming_frame_count_ = clock_->TimeInMilliseconds();
210 receive_statistics_ = FrameCounts(); 215 receive_statistics_ = FrameCounts();
211 216
212 num_consecutive_old_packets_ = 0; 217 num_consecutive_old_packets_ = 0;
213 num_packets_ = 0; 218 num_packets_ = 0;
214 num_duplicated_packets_ = 0; 219 num_duplicated_packets_ = 0;
215 num_discarded_packets_ = 0; 220 num_discarded_packets_ = 0;
221 time_last_decodable_frame_ = -1;
216 time_first_packet_ms_ = 0; 222 time_first_packet_ms_ = 0;
217 223
218 // Start in a non-signaled state. 224 // Start in a non-signaled state.
219 waiting_for_completion_.frame_size = 0; 225 waiting_for_completion_.frame_size = 0;
220 waiting_for_completion_.timestamp = 0; 226 waiting_for_completion_.timestamp = 0;
221 waiting_for_completion_.latest_packet_time = -1; 227 waiting_for_completion_.latest_packet_time = -1;
222 first_packet_since_reset_ = true; 228 first_packet_since_reset_ = true;
223 rtt_ms_ = kDefaultRtt; 229 rtt_ms_ = kDefaultRtt;
224 last_decoded_state_.Reset(); 230 last_decoded_state_.Reset();
225 last_gof_valid_ = false; 231 last_gof_valid_ = false;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 return running_; 263 return running_;
258 } 264 }
259 265
260 void VCMJitterBuffer::Flush() { 266 void VCMJitterBuffer::Flush() {
261 CriticalSectionScoped cs(crit_sect_); 267 CriticalSectionScoped cs(crit_sect_);
262 decodable_frames_.Reset(&free_frames_); 268 decodable_frames_.Reset(&free_frames_);
263 incomplete_frames_.Reset(&free_frames_); 269 incomplete_frames_.Reset(&free_frames_);
264 last_decoded_state_.Reset(); // TODO(mikhal): sync reset. 270 last_decoded_state_.Reset(); // TODO(mikhal): sync reset.
265 last_gof_valid_ = false; 271 last_gof_valid_ = false;
266 num_consecutive_old_packets_ = 0; 272 num_consecutive_old_packets_ = 0;
273 time_last_decodable_frame_ = -1;
267 // Also reset the jitter and delay estimates 274 // Also reset the jitter and delay estimates
268 jitter_estimate_.Reset(); 275 jitter_estimate_.Reset();
269 inter_frame_delay_.Reset(clock_->TimeInMilliseconds()); 276 inter_frame_delay_.Reset(clock_->TimeInMilliseconds());
270 waiting_for_completion_.frame_size = 0; 277 waiting_for_completion_.frame_size = 0;
271 waiting_for_completion_.timestamp = 0; 278 waiting_for_completion_.timestamp = 0;
272 waiting_for_completion_.latest_packet_time = -1; 279 waiting_for_completion_.latest_packet_time = -1;
273 first_packet_since_reset_ = true; 280 first_packet_since_reset_ = true;
274 missing_sequence_numbers_.clear(); 281 missing_sequence_numbers_.clear();
275 } 282 }
276 283
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 buffer_state = kFlushIndicator; 693 buffer_state = kFlushIndicator;
687 } 694 }
688 695
689 latest_received_sequence_number_ = LatestSequenceNumber( 696 latest_received_sequence_number_ = LatestSequenceNumber(
690 latest_received_sequence_number_, packet.seqNum); 697 latest_received_sequence_number_, packet.seqNum);
691 } 698 }
692 } 699 }
693 700
694 // Is the frame already in the decodable list? 701 // Is the frame already in the decodable list?
695 bool continuous = IsContinuous(*frame); 702 bool continuous = IsContinuous(*frame);
703 bool continuous_for_decoding;
704 if (continuous &&
705 (decode_error_mode_ != kWithErrors || nack_mode_ != kNoNack)) {
stefan-webrtc 2015/09/18 14:22:41 Can you comment on this if-statement? Especially I
joachim 2015/09/18 20:23:47 If "IsContinuous" returns true and decode_error_mo
706 continuous_for_decoding = true;
707 time_last_decodable_frame_ = now_ms;
708 } else {
709 continuous_for_decoding = IsContinuousForDecoding(*frame);
710 if (continuous_for_decoding) {
711 time_last_decodable_frame_ = now_ms;
712 }
713 }
696 switch (buffer_state) { 714 switch (buffer_state) {
697 case kGeneralError: 715 case kGeneralError:
698 case kTimeStampError: 716 case kTimeStampError:
699 case kSizeError: { 717 case kSizeError: {
700 free_frames_.push_back(frame); 718 free_frames_.push_back(frame);
701 break; 719 break;
702 } 720 }
703 case kCompleteSession: { 721 case kCompleteSession: {
704 if (previous_state != kStateDecodable && 722 if (previous_state != kStateDecodable &&
705 previous_state != kStateComplete) { 723 previous_state != kStateComplete) {
706 CountFrame(*frame); 724 CountFrame(*frame);
707 if (continuous) { 725 if (continuous) {
708 // Signal that we have a complete session. 726 // Signal that we have a complete session.
709 frame_event_->Set(); 727 frame_event_->Set();
710 } 728 }
711 } 729 }
712 FALLTHROUGH(); 730 FALLTHROUGH();
713 } 731 }
714 // Note: There is no break here - continuing to kDecodableSession. 732 // Note: There is no break here - continuing to kDecodableSession.
715 case kDecodableSession: { 733 case kDecodableSession: {
716 *retransmitted = (frame->GetNackCount() > 0); 734 *retransmitted = (frame->GetNackCount() > 0);
717 if (continuous) { 735 if (continuous) {
718 decodable_frames_.InsertFrame(frame); 736 decodable_frames_.InsertFrame(frame);
719 FindAndInsertContinuousFrames(*frame); 737 FindAndInsertContinuousFrames(*frame);
720 } else { 738 } else {
721 incomplete_frames_.InsertFrame(frame); 739 incomplete_frames_.InsertFrame(frame);
722 } 740 }
741 if (nack_mode_ == kNoNack && continuous && !continuous_for_decoding) {
stefan-webrtc 2015/09/18 14:22:42 Why do you want to do this only for kDecodableSess
joachim 2015/09/18 20:23:47 Right, added there too.
742 // If we didn't receive a continuous decodable frame for too long and
743 // can't report through NACKs to the sender, request a keyframe.
744 if (time_last_decodable_frame_ >= 0 &&
745 now_ms - time_last_decodable_frame_ > kMaxDiscontinuousFramesTime) {
746 // Update to current time so we don't request keyframes too often.
747 time_last_decodable_frame_ = now_ms;
748 return kFlushIndicator;
749 }
750 }
723 break; 751 break;
724 } 752 }
725 case kIncomplete: { 753 case kIncomplete: {
726 if (frame->GetState() == kStateEmpty && 754 if (frame->GetState() == kStateEmpty &&
727 last_decoded_state_.UpdateEmptyFrame(frame)) { 755 last_decoded_state_.UpdateEmptyFrame(frame)) {
728 free_frames_.push_back(frame); 756 free_frames_.push_back(frame);
729 return kNoError; 757 return kNoError;
730 } else { 758 } else {
731 incomplete_frames_.InsertFrame(frame); 759 incomplete_frames_.InsertFrame(frame);
732 } 760 }
(...skipping 12 matching lines...) Expand all
745 break; 773 break;
746 } 774 }
747 case kFlushIndicator: 775 case kFlushIndicator:
748 free_frames_.push_back(frame); 776 free_frames_.push_back(frame);
749 return kFlushIndicator; 777 return kFlushIndicator;
750 default: assert(false); 778 default: assert(false);
751 } 779 }
752 return buffer_state; 780 return buffer_state;
753 } 781 }
754 782
755 bool VCMJitterBuffer::IsContinuousInState(const VCMFrameBuffer& frame, 783 bool VCMJitterBuffer::IsContinuousInState(const VCMFrameBuffer& frame,
stefan-webrtc 2015/09/18 14:22:42 Should this method have a different name? I'd say
joachim 2015/09/18 20:23:47 As the functionality of "IsContinuousInState" is t
756 const VCMDecodingState& decoding_state) const { 784 const VCMDecodingState& decoding_state) const {
757 if (decode_error_mode_ == kWithErrors) 785 if (decode_error_mode_ == kWithErrors) {
758 return true; 786 return true;
787 }
788 return IsContinuousInStateForDecoding(frame, decoding_state);
stefan-webrtc 2015/09/18 14:22:41 return decode_error_mode_ == kWithErrors || IsCont
joachim 2015/09/18 20:23:47 Refactored, so that doesn't apply any more.
789 }
790
791 bool VCMJitterBuffer::IsContinuousInStateForDecoding(
792 const VCMFrameBuffer& frame, const VCMDecodingState& decoding_state) const {
759 // Is this frame (complete or decodable) and continuous? 793 // Is this frame (complete or decodable) and continuous?
760 // kStateDecodable will never be set when decode_error_mode_ is false 794 // kStateDecodable will never be set when decode_error_mode_ is false
761 // as SessionInfo determines this state based on the error mode (and frame 795 // as SessionInfo determines this state based on the error mode (and frame
762 // completeness). 796 // completeness).
763 return (frame.GetState() == kStateComplete || 797 return (frame.GetState() == kStateComplete ||
764 frame.GetState() == kStateDecodable) && 798 frame.GetState() == kStateDecodable) &&
765 decoding_state.ContinuousFrame(&frame); 799 decoding_state.ContinuousFrame(&frame);
766 } 800 }
767 801
768 bool VCMJitterBuffer::IsContinuous(const VCMFrameBuffer& frame) const { 802 bool VCMJitterBuffer::IsContinuous(const VCMFrameBuffer& frame) const {
769 if (IsContinuousInState(frame, last_decoded_state_)) { 803 if (IsContinuousInState(frame, last_decoded_state_)) {
770 return true; 804 return true;
771 } 805 }
772 VCMDecodingState decoding_state; 806 VCMDecodingState decoding_state;
773 decoding_state.CopyFrom(last_decoded_state_); 807 decoding_state.CopyFrom(last_decoded_state_);
774 for (FrameList::const_iterator it = decodable_frames_.begin(); 808 for (FrameList::const_iterator it = decodable_frames_.begin();
775 it != decodable_frames_.end(); ++it) { 809 it != decodable_frames_.end(); ++it) {
776 VCMFrameBuffer* decodable_frame = it->second; 810 VCMFrameBuffer* decodable_frame = it->second;
777 if (IsNewerTimestamp(decodable_frame->TimeStamp(), frame.TimeStamp())) { 811 if (IsNewerTimestamp(decodable_frame->TimeStamp(), frame.TimeStamp())) {
778 break; 812 break;
779 } 813 }
780 decoding_state.SetState(decodable_frame); 814 decoding_state.SetState(decodable_frame);
781 if (IsContinuousInState(frame, decoding_state)) { 815 if (IsContinuousInState(frame, decoding_state)) {
782 return true; 816 return true;
783 } 817 }
784 } 818 }
785 return false; 819 return false;
786 } 820 }
787 821
822 bool VCMJitterBuffer::IsContinuousForDecoding(
stefan-webrtc 2015/09/18 14:22:41 I don't like how this duplicates the code of IsCon
joachim 2015/09/18 20:23:47 Updated to take a parameter for the two modes.
823 const VCMFrameBuffer& frame) const {
824 if (IsContinuousInStateForDecoding(frame, last_decoded_state_)) {
825 return true;
826 }
827 VCMDecodingState decoding_state;
828 decoding_state.CopyFrom(last_decoded_state_);
829 for (FrameList::const_iterator it = decodable_frames_.begin();
830 it != decodable_frames_.end(); ++it) {
831 VCMFrameBuffer* decodable_frame = it->second;
832 if (IsNewerTimestamp(decodable_frame->TimeStamp(), frame.TimeStamp())) {
833 break;
834 }
835 decoding_state.SetState(decodable_frame);
836 if (IsContinuousInStateForDecoding(frame, decoding_state)) {
837 return true;
838 }
839 }
840 return false;
841 }
842
788 void VCMJitterBuffer::FindAndInsertContinuousFrames( 843 void VCMJitterBuffer::FindAndInsertContinuousFrames(
789 const VCMFrameBuffer& new_frame) { 844 const VCMFrameBuffer& new_frame) {
790 VCMDecodingState decoding_state; 845 VCMDecodingState decoding_state;
791 decoding_state.CopyFrom(last_decoded_state_); 846 decoding_state.CopyFrom(last_decoded_state_);
792 decoding_state.SetState(&new_frame); 847 decoding_state.SetState(&new_frame);
793 FindAndInsertContinuousFramesWithState(decoding_state); 848 FindAndInsertContinuousFramesWithState(decoding_state);
794 } 849 }
795 850
796 void VCMJitterBuffer::FindAndInsertContinuousFramesWithState( 851 void VCMJitterBuffer::FindAndInsertContinuousFramesWithState(
797 const VCMDecodingState& original_decoded_state) { 852 const VCMDecodingState& original_decoded_state) {
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1308 }
1254 // Evaluate if the RTT is higher than |high_rtt_nack_threshold_ms_|, and in 1309 // Evaluate if the RTT is higher than |high_rtt_nack_threshold_ms_|, and in
1255 // that case we don't wait for retransmissions. 1310 // that case we don't wait for retransmissions.
1256 if (high_rtt_nack_threshold_ms_ >= 0 && 1311 if (high_rtt_nack_threshold_ms_ >= 0 &&
1257 rtt_ms_ >= high_rtt_nack_threshold_ms_) { 1312 rtt_ms_ >= high_rtt_nack_threshold_ms_) {
1258 return false; 1313 return false;
1259 } 1314 }
1260 return true; 1315 return true;
1261 } 1316 }
1262 } // namespace webrtc 1317 } // 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