libmix: A fix to enable range mapped feature for VC1

BZ: 129080

In VC1 advanced profile, if one syntax element Range Mapping
Luma Flag is present in Entry Point Header and equals 1, scaling
should be performed after all other decoding stage (including loop-filter)
have been performed. If out-of-loop post-processing is done on the render target,
then we need to keep the in-loop decoded picture as a reference picture.
However, video decoder failed to keep in-loop decoded picture.

Change-Id: I0f163982fc9e8c30071c651670c6154bbf76596e
Signed-off-by: Tianmi Chen <tianmi.chen@intel.com>
Reviewed-on: http://android.intel.com:8080/134060
Reviewed-by: Shi, PingX <pingx.shi@intel.com>
Tested-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: cactus <cactus@intel.com>
Tested-by: cactus <cactus@intel.com>
diff --git a/videodecoder/VideoDecoderBase.cpp b/videodecoder/VideoDecoderBase.cpp
index f2d72d6..6509e01 100755
--- a/videodecoder/VideoDecoderBase.cpp
+++ b/videodecoder/VideoDecoderBase.cpp
@@ -702,7 +702,7 @@
 }
 
 
-Decode_Status VideoDecoderBase::setupVA(int32_t numSurface, VAProfile profile) {
+Decode_Status VideoDecoderBase::setupVA(int32_t numSurface, VAProfile profile, int32_t numExtraSurface) {
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     Decode_Status status;
     VAConfigAttrib attrib;
@@ -789,7 +789,9 @@
     }
 
     mNumSurfaces = numSurface;
-    mSurfaces = new VASurfaceID [mNumSurfaces];
+    mNumExtraSurfaces = numExtraSurface;
+    mSurfaces = new VASurfaceID [mNumSurfaces + mNumExtraSurfaces];
+    mExtraSurfaces = mSurfaces + mNumSurfaces;
     if (mSurfaces == NULL) {
         return DECODE_MEMORY_FAIL;
     }
@@ -846,6 +848,19 @@
     }
     CHECK_VA_STATUS("vaCreateSurfaces");
 
+    if (mNumExtraSurfaces != 0) {
+        vaStatus = vaCreateSurfaces(
+            mVADisplay,
+            format,
+            mVideoFormatInfo.width,
+            mVideoFormatInfo.height,
+            mExtraSurfaces,
+            mNumExtraSurfaces,
+            NULL,
+            0);
+        CHECK_VA_STATUS("vaCreateSurfaces");
+    }
+
     mVideoFormatInfo.surfaceNumber = mNumSurfaces;
     mVideoFormatInfo.ctxSurfaces = mSurfaces;
 
@@ -857,7 +872,7 @@
                 mVideoFormatInfo.height,
                 0,
                 mSurfaces,
-                mNumSurfaces,
+                mNumSurfaces + mNumExtraSurfaces,
                 &mVAContext);
         CHECK_VA_STATUS("vaCreateContext");
     }
@@ -924,7 +939,7 @@
 
     if (mSurfaces)
     {
-        vaDestroySurfaces(mVADisplay, mSurfaces, mNumSurfaces);
+        vaDestroySurfaces(mVADisplay, mSurfaces, mNumSurfaces + mNumExtraSurfaces);
         delete [] mSurfaces;
         mSurfaces = NULL;
     }
diff --git a/videodecoder/VideoDecoderBase.h b/videodecoder/VideoDecoderBase.h
index cb88622..eab4058 100644
--- a/videodecoder/VideoDecoderBase.h
+++ b/videodecoder/VideoDecoderBase.h
@@ -79,7 +79,7 @@
     virtual VideoSurfaceBuffer* findOutputByPoc(bool draining = false);
     virtual VideoSurfaceBuffer* findOutputByPct(bool draining = false);
     virtual VideoSurfaceBuffer* findOutputByPts(bool draining = false);
-    virtual Decode_Status setupVA(int32_t numSurface, VAProfile profile);
+    virtual Decode_Status setupVA(int32_t numSurface, VAProfile profile, int32_t numExtraSurface = 0);
     virtual Decode_Status terminateVA(void);
     virtual Decode_Status parseBuffer(uint8_t *buffer, int32_t size, bool config, void** vbpData);
 
@@ -107,6 +107,8 @@
     VADisplay mVADisplay;
     VAContextID mVAContext;
     VAConfigID mVAConfig;
+    VASurfaceID *mExtraSurfaces; // extra surfaces array
+    int32_t mNumExtraSurfaces;
     bool mVAStarted;
     uint64_t mCurrentPTS; // current presentation time stamp (unit is unknown, depend on the framework: GStreamer 100-nanosec, Android: microsecond)
     // the following three member variables should be set using
diff --git a/videodecoder/VideoDecoderWMV.cpp b/videodecoder/VideoDecoderWMV.cpp
index 7bb9ece..41b3cda 100644
--- a/videodecoder/VideoDecoderWMV.cpp
+++ b/videodecoder/VideoDecoderWMV.cpp
@@ -30,7 +30,11 @@
     : VideoDecoderBase(mimeType, VBP_VC1),
       mBufferIDs(NULL),
       mNumBufferIDs(0),
-      mConfigDataParsed(false) {
+      mConfigDataParsed(false),
+      mRangeMapped(false),
+      mDeblockedCurrPicIndex(0),
+      mDeblockedLastPicIndex(1),
+      mDeblockedForwardPicIndex(2) {
 }
 
 
@@ -64,12 +68,22 @@
     }
     mNumBufferIDs = 0;
     mConfigDataParsed = false;
+    mRangeMapped = false;
+
+    mDeblockedCurrPicIndex = 0;
+    mDeblockedLastPicIndex = 1;
+    mDeblockedForwardPicIndex = 2;
 
     VideoDecoderBase::stop();
 }
 
 void VideoDecoderWMV::flush(void) {
     VideoDecoderBase::flush();
+
+    mRangeMapped = false;
+    mDeblockedCurrPicIndex = 0;
+    mDeblockedLastPicIndex = 1;
+    mDeblockedForwardPicIndex = 2;
 }
 
 Decode_Status VideoDecoderWMV::decode(VideoDecodeBuffer *buffer) {
@@ -152,6 +166,9 @@
     } else {
         mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
     }
+
+    mRangeMapped = (data->se_data->RANGE_MAPY_FLAG || data->se_data->RANGE_MAPUV_FLAG || data->se_data->RANGERED);
+
     int frameType = data->pic_data[0].pic_parms->picture_fields.bits.picture_type;
     mAcquiredBuffer->referenceFrame = (frameType == VC1_PTYPE_I || frameType == VC1_PTYPE_P);
 
@@ -166,6 +183,10 @@
         }
     }
 
+    if (mRangeMapped) {
+        updateDeblockedPicIndexes(frameType);
+    }
+
     // let outputSurfaceBuffer handle "asReference" for VC1
     status = outputSurfaceBuffer();
     return status;
@@ -189,9 +210,9 @@
     status = setReference(picParams, picIndex, mAcquiredBuffer->renderBuffer.surface);
     CHECK_STATUS("setReference");
 
-    if (data->se_data->LOOPFILTER) {
-        //Loop filter handling
-        picParams->inloop_decoded_picture = mAcquiredBuffer->renderBuffer.surface;
+    if (mRangeMapped) {
+        // keep the destination surface for the picture after decoding and in-loop filtering
+        picParams->inloop_decoded_picture = mExtraSurfaces[mDeblockedCurrPicIndex];
     } else {
         picParams->inloop_decoded_picture = VA_INVALID_SURFACE;
     }
@@ -334,6 +355,21 @@
     return DECODE_SUCCESS;
 }
 
+void VideoDecoderWMV::updateDeblockedPicIndexes(int frameType) {
+    int32_t curPicIndex = mDeblockedCurrPicIndex;
+
+    /* Out Loop (range map) buffers */
+    if (frameType != VC1_PTYPE_SKIPPED) {
+        if ((frameType == VC1_PTYPE_I) || (frameType == VC1_PTYPE_P)) {
+            mDeblockedCurrPicIndex = mDeblockedLastPicIndex;
+            mDeblockedLastPicIndex = curPicIndex;
+        } else {
+            mDeblockedCurrPicIndex = mDeblockedForwardPicIndex;
+            mDeblockedForwardPicIndex = curPicIndex;
+        }
+    }
+}
+
 Decode_Status VideoDecoderWMV::updateConfigData(
         uint8_t *configData,
         int32_t configDataLen,
@@ -393,7 +429,7 @@
         break;
     }
 
-    return VideoDecoderBase::setupVA(VC1_SURFACE_NUMBER, vaProfile);
+    return VideoDecoderBase::setupVA(VC1_SURFACE_NUMBER, vaProfile, VC1_EXTRA_SURFACE_NUMBER);
 }
 
 void VideoDecoderWMV::updateFormatInfo(vbp_data_vc1 *data) {
diff --git a/videodecoder/VideoDecoderWMV.h b/videodecoder/VideoDecoderWMV.h
index e1b0f99..6a4a6bb 100644
--- a/videodecoder/VideoDecoderWMV.h
+++ b/videodecoder/VideoDecoderWMV.h
@@ -42,6 +42,7 @@
     Decode_Status decodeFrame(VideoDecodeBuffer *buffer, vbp_data_vc1 *data);
     Decode_Status decodePicture(vbp_data_vc1 *data, int32_t picIndex);
     Decode_Status setReference(VAPictureParameterBufferVC1 *params, int32_t picIndex, VASurfaceID current);
+    void updateDeblockedPicIndexes(int frameType);
     Decode_Status updateConfigData(uint8_t *configData, int32_t configDataLen, uint8_t **newConfigData, int32_t *newConfigDataLen);
     Decode_Status startVA(vbp_data_vc1 *data);
     void updateFormatInfo(vbp_data_vc1 *data);
@@ -51,11 +52,17 @@
 private:
     enum {
         VC1_SURFACE_NUMBER = 10,
+        VC1_EXTRA_SURFACE_NUMBER = 3,
     };
 
     VABufferID *mBufferIDs;
     int32_t mNumBufferIDs;
     bool mConfigDataParsed;
+    bool mRangeMapped;
+
+    int32_t mDeblockedCurrPicIndex;
+    int32_t mDeblockedLastPicIndex;
+    int32_t mDeblockedForwardPicIndex;
 };