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
This commit is contained in:
mikhal@webrtc.org 2013-04-22 22:24:38 +00:00
parent 63117339dc
commit c1f243f8e7
2 changed files with 36 additions and 23 deletions

View File

@ -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<uint32_t>(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;
}

View File

@ -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) {