Fix H.264 HW decoding for Qualcomm KK devices.

- Qualcomm H.264 HW decoder on KK and older requires
a few video frames before it can generate output. Increase
maximum allowed pending frames for H.264 decoder to 30.
Plus changes in the logging to track decoder buffers
timestamps.

R=wzh@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8490}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8490 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/java/jni/androidmediacodeccommon.h b/talk/app/webrtc/java/jni/androidmediacodeccommon.h
index d19d1a4..23f6c52 100644
--- a/talk/app/webrtc/java/jni/androidmediacodeccommon.h
+++ b/talk/app/webrtc/java/jni/androidmediacodeccommon.h
@@ -65,9 +65,13 @@
 // Arbitrary interval to poll the codec for new outputs.
 enum { kMediaCodecPollMs = 10 };
 // Media codec maximum output buffer ready timeout.
-enum { kMediaCodecTimeoutMs = 500 };
+enum { kMediaCodecTimeoutMs = 1000 };
 // Interval to print codec statistics (bitrate, fps, encoding/decoding time).
 enum { kMediaCodecStatisticsIntervalMs = 3000 };
+// Maximum amount of pending frames for VP8 decoder.
+enum { kMaxPendingFramesVp8 = 1 };
+// Maximum amount of pending frames for H.264 decoder.
+enum { kMaxPendingFramesH264 = 30 };
 
 static inline int64_t GetCurrentTimeMs() {
   return webrtc::TickTime::Now().Ticks() / 1000000LL;
diff --git a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
index db0c49a..8824863 100644
--- a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
+++ b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
@@ -315,9 +315,15 @@
   }
   inited_ = true;
 
-  max_pending_frames_ = 0;
-  if (use_surface_) {
-    max_pending_frames_ = 1;
+  switch (codecType_) {
+    case kVideoCodecVP8:
+      max_pending_frames_ = kMaxPendingFramesVp8;
+      break;
+    case kVideoCodecH264:
+      max_pending_frames_ = kMaxPendingFramesH264;
+      break;
+    default:
+      max_pending_frames_ = 0;
   }
   start_time_ms_ = GetCurrentTimeMs();
   current_frames_ = 0;
@@ -436,7 +442,8 @@
   // Try to drain the decoder and wait until output is not too
   // much behind the input.
   if (frames_received_ > frames_decoded_ + max_pending_frames_) {
-    ALOGV("Wait for output...");
+    ALOGV("Received: %d. Decoded: %d. Wait for output...",
+        frames_received_, frames_decoded_);
     if (!DeliverPendingOutputs(jni, kMediaCodecTimeoutMs * 1000)) {
       error_count_++;
       Reset();
@@ -475,9 +482,10 @@
     Reset();
     return WEBRTC_VIDEO_CODEC_ERROR;
   }
-  ALOGV("Decoder frame in # %d. Type: %d. Buffer # %d. Size: %d",
-      frames_received_, inputImage._frameType,
-      j_input_buffer_index, inputImage._length);
+  jlong timestamp_us = (frames_received_ * 1000000) / codec_.maxFramerate;
+  ALOGV("Decoder frame in # %d. Type: %d. Buffer # %d. TS: %lld. Size: %d",
+      frames_received_, inputImage._frameType, j_input_buffer_index,
+      timestamp_us / 1000, inputImage._length);
   memcpy(buffer, inputImage._buffer, inputImage._length);
 
   // Save input image timestamps for later output.
@@ -488,7 +496,6 @@
   frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
 
   // Feed input to decoder.
-  jlong timestamp_us = (frames_received_ * 1000000) / codec_.maxFramerate;
   bool success = jni->CallBooleanMethod(*j_media_codec_video_decoder_,
                                         j_queue_input_buffer_method_,
                                         j_input_buffer_index,
@@ -541,6 +548,9 @@
       GetIntField(jni, j_decoder_output_buffer_info, j_info_offset_field_);
   int output_buffer_size =
       GetIntField(jni, j_decoder_output_buffer_info, j_info_size_field_);
+  long output_timestamps_ms = GetLongField(jni, j_decoder_output_buffer_info,
+      j_info_presentation_timestamp_us_field_) / 1000;
+
   CHECK_EXCEPTION(jni);
 
   // Get decoded video frame properties.
@@ -610,9 +620,9 @@
     frame_decoding_time_ms = GetCurrentTimeMs() - frame_rtc_times_ms_.front();
     frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
   }
-  ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. Size: %d."
+  ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. TS: %ld."
       " DecTime: %lld", frames_decoded_, width, height, stride, slice_height,
-      color_format, output_buffer_size, frame_decoding_time_ms);
+      color_format, output_timestamps_ms, frame_decoding_time_ms);
 
   // Return output buffer back to codec.
   bool success = jni->CallBooleanMethod(
diff --git a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
index 7ac88ed..1ba6843 100644
--- a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
+++ b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
@@ -41,7 +41,6 @@
 import android.opengl.GLES11Ext;
 import android.opengl.GLES20;
 import android.os.Build;
-import android.os.Bundle;
 import android.util.Log;
 import android.view.Surface;
 
@@ -465,10 +464,10 @@
           result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
         if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
           outputBuffers = mediaCodec.getOutputBuffers();
-          Log.d(TAG, "Output buffers changed: " + outputBuffers.length);
+          Log.d(TAG, "Decoder output buffers changed: " + outputBuffers.length);
         } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
           MediaFormat format = mediaCodec.getOutputFormat();
-          Log.d(TAG, "Format changed: " + format.toString());
+          Log.d(TAG, "Decoder format changed: " + format.toString());
           width = format.getInteger(MediaFormat.KEY_WIDTH);
           height = format.getInteger(MediaFormat.KEY_HEIGHT);
           if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {