From c1f243f8e7ca5c0a20863f6060ca6be0541dd6ee Mon Sep 17 00:00:00 2001 From: "mikhal@webrtc.org" Date: Mon, 22 Apr 2013 22:24:38 +0000 Subject: [PATCH] VCM/JB: Skip to the next complete key frame Review URL: https://webrtc-codereview.appspot.com/1317006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3885 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../video_coding/main/source/jitter_buffer.cc | 36 +++++++++++-------- .../main/source/jitter_buffer_unittest.cc | 23 +++++++----- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.cc b/webrtc/modules/video_coding/main/source/jitter_buffer.cc index 86683ff9b7..abcda8202c 100644 --- a/webrtc/modules/video_coding/main/source/jitter_buffer.cc +++ b/webrtc/modules/video_coding/main/source/jitter_buffer.cc @@ -54,12 +54,11 @@ class FrameEqualTimestamp { uint32_t timestamp_; }; -class CompleteDecodableKeyFrameCriteria { +class CompleteKeyFrameCriteria { public: bool operator()(VCMFrameBuffer* frame) { - return (frame->FrameType() == kVideoFrameKey) && - (frame->GetState() == kStateComplete || - frame->GetState() == kStateDecodable); + return (frame->FrameType() == kVideoFrameKey && + frame->GetState() == kStateComplete); } }; @@ -435,24 +434,19 @@ bool VCMJitterBuffer::CompleteSequenceWithNextFrame() { VCMEncodedFrame* VCMJitterBuffer::GetCompleteFrameForDecoding( uint32_t max_wait_time_ms) { TRACE_EVENT0("webrtc", "JB::GetCompleteFrame"); + crit_sect_->Enter(); if (!running_) { return NULL; } - crit_sect_->Enter(); - CleanUpOldOrEmptyFrames(); - if (last_decoded_state_.in_initial_state() && WaitForRetransmissions()) { + if (last_decoded_state_.in_initial_state()) { waiting_for_key_frame_ = true; } FrameList::iterator it = FindOldestCompleteContinuousFrame(); if (it == frame_list_.end()) { - if (max_wait_time_ms == 0) { - crit_sect_->Leave(); - return NULL; - } const int64_t end_wait_time_ms = clock_->TimeInMilliseconds() + max_wait_time_ms; int64_t wait_time_ms = max_wait_time_ms; @@ -462,7 +456,7 @@ VCMEncodedFrame* VCMJitterBuffer::GetCompleteFrameForDecoding( frame_event_->Wait(static_cast(wait_time_ms)); crit_sect_->Enter(); if (ret == kEventSignaled) { - // are we closing down the Jitter buffer + // Are we closing down the Jitter buffer? if (!running_) { crit_sect_->Leave(); return NULL; @@ -490,11 +484,23 @@ VCMEncodedFrame* VCMJitterBuffer::GetCompleteFrameForDecoding( if (it == frame_list_.end()) { // Even after signaling we're still missing a complete continuous frame. + // Look for a complete key frame. + it = find_if(frame_list_.begin(), frame_list_.end(), + CompleteKeyFrameCriteria()); + if (it == frame_list_.end()) { + crit_sect_->Leave(); + return NULL; + } + } + + VCMFrameBuffer* oldest_frame = *it; + + // Are we waiting for a key frame? + if (waiting_for_key_frame_ && oldest_frame->FrameType() != kVideoFrameKey) { crit_sect_->Leave(); return NULL; } - VCMFrameBuffer* oldest_frame = *it; it = frame_list_.erase(it); if (frame_list_.empty()) { TRACE_EVENT_INSTANT1("webrtc", "JB::FrameListEmptied", @@ -1003,9 +1009,9 @@ VCMEncodedFrame* VCMJitterBuffer::GetFrameForDecodingNACK() { } FrameList::iterator it = FindOldestCompleteContinuousFrame(); if (it == frame_list_.end()) { - // If we didn't find one we're good with a complete key/decodable frame. + // If we didn't find one we're good with a complete key frame. it = find_if(frame_list_.begin(), frame_list_.end(), - CompleteDecodableKeyFrameCriteria()); + CompleteKeyFrameCriteria()); if (it == frame_list_.end()) { return NULL; } diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc index 7107ccbc76..22fb425c52 100644 --- a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc +++ b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc @@ -373,6 +373,16 @@ TEST_F(TestRunningJitterBuffer, StatisticsTest) { EXPECT_EQ(kDefaultBitrateKbps, bitrate); } +TEST_F(TestRunningJitterBuffer, SkipToKeyFrame) { + // Insert delta frames. + EXPECT_GE(InsertFrames(5, kVideoFrameDelta), kNoError); + // Can't decode without a key frame. + EXPECT_FALSE(DecodeCompleteFrame()); + InsertFrame(kVideoFrameKey); + // Skip to the next key frame. + EXPECT_TRUE(DecodeCompleteFrame()); +} + TEST_F(TestJitterBufferNack, EmptyPackets) { // Make sure empty packets doesn't clog the jitter buffer. jitter_buffer_->SetNackMode(kNack, media_optimization::kLowRttNackMs, -1); @@ -408,12 +418,12 @@ TEST_F(TestJitterBufferNack, NackTooOldPackets) { EXPECT_FALSE(DecodeCompleteFrame()); EXPECT_FALSE(DecodeFrame()); - EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); // The next complete continuous frame isn't a key frame, but we're waiting // for one. EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); // Skipping ahead to the key frame. - EXPECT_TRUE(DecodeFrame()); + EXPECT_TRUE(DecodeCompleteFrame()); } TEST_F(TestJitterBufferNack, NackLargeJitterBuffer) { @@ -453,16 +463,13 @@ TEST_F(TestJitterBufferNack, NackListFull) { EXPECT_TRUE(request_key_frame); EXPECT_GE(InsertFrame(kVideoFrameDelta), kNoError); - // Waiting for a key frame. - EXPECT_FALSE(DecodeCompleteFrame()); - EXPECT_FALSE(DecodeFrame()); - - EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); // The next complete continuous frame isn't a key frame, but we're waiting // for one. EXPECT_FALSE(DecodeCompleteFrame()); + EXPECT_FALSE(DecodeFrame()); + EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError); // Skipping ahead to the key frame. - EXPECT_TRUE(DecodeFrame()); + EXPECT_TRUE(DecodeCompleteFrame()); } TEST_F(TestJitterBufferNack, NoNackListReturnedBeforeFirstDecode) {