Start NACKing as soon as we have the first packet of a key frame.

BUG=1605

Review URL: https://webrtc-codereview.appspot.com/1307007

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3855 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/video_coding/main/source/frame_buffer.cc b/webrtc/modules/video_coding/main/source/frame_buffer.cc
index bc1407b..69ef0a2 100644
--- a/webrtc/modules/video_coding/main/source/frame_buffer.cc
+++ b/webrtc/modules/video_coding/main/source/frame_buffer.cc
@@ -217,6 +217,12 @@
 }
 
 bool
+VCMFrameBuffer::HaveFirstPacket() const
+{
+    return _sessionInfo.HaveFirstPacket();
+}
+
+bool
 VCMFrameBuffer::HaveLastPacket() const
 {
     return _sessionInfo.HaveLastPacket();
diff --git a/webrtc/modules/video_coding/main/source/frame_buffer.h b/webrtc/modules/video_coding/main/source/frame_buffer.h
index 1d1fd24..81400a2 100644
--- a/webrtc/modules/video_coding/main/source/frame_buffer.h
+++ b/webrtc/modules/video_coding/main/source/frame_buffer.h
@@ -44,6 +44,7 @@
 
     bool IsRetransmitted() const;
     bool IsSessionComplete() const;
+    bool HaveFirstPacket() const;
     bool HaveLastPacket() const;
     // Makes sure the session contain a decodable stream.
     void MakeSessionDecodable();
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.cc b/webrtc/modules/video_coding/main/source/jitter_buffer.cc
index 849d641..86683ff 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer.cc
@@ -878,11 +878,19 @@
     return NULL;
   }
   if (last_decoded_state_.in_initial_state()) {
-    const bool have_non_empty_frame = frame_list_.end() != find_if(
-          frame_list_.begin(), frame_list_.end(), HasNonEmptyState);
-    *request_key_frame = have_non_empty_frame;
-    *nack_list_size = 0;
-    return NULL;
+    bool first_frame_is_key = !frame_list_.empty() &&
+        frame_list_.front()->FrameType() == kVideoFrameKey &&
+        frame_list_.front()->HaveFirstPacket();
+    if (!first_frame_is_key) {
+      const bool have_non_empty_frame = frame_list_.end() != find_if(
+            frame_list_.begin(), frame_list_.end(), HasNonEmptyState);
+      bool found_key_frame = RecycleFramesUntilKeyFrame();
+      if (!found_key_frame) {
+        *request_key_frame = have_non_empty_frame;
+        *nack_list_size = 0;
+        return NULL;
+      }
+    }
   }
   if (TooLargeNackList()) {
     TRACE_EVENT_INSTANT1("webrtc", "JB::NackListTooLarge",
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 08f78a9..7107ccb 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
@@ -494,6 +494,24 @@
   EXPECT_TRUE(list != NULL);
 }
 
+TEST_F(TestJitterBufferNack, UseNackToRecoverFirstKeyFrame) {
+  stream_generator->Init(0, 0, clock_->TimeInMilliseconds());
+  stream_generator->GenerateFrame(kVideoFrameKey, 3, 0,
+                                  clock_->TimeInMilliseconds());
+  EXPECT_EQ(kFirstPacket, InsertPacketAndPop(0));
+  // Drop second packet.
+  EXPECT_EQ(kIncomplete, InsertPacketAndPop(1));
+  EXPECT_FALSE(DecodeCompleteFrame());
+  uint16_t nack_list_size = 0;
+  bool extended = false;
+  uint16_t* list = jitter_buffer_->GetNackList(&nack_list_size, &extended);
+  EXPECT_EQ(1, nack_list_size);
+  ASSERT_TRUE(list != NULL);
+  VCMPacket packet;
+  stream_generator->GetPacket(&packet, 0);
+  EXPECT_EQ(packet.seqNum, list[0]);
+}
+
 TEST_F(TestJitterBufferNack, NormalOperation) {
   EXPECT_EQ(kNack, jitter_buffer_->nack_mode());
 
diff --git a/webrtc/modules/video_coding/main/source/session_info.cc b/webrtc/modules/video_coding/main/source/session_info.cc
index eb32822..6db57f2 100644
--- a/webrtc/modules/video_coding/main/source/session_info.cc
+++ b/webrtc/modules/video_coding/main/source/session_info.cc
@@ -354,6 +354,11 @@
 }
 
 bool
+VCMSessionInfo::HaveFirstPacket() const {
+  return !packets_.empty() && packets_.front().isFirstPacket;
+}
+
+bool
 VCMSessionInfo::HaveLastPacket() const {
   return (!packets_.empty() && packets_.back().markerBit);
 }
diff --git a/webrtc/modules/video_coding/main/source/session_info.h b/webrtc/modules/video_coding/main/source/session_info.h
index 3d7dcd9..18ee7a4 100644
--- a/webrtc/modules/video_coding/main/source/session_info.h
+++ b/webrtc/modules/video_coding/main/source/session_info.h
@@ -59,6 +59,7 @@
   // Returns the number of bytes deleted from the session.
   int MakeDecodable();
   int SessionLength() const;
+  bool HaveFirstPacket() const;
   bool HaveLastPacket() const;
   bool session_nack() const;
   webrtc::FrameType FrameType() const { return frame_type_; }