summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c')
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c1027
1 files changed, 1027 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c
new file mode 100755
index 0000000..2a81c4a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c
@@ -0,0 +1,1027 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdInterPrediction
+ MvPrediction16x16
+ MvPrediction16x8
+ MvPrediction8x16
+ MvPrediction8x8
+ MvPrediction
+ MedianFilter
+ GetInterNeighbour
+ GetPredictionMv
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_inter_prediction.h"
+#include "h264bsd_neighbour.h"
+#include "h264bsd_util.h"
+#include "h264bsd_reconstruct.h"
+#include "h264bsd_dpb.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ u32 available;
+ u32 refIndex;
+ mv_t mv;
+} interNeighbour_t;
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred,
+ u32 mbPartIdx, u32 subMbPartIdx);
+static i32 MedianFilter(i32 a, i32 b, i32 c);
+
+static void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
+ interNeighbour_t *n, u32 index);
+static void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex);
+
+static const neighbour_t N_A_SUB_PART[4][4][4] = {
+ { { {MB_A,5}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,5}, {MB_A,7}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,5}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2} } },
+
+ { { {MB_CURR,1}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,1}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,1}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6} } },
+
+ { { {MB_A,13}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,13}, {MB_A,15}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,13}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10} } },
+
+ { { {MB_CURR,9}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,9}, {MB_CURR,11}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,9}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,9}, {MB_CURR,12}, {MB_CURR,11}, {MB_CURR,14} } } };
+
+static const neighbour_t N_B_SUB_PART[4][4][4] = {
+ { { {MB_B,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,10}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,10}, {MB_B,11}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1} } },
+
+ { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_B,15}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5} } },
+
+ { { {MB_CURR,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,2}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,2}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9} } },
+
+ { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_CURR,7}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12}, {MB_CURR,13} } } };
+
+static const neighbour_t N_C_SUB_PART[4][4][4] = {
+ { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_NA,4}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4} } },
+
+ { { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,15}, {MB_C,10}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0} } },
+
+ { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_NA,12}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12} } },
+
+ { { {MB_NA,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_NA,2}, {MB_NA,8}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,7}, {MB_NA,2}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13}, {MB_NA,8} } } };
+
+static const neighbour_t N_D_SUB_PART[4][4][4] = {
+ { { {MB_D,15}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_D,15}, {MB_A,5}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_D,15}, {MB_B,10}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0} } },
+
+ { { {MB_B,11}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_CURR,1}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4} } },
+
+ { { {MB_A,7}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,7}, {MB_A,13}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,7}, {MB_CURR,2}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8} } },
+
+ { { {MB_CURR,3}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,9}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12} } } };
+
+
+#ifdef H264DEC_OMXDL
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterPrediction
+
+ Functional description:
+ Processes one inter macroblock. Performs motion vector prediction
+ and reconstructs prediction macroblock. Writes the final macroblock
+ (prediction + residual) into the output image (currImage)
+
+ Inputs:
+ pMb pointer to macroblock specific information
+ pMbLayer pointer to current macroblock data from stream
+ dpb pointer to decoded picture buffer
+ mbNum current macroblock number
+ currImage pointer to output image
+ data pointer where predicted macroblock will be stored
+
+ Outputs:
+ pMb structure is updated with current macroblock
+ currImage current macroblock is written into image
+ data prediction is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in motion vector prediction
+
+------------------------------------------------------------------------------*/
+u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 x, y;
+ u32 colAndRow;
+ subMbPartMode_e subPartMode;
+ image_t refImage;
+ u8 fillBuff[32*21 + 15 + 32];
+ u8 *pFill;
+ u32 tmp;
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
+ ASSERT(pMbLayer);
+
+ /* 16-byte alignment */
+ pFill = ALIGN(fillBuff, 16);
+
+ /* set row bits 15:0 */
+ colAndRow = mbNum / currImage->width;
+ /*set col to bits 31:16 */
+ colAndRow += (mbNum - colAndRow * currImage->width) << 16;
+ colAndRow <<= 4;
+
+ refImage.width = currImage->width;
+ refImage.height = currImage->height;
+
+ switch (pMb->mbType)
+ {
+ case P_Skip:
+ case P_L0_16x16:
+ if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ tmp = (0<<24) + (0<<16) + (16<<8) + 16;
+ h264bsdPredictSamples(data, pMb->mv, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case P_L0_L0_16x8:
+ if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ tmp = (0<<24) + (0<<16) + (16<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv, &refImage,
+ colAndRow, tmp, pFill);
+
+ refImage.data = pMb->refAddr[2];
+ tmp = (0<<24) + (8<<16) + (16<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+8, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case P_L0_L0_8x16:
+ if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ tmp = (0<<24) + (0<<16) + (8<<8) + 16;
+ h264bsdPredictSamples(data, pMb->mv, &refImage,
+ colAndRow, tmp, pFill);
+ refImage.data = pMb->refAddr[1];
+ tmp = (8<<24) + (0<<16) + (8<<8) + 16;
+ h264bsdPredictSamples(data, pMb->mv+4, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ default: /* P_8x8 and P_8x8ref0 */
+ if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ for (i = 0; i < 4; i++)
+ {
+ refImage.data = pMb->refAddr[i];
+ subPartMode =
+ h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
+ x = i & 0x1 ? 8 : 0;
+ y = i < 2 ? 0 : 8;
+ switch (subPartMode)
+ {
+ case MB_SP_8x8:
+ tmp = (x<<24) + (y<<16) + (8<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case MB_SP_8x4:
+ tmp = (x<<24) + (y<<16) + (8<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = (x<<24) + ((y+4)<<16) + (8<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case MB_SP_4x8:
+ tmp = (x<<24) + (y<<16) + (4<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ default:
+ tmp = (x<<24) + (y<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = (x<<24) + ((y+4)<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = ((x+4)<<24) + ((y+4)<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+ }
+ }
+ break;
+ }
+
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ return HANTRO_OK;
+
+ return(HANTRO_OK);
+}
+
+#else /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterPrediction
+
+ Functional description:
+ Processes one inter macroblock. Performs motion vector prediction
+ and reconstructs prediction macroblock. Writes the final macroblock
+ (prediction + residual) into the output image (currImage)
+
+ Inputs:
+ pMb pointer to macroblock specific information
+ pMbLayer pointer to current macroblock data from stream
+ dpb pointer to decoded picture buffer
+ mbNum current macroblock number
+ currImage pointer to output image
+ data pointer where predicted macroblock will be stored
+
+ Outputs:
+ pMb structure is updated with current macroblock
+ currImage current macroblock is written into image
+ data prediction is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in motion vector prediction
+
+------------------------------------------------------------------------------*/
+u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 x, y;
+ u32 row, col;
+ subMbPartMode_e subPartMode;
+ image_t refImage;
+
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
+ ASSERT(pMbLayer);
+
+ row = mbNum / currImage->width;
+ col = mbNum - row * currImage->width;
+ row *= 16;
+ col *= 16;
+
+ refImage.width = currImage->width;
+ refImage.height = currImage->height;
+
+ switch (pMb->mbType)
+ {
+ case P_Skip:
+ case P_L0_16x16:
+ if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
+ 16, 16);
+ break;
+
+ case P_L0_L0_16x8:
+ if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
+ 16, 8);
+ refImage.data = pMb->refAddr[2];
+ h264bsdPredictSamples(data, pMb->mv+8, &refImage, col, row, 0, 8,
+ 16, 8);
+ break;
+
+ case P_L0_L0_8x16:
+ if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
+ 8, 16);
+ refImage.data = pMb->refAddr[1];
+ h264bsdPredictSamples(data, pMb->mv+4, &refImage, col, row, 8, 0,
+ 8, 16);
+ break;
+
+ default: /* P_8x8 and P_8x8ref0 */
+ if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ for (i = 0; i < 4; i++)
+ {
+ refImage.data = pMb->refAddr[i];
+ subPartMode =
+ h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
+ x = i & 0x1 ? 8 : 0;
+ y = i < 2 ? 0 : 8;
+ switch (subPartMode)
+ {
+ case MB_SP_8x8:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 8, 8);
+ break;
+
+ case MB_SP_8x4:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 8, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ col, row, x, y+4, 8, 4);
+ break;
+
+ case MB_SP_4x8:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 4, 8);
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ col, row, x+4, y, 4, 8);
+ break;
+
+ default:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 4, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ col, row, x+4, y, 4, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ col, row, x, y+4, 4, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
+ col, row, x+4, y+4, 4, 4);
+ break;
+ }
+ }
+ break;
+ }
+
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ return HANTRO_OK;
+
+ if (pMb->mbType != P_Skip)
+ {
+ h264bsdWriteOutputBlocks(currImage, mbNum, data,
+ pMbLayer->residual.level);
+ }
+ else
+ {
+ h264bsdWriteMacroblock(currImage, data);
+ }
+
+ return(HANTRO_OK);
+}
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction16x16
+
+ Functional description:
+ Motion vector prediction for 16x16 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ mv_t mv;
+ mv_t mvPred;
+ interNeighbour_t a[3]; /* A, B, C */
+ u32 refIndex;
+ u8 *tmp;
+ u32 *tmpMv1, *tmpMv2;
+
+/* Code */
+
+ refIndex = mbPred->refIdxL0[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
+ /*lint --e(740) Unusual pointer cast (incompatible indirect types) */
+ tmpMv1 = (u32*)(&a[0].mv); /* we test just that both MVs are zero */
+ /*lint --e(740) */
+ tmpMv2 = (u32*)(&a[1].mv); /* i.e. a[0].mv.hor == 0 && a[0].mv.ver == 0 */
+ if (pMb->mbType == P_Skip &&
+ (!a[0].available || !a[1].available ||
+ ( a[0].refIndex == 0 && ((u32)(*tmpMv1) == 0) ) ||
+ ( a[1].refIndex == 0 && ((u32)(*tmpMv2) == 0) )))
+ {
+ mv.hor = mv.ver = 0;
+ }
+ else
+ {
+ mv = mbPred->mvdL0[0];
+ GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75]
+ * (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
+ pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
+ pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
+ pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
+
+ pMb->refPic[0] = refIndex;
+ pMb->refPic[1] = refIndex;
+ pMb->refPic[2] = refIndex;
+ pMb->refPic[3] = refIndex;
+ pMb->refAddr[0] = tmp;
+ pMb->refAddr[1] = tmp;
+ pMb->refAddr[2] = tmp;
+ pMb->refAddr[3] = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction16x8
+
+ Functional description:
+ Motion vector prediction for 16x8 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ mv_t mv;
+ mv_t mvPred;
+ interNeighbour_t a[3]; /* A, B, C */
+ u32 refIndex;
+ u8 *tmp;
+
+/* Code */
+
+ mv = mbPred->mvdL0[0];
+ refIndex = mbPred->refIdxL0[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
+
+ if (a[1].refIndex == refIndex)
+ mvPred = a[1].mv;
+ else
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
+ GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
+ pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = mv;
+ pMb->refPic[0] = refIndex;
+ pMb->refPic[1] = refIndex;
+ pMb->refAddr[0] = tmp;
+ pMb->refAddr[1] = tmp;
+
+ mv = mbPred->mvdL0[1];
+ refIndex = mbPred->refIdxL0[1];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 13);
+ if (a[0].refIndex == refIndex)
+ mvPred = a[0].mv;
+ else
+ {
+ a[1].available = HANTRO_TRUE;
+ a[1].refIndex = pMb->refPic[0];
+ a[1].mv = pMb->mv[0];
+
+ /* c is not available */
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a+2, 7);
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
+ pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
+ pMb->refPic[2] = refIndex;
+ pMb->refPic[3] = refIndex;
+ pMb->refAddr[2] = tmp;
+ pMb->refAddr[3] = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction8x16
+
+ Functional description:
+ Motion vector prediction for 8x16 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ mv_t mv;
+ mv_t mvPred;
+ interNeighbour_t a[3]; /* A, B, C */
+ u32 refIndex;
+ u8 *tmp;
+
+/* Code */
+
+ mv = mbPred->mvdL0[0];
+ refIndex = mbPred->refIdxL0[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
+
+ if (a[0].refIndex == refIndex)
+ mvPred = a[0].mv;
+ else
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 14);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
+ pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = mv;
+ pMb->refPic[0] = refIndex;
+ pMb->refPic[2] = refIndex;
+ pMb->refAddr[0] = tmp;
+ pMb->refAddr[2] = tmp;
+
+ mv = mbPred->mvdL0[1];
+ refIndex = mbPred->refIdxL0[1];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 11);
+ }
+ if (a[2].refIndex == refIndex)
+ mvPred = a[2].mv;
+ else
+ {
+ a[0].available = HANTRO_TRUE;
+ a[0].refIndex = pMb->refPic[0];
+ a[0].mv = pMb->mv[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 14);
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
+ pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
+ pMb->refPic[1] = refIndex;
+ pMb->refPic[3] = refIndex;
+ pMb->refAddr[1] = tmp;
+ pMb->refAddr[3] = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction8x8
+
+ Functional description:
+ Motion vector prediction for 8x8 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ u32 i, j;
+ u32 numSubMbPart;
+
+/* Code */
+
+ for (i = 0; i < 4; i++)
+ {
+ numSubMbPart = h264bsdNumSubMbPart(subMbPred->subMbType[i]);
+ pMb->refPic[i] = subMbPred->refIdxL0[i];
+ pMb->refAddr[i] = h264bsdGetRefPicData(dpb, subMbPred->refIdxL0[i]);
+ if (pMb->refAddr[i] == NULL)
+ return(HANTRO_NOK);
+ for (j = 0; j < numSubMbPart; j++)
+ {
+ if (MvPrediction(pMb, subMbPred, i, j) != HANTRO_OK)
+ return(HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction
+
+ Functional description:
+ Perform motion vector prediction for sub-partition
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred, u32 mbPartIdx,
+ u32 subMbPartIdx)
+{
+
+/* Variables */
+
+ mv_t mv, mvPred;
+ u32 refIndex;
+ subMbPartMode_e subMbPartMode;
+ const neighbour_t *n;
+ mbStorage_t *nMb;
+ interNeighbour_t a[3]; /* A, B, C */
+
+/* Code */
+
+ mv = subMbPred->mvdL0[mbPartIdx][subMbPartIdx];
+ subMbPartMode = h264bsdSubMbPartMode(subMbPred->subMbType[mbPartIdx]);
+ refIndex = subMbPred->refIdxL0[mbPartIdx];
+
+ n = N_A_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a, n->index);
+
+ n = N_B_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a+1, n->index);
+
+ n = N_C_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
+
+ if (!a[2].available)
+ {
+ n = N_D_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if (((u32)(i32)(mv.hor+8192) >= (16384)))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if (((u32)(i32)(mv.ver+2048) >= (4096)))
+ return(HANTRO_NOK);
+
+ switch (subMbPartMode)
+ {
+ case MB_SP_8x8:
+ pMb->mv[4*mbPartIdx] = mv;
+ pMb->mv[4*mbPartIdx + 1] = mv;
+ pMb->mv[4*mbPartIdx + 2] = mv;
+ pMb->mv[4*mbPartIdx + 3] = mv;
+ break;
+
+ case MB_SP_8x4:
+ pMb->mv[4*mbPartIdx + 2*subMbPartIdx] = mv;
+ pMb->mv[4*mbPartIdx + 2*subMbPartIdx + 1] = mv;
+ break;
+
+ case MB_SP_4x8:
+ pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
+ pMb->mv[4*mbPartIdx + subMbPartIdx + 2] = mv;
+ break;
+
+ case MB_SP_4x4:
+ pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
+ break;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MedianFilter
+
+ Functional description:
+ Median filtering for motion vector prediction
+
+------------------------------------------------------------------------------*/
+
+i32 MedianFilter(i32 a, i32 b, i32 c)
+{
+
+/* Variables */
+
+ i32 max,min,med;
+
+/* Code */
+
+ max = min = med = a;
+ if (b > max)
+ {
+ max = b;
+ }
+ else if (b < min)
+ {
+ min = b;
+ }
+ if (c > max)
+ {
+ med = max;
+ }
+ else if (c < min)
+ {
+ med = min;
+ }
+ else
+ {
+ med = c;
+ }
+
+ return(med);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetInterNeighbour
+
+ Functional description:
+ Get availability, reference index and motion vector of a neighbour
+
+------------------------------------------------------------------------------*/
+
+void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
+ interNeighbour_t *n, u32 index)
+{
+
+ n->available = HANTRO_FALSE;
+ n->refIndex = 0xFFFFFFFF;
+ n->mv.hor = n->mv.ver = 0;
+
+ if (nMb && (sliceId == nMb->sliceId))
+ {
+ u32 tmp;
+ mv_t tmpMv;
+
+ tmp = nMb->mbType;
+ n->available = HANTRO_TRUE;
+ /* MbPartPredMode "inlined" */
+ if (tmp <= P_8x8ref0)
+ {
+ tmpMv = nMb->mv[index];
+ tmp = nMb->refPic[index>>2];
+ n->refIndex = tmp;
+ n->mv = tmpMv;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetPredictionMv
+
+ Functional description:
+ Compute motion vector predictor based on neighbours A, B and C
+
+------------------------------------------------------------------------------*/
+
+void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex)
+{
+
+ if ( a[1].available || a[2].available || !a[0].available)
+ {
+ u32 isA, isB, isC;
+ isA = (a[0].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
+ isB = (a[1].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
+ isC = (a[2].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (((u32)isA+(u32)isB+(u32)isC) != 1)
+ {
+ mv->hor = (i16)MedianFilter(a[0].mv.hor, a[1].mv.hor, a[2].mv.hor);
+ mv->ver = (i16)MedianFilter(a[0].mv.ver, a[1].mv.ver, a[2].mv.ver);
+ }
+ else if (isA)
+ *mv = a[0].mv;
+ else if (isB)
+ *mv = a[1].mv;
+ else
+ *mv = a[2].mv;
+ }
+ else
+ {
+ *mv = a[0].mv;
+ }
+
+}
+
+