libmix: fix the wrong reference frame issue when the POC of successive frames are same

BZ: 118207 122198

Fix this wrong reference frame issue by looking up latest ref frame in the DPB with specified
POC in case successive frames have same POC

Orig-Change-Id: I09f80dab92e720314db7f48a0eeaebcad1f73d7d
Orig-Change-Id: I30f10a8f2662e3aaa001388096c843a6846fcde4

Change-Id: Ifaea1ab43c6a8f7452e6e9a84c6c6f6aa98ed9de
Signed-off-by: ywan171 <yi.a.wang@intel.com>
Reviewed-on: http://android.intel.com:8080/119118
Reviewed-by: Shi, PingX <pingx.shi@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 5730795..530d8c9 100644
--- a/videodecoder/VideoDecoderAVC.cpp
+++ b/videodecoder/VideoDecoderAVC.cpp
@@ -414,7 +414,8 @@
             continue;
         }
         dpb->poc = getPOC(ref);
-        dpb->surfaceBuffer = findSurfaceBuffer(ref);
+        // looking for the latest ref frame in the DPB with specified POC, in case frames have same POC
+        dpb->surfaceBuffer = findRefSurfaceBuffer(ref);
         if (dpb->surfaceBuffer == NULL) {
             ETRACE("Reference frame %d is missing for current frame %d", dpb->poc, getPOC(&(picParam->CurrPic)));
             if (dpb->poc == getPOC(&(picParam->CurrPic))) {
@@ -568,6 +569,24 @@
             return dpb->surfaceBuffer;
         }
     }
+    // ETRACE("Unable to find surface for poc %d", getPOC(pic));
+    return NULL;
+}
+
+VideoSurfaceBuffer* VideoDecoderAVC::findRefSurfaceBuffer(VAPictureH264 *pic) {
+    DecodedPictureBuffer *dpb = mDPBs[mToggleDPB];
+    // always looking for the latest one in the DPB, in case ref frames have same POC
+    dpb += (DPB_SIZE - 1);
+    for (int32_t i = DPB_SIZE; i > 0; i--, dpb--) {
+        if (dpb->poc == pic->BottomFieldOrderCnt ||
+            dpb->poc == pic->TopFieldOrderCnt) {
+            // TODO: remove these debugging codes
+            if (dpb->surfaceBuffer == NULL) {
+                ETRACE("Invalid surface buffer in the DPB for poc %d.", getPOC(pic));
+            }
+            return dpb->surfaceBuffer;
+        }
+    }
     ETRACE("Unable to find surface for poc %d", getPOC(pic));
     return NULL;
 }
diff --git a/videodecoder/VideoDecoderAVC.h b/videodecoder/VideoDecoderAVC.h
index 799ae2e..9c23e6b 100644
--- a/videodecoder/VideoDecoderAVC.h
+++ b/videodecoder/VideoDecoderAVC.h
@@ -50,6 +50,7 @@
     inline uint32_t getPOC(VAPictureH264 *pic); // Picture Order Count
     inline VASurfaceID findSurface(VAPictureH264 *pic);
     inline VideoSurfaceBuffer* findSurfaceBuffer(VAPictureH264 *pic);
+    inline VideoSurfaceBuffer* findRefSurfaceBuffer(VAPictureH264 *pic);
     inline void invalidateDPB(int toggle);
     inline void clearAsReference(int toggle);
     Decode_Status startVA(vbp_data_h264 *data);