| Index: webrtc/modules/video_coding/jitter_buffer.cc
|
| diff --git a/webrtc/modules/video_coding/jitter_buffer.cc b/webrtc/modules/video_coding/jitter_buffer.cc
|
| index 15195dbfdc2bcc338a949d413a4b9dfd7bdbc4d8..d44d2b68f10931e36a6f953c0c6d679f9c734685 100644
|
| --- a/webrtc/modules/video_coding/jitter_buffer.cc
|
| +++ b/webrtc/modules/video_coding/jitter_buffer.cc
|
| @@ -38,6 +38,10 @@ static const uint32_t kSsCleanupIntervalSec = 60;
|
| // 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 @@ bool VCMJitterBuffer::NextMaybeIncompleteTimestamp(uint32_t* timestamp) {
|
|
|
| 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 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
| 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 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
| 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 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
|
|
| 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
|
|
|