libmix: Allocate video decoder's output buffers based on the real needs

BZ: 116761

Change-Id: I4124a337c2f0fb9153728e8a51be5a6412e9b5a8
Signed-off-by: Dan Liang <dan.liang@intel.com>
Reviewed-on: http://android.intel.com:8080/114245
Reviewed-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: cactus <cactus@intel.com>
Tested-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
diff --git a/videodecoder/VideoDecoderAVC.cpp b/videodecoder/VideoDecoderAVC.cpp
index 15328bd..5730795 100644
--- a/videodecoder/VideoDecoderAVC.cpp
+++ b/videodecoder/VideoDecoderAVC.cpp
@@ -593,7 +593,6 @@
 
 Decode_Status VideoDecoderAVC::startVA(vbp_data_h264 *data) {
     int32_t DPBSize = getDPBSize(data);
-    updateFormatInfo(data);
 
     //Use high profile for all kinds of H.264 profiles (baseline, main and high) except for constrained baseline
     VAProfile vaProfile = VAProfileH264High;
@@ -607,6 +606,7 @@
     }
 
     VideoDecoderBase::setOutputWindowSize(DPBSize);
+    updateFormatInfo(data);
 
    // for 1080p, limit the total surface to 19, according the hardware limitation
    // change the max surface number from 19->10 to workaround memory shortage
@@ -677,6 +677,17 @@
         data->codec_data->crop_right,
         data->codec_data->crop_bottom);
 
+    // The number of actual buffer needed is
+    // outputQueue + nativewindow_owned + (diff > 0 ? diff : 1) + widi_need_max + 1(available buffer)
+    // while outputQueue = DPB < 8? DPB :8
+    // and diff = Reference + 1 - ouputQueue
+    int diff = data->codec_data->num_ref_frames + 1 - mOutputWindowSize;
+    mVideoFormatInfo.actualBufferNeeded = mOutputWindowSize + 4 /* Owned by native window */
+                                          + (diff > 0 ? diff : 1)
+                                          + 6 /* WiDi maximum needs */
+                                          + 1;
+    ITRACE("actualBufferNeeded =%d", mVideoFormatInfo.actualBufferNeeded);
+
     mVideoFormatInfo.valid = true;
 }
 
diff --git a/videodecoder/VideoDecoderBase.cpp b/videodecoder/VideoDecoderBase.cpp
index ea3ce25..2379eaa 100755
--- a/videodecoder/VideoDecoderBase.cpp
+++ b/videodecoder/VideoDecoderBase.cpp
@@ -708,6 +708,9 @@
     }
 
     if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER){
+        if (mVideoFormatInfo.actualBufferNeeded > mConfigBuffer.surfaceNumber)
+            return DECODE_FORMAT_CHANGE;
+
         numSurface = mConfigBuffer.surfaceNumber;
         // if format has been changed in USE_NATIVE_GRAPHIC_BUFFER mode,
         // we can not setupVA here when the graphic buffer resolution is smaller than the resolution decoder really needs
diff --git a/videodecoder/VideoDecoderBase.h b/videodecoder/VideoDecoderBase.h
index 2f45fec..f0c60cf 100644
--- a/videodecoder/VideoDecoderBase.h
+++ b/videodecoder/VideoDecoderBase.h
@@ -114,6 +114,8 @@
     bool mSizeChanged; // indicate whether video size is changed.
     bool mShowFrame; // indicate whether the decoded frame is for display
 
+    int32_t mOutputWindowSize; // indicate limit of number of outstanding frames for output
+
     enum {
         // TODO: move this to vbp_loader.h
         VBP_INVALID = 0xFF,
@@ -135,7 +137,6 @@
     bool mRawOutput; // whether to output NV12 raw data
     bool mManageReference;  // this should stay true for VC1/MP4 decoder, and stay false for AVC decoder. AVC  handles reference frame using DPB
     OUTPUT_METHOD mOutputMethod;
-    int32_t mOutputWindowSize; // indicate limit of number of outstanding frames for output
 
     int32_t mNumSurfaces;
     VideoSurfaceBuffer *mSurfaceBuffers;
diff --git a/videodecoder/VideoDecoderDefs.h b/videodecoder/VideoDecoderDefs.h
index b527577..672020c 100644
--- a/videodecoder/VideoDecoderDefs.h
+++ b/videodecoder/VideoDecoderDefs.h
@@ -179,6 +179,7 @@
     int32_t bitrate;
     int32_t framerateNom;
     int32_t framerateDenom;
+    int32_t actualBufferNeeded;
     VideoExtensionBuffer *ext;
 };