Request keyframe if too many packets are missing and NACK is disabled.
This allows enabling "EndToEndTest.ReceivesPliAndRecoversWithoutNack".
BUG=webrtc:2250
Review URL: https://codereview.webrtc.org/1211873004
Cr-Commit-Position: refs/heads/master@{#10747}
diff --git a/webrtc/modules/video_coding/jitter_buffer.cc b/webrtc/modules/video_coding/jitter_buffer.cc
index 15195db..d44d2b6 100644
--- a/webrtc/modules/video_coding/jitter_buffer.cc
+++ b/webrtc/modules/video_coding/jitter_buffer.cc
@@ -38,6 +38,10 @@
// Use this rtt if no value has been reported.
static const int64_t kDefaultRtt = 200;
+// Request a keyframe if no continuous frame has been received for this
+// number of milliseconds and NACKs are disabled.
+static const int64_t kMaxDiscontinuousFramesTime = 1000;
+
typedef std::pair<uint32_t, VCMFrameBuffer*> FrameListPair;
bool IsKeyFrame(FrameListPair pair) {
@@ -528,16 +532,25 @@
CleanUpOldOrEmptyFrames();
+ VCMFrameBuffer* oldest_frame;
if (decodable_frames_.empty()) {
- return false;
- }
- VCMFrameBuffer* oldest_frame = decodable_frames_.Front();
- // If we have exactly one frame in the buffer, release it only if it is
- // complete. We know decodable_frames_ is not empty due to the previous
- // check.
- if (decodable_frames_.size() == 1 && incomplete_frames_.empty()
- && oldest_frame->GetState() != kStateComplete) {
- return false;
+ if (nack_mode_ != kNoNack || incomplete_frames_.size() <= 1) {
+ return false;
+ }
+ oldest_frame = incomplete_frames_.Front();
+ // Frame will only be removed from buffer if it is complete (or decodable).
+ if (oldest_frame->GetState() < kStateComplete) {
+ return false;
+ }
+ } else {
+ oldest_frame = decodable_frames_.Front();
+ // If we have exactly one frame in the buffer, release it only if it is
+ // complete. We know decodable_frames_ is not empty due to the previous
+ // check.
+ if (decodable_frames_.size() == 1 && incomplete_frames_.empty()
+ && oldest_frame->GetState() != kStateComplete) {
+ return false;
+ }
}
*timestamp = oldest_frame->TimeStamp();
@@ -779,6 +792,11 @@
FindAndInsertContinuousFrames(*frame);
} else {
incomplete_frames_.InsertFrame(frame);
+ // If NACKs are enabled, keyframes are triggered by |GetNackList|.
+ if (nack_mode_ == kNoNack && NonContinuousOrIncompleteDuration() >
+ 90 * kMaxDiscontinuousFramesTime) {
+ return kFlushIndicator;
+ }
}
break;
}
@@ -789,6 +807,11 @@
return kNoError;
} else {
incomplete_frames_.InsertFrame(frame);
+ // If NACKs are enabled, keyframes are triggered by |GetNackList|.
+ if (nack_mode_ == kNoNack && NonContinuousOrIncompleteDuration() >
+ 90 * kMaxDiscontinuousFramesTime) {
+ return kFlushIndicator;
+ }
}
break;
}
@@ -814,8 +837,6 @@
bool VCMJitterBuffer::IsContinuousInState(const VCMFrameBuffer& frame,
const VCMDecodingState& decoding_state) const {
- if (decode_error_mode_ == kWithErrors)
- return true;
// Is this frame (complete or decodable) and continuous?
// kStateDecodable will never be set when decode_error_mode_ is false
// as SessionInfo determines this state based on the error mode (and frame