shithub: openh264

Download patch

ref: 5b12578960b1a9cbb009a4ed2ffb41459345ec71
parent: 5a1aedb622fa15f0d6fb9fbf8306e7cf9312972a
parent: 9ef0c74fdd58b076377bf20aef0a79ee5f8a271e
author: dongzha <dongzha@cisco.com>
date: Wed Mar 4 09:58:40 EST 2015

Merge pull request #1829 from syureyi/wp_p

Decoder WP support

--- a/codec/decoder/core/inc/dec_frame.h
+++ b/codec/decoder/core/inc/dec_frame.h
@@ -102,7 +102,9 @@
   int32_t					iInterLayerSliceBetaOffset;
   //SPosOffset			sScaledRefLayer;
   int32_t					iSliceGroupChangeCycle;
+  
   PRefPicListReorderSyn	pRefPicListReordering;
+  PPredWeightTabSyn     pPredWeightTable;
   PRefPicMarking          pRefPicMarking; // Decoded reference picture marking syntaxs
   PRefBasePicMarking	    pRefPicBaseMarking;
 
@@ -109,6 +111,7 @@
   PPicture				pRef;			// reference picture pointer
   PPicture				pDec;			// reconstruction picture pointer for layer
 
+    bool    bUseWeightPredictionFlag;
   bool					bStoreRefBasePicFlag;				// iCurTid == 0 && iCurQid = 0 && bEncodeKeyPic = 1
   bool					bTCoeffLevelPredFlag;
   bool					bConstrainedIntraResamplingFlag;
--- a/codec/decoder/core/inc/error_code.h
+++ b/codec/decoder/core/inc/error_code.h
@@ -147,6 +147,13 @@
 ERR_INFO_INVALID_I16x16_PRED_MODE,
 ERR_INFO_INVALID_I_CHROMA_PRED_MODE,
 
+ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM,
+ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM,
+ERR_INFO_INVALID_LUMA_WEIGHT,
+ERR_INFO_INVALID_CHROMA_WEIGHT,
+ERR_INFO_INVALID_LUMA_OFFSET,
+ERR_INFO_INVALID_CHROMA_OFFSET,
+
 ERR_INFO_UNSUPPORTED_NON_BASELINE,
 ERR_INFO_UNSUPPORTED_FMOTYPE,
 ERR_INFO_UNSUPPORTED_MBAFF,
--- a/codec/decoder/core/inc/slice.h
+++ b/codec/decoder/core/inc/slice.h
@@ -68,7 +68,7 @@
   bool	bLumaWeightFlag;
   bool	bChromaWeightFlag;
 } sPredList[LIST_A];
-} SPredWeightTabSyn;
+} SPredWeightTabSyn,*PPredWeightTabSyn;
 
 /* Decoded reference picture marking syntax, refer to Page 66 in JVT X201wcm */
 typedef struct TagRefPicMarking {
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -1353,10 +1353,10 @@
   pPps->bWeightedPredFlag  = !!uiCode;
   WELS_READ_VERIFY (BsGetBits (pBsAux, 2, &uiCode)); //weighted_bipred_idc
   pPps->uiWeightedBipredIdc = uiCode;
-  if (pPps->bWeightedPredFlag || pPps->uiWeightedBipredIdc != 0) {
+  if (pPps->uiWeightedBipredIdc != 0) {
     WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
-             "ParsePps(): weighted_pred_flag (%d) weighted_bipred_idc (%d) neither supported.\n",
-             pPps->bWeightedPredFlag, pPps->uiWeightedBipredIdc);
+             "ParsePps(): weighted_bipred_idc (%d) not supported.\n",
+             pPps->uiWeightedBipredIdc);
     return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_WP);
   }
 
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -179,6 +179,78 @@
   return iRet;
 }
 
+int32_t ParsePredWeightedTable (PBitStringAux pBs, PSliceHeader pSh) {
+  uint32_t uiCode;
+  int32_t iList = 0;
+  int32_t iCode;
+
+  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
+  WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "luma_log2_weight_denom",
+                                  GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM));
+  pSh->sPredWeightTable.uiLumaLog2WeightDenom = uiCode;
+  if (pSh->pSps->uiChromaArrayType != 0) {
+    WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
+    WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "chroma_log2_weight_denom",
+                                    GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM));
+    pSh->sPredWeightTable.uiChromaLog2WeightDenom = uiCode;
+  }
+
+
+  do {
+
+    for (int i = 0; i < pSh->uiRefCount[iList]; i++) {
+      //luma
+      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
+      if (!!uiCode) {
+
+        WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
+        WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_weight",
+                                        GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_WEIGHT));
+        pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = iCode;
+
+        WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
+        WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_offset",
+                                        GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_OFFSET));
+        pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = iCode;
+      } else {
+        pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = 1 << (pSh->sPredWeightTable.uiLumaLog2WeightDenom);
+        pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = 0;
+
+      }
+      //chroma
+      if (pSh->pSps->uiChromaArrayType == 0)
+        continue;
+
+      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
+      if (!!uiCode) {
+        for (int j = 0; j < 2; j++) {
+
+
+          WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
+          WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_weight",
+                                          GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_WEIGHT));
+          pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = iCode;
+
+          WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
+          WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_offset",
+                                          GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_OFFSET));
+          pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = iCode;
+        }
+      } else {
+        for (int j = 0; j < 2; j++) {
+
+
+          pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = 1 << (pSh->sPredWeightTable.uiChromaLog2WeightDenom);
+          pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = 0;
+        }
+      }
+
+    }
+    ++iList;
+  } while (iList < LIST_1);//TODO: SUPPORT LIST_A
+  return ERR_NONE;
+}
+
 /*
  *	Predeclared function routines ..
  */
@@ -728,6 +800,14 @@
       return iRet;
     }
 
+    if (pPps->bWeightedPredFlag && (uiSliceType == P_SLICE)) {
+      iRet = ParsePredWeightedTable (pBs, pSliceHead);
+      if (iRet != ERR_NONE) {
+        WelsLog (pLogCtx, WELS_LOG_WARNING, "invalid weighted prediction syntaxs!");
+        return iRet;
+      }
+    }
+
     if (kbExtensionFlag) {
       if (pNalHeaderExt->iNoInterLayerPredFlag || pNalHeaderExt->uiQualityId > 0)
         pSliceHeadExt->bBasePredWeightTableFlag	= false;
@@ -1876,6 +1956,14 @@
   if (kuiQualityId == BASE_QUALITY_ID) {
     pDqLayer->pRefPicListReordering		= &pSh->pRefPicListReordering;
     pDqLayer->pRefPicMarking		= &pSh->sRefMarking;
+    
+    if (pSh->pPps->bWeightedPredFlag) {
+      pDqLayer->bUseWeightPredictionFlag = true;
+      pDqLayer->pPredWeightTable    = &pSh->sPredWeightTable;
+
+    } else
+      pDqLayer->bUseWeightPredictionFlag = false;
+
     pDqLayer->pRefPicBaseMarking	= &pShExt->sRefBasePicMarking;
   }
 
--- a/codec/decoder/core/src/rec_mb.cpp
+++ b/codec/decoder/core/src/rec_mb.cpp
@@ -186,7 +186,7 @@
 #define MC_FLOW_SIMPLE_JUDGE 1
 #endif //MC_FLOW_SIMPLE_JUDGE
 void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
-                           int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
+             int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
   int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel
   int32_t iFullMVy = (iYOffset << 2) + iMVs[1];
   iFullMVx = WELS_CLIP3 (iFullMVx, ((-PADDING_LENGTH + 2) << 2), ((pMCRefMem->iPicWidth + PADDING_LENGTH - 19) << 2));
@@ -214,6 +214,74 @@
 
 }
 
+void WeightPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, int32_t iRefIdx, int32_t iBlkWidth,
+                       int32_t iBlkHeight) {
+
+
+  int32_t iLog2denom, iWoc, iOoc;
+  int32_t iPredTemp, iLineStride;
+  int32_t iPixel = 0;
+  uint8_t* pDst;
+  //luma
+  iLog2denom = pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom;
+  iWoc = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iLumaWeight[iRefIdx];
+  iOoc = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iLumaOffset[iRefIdx];
+  iLineStride = pMCRefMem->iDstLineLuma;
+
+  for (int i = 0; i < iBlkHeight; i++) {
+    for (int j = 0; j < iBlkWidth; j++) {
+      iPixel = j + i * (iLineStride);
+      if (iLog2denom >= 1) {
+        iPredTemp = ((pMCRefMem->pDstY[iPixel] * iWoc + (1 << (iLog2denom - 1))) >> iLog2denom) + iOoc;
+
+        pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+      } else {
+        iPredTemp = pMCRefMem->pDstY[iPixel] * iWoc + iOoc;
+
+        pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+
+      }
+    }
+  }
+
+
+  //UV
+  iBlkWidth = iBlkWidth >> 2;
+  iBlkHeight = iBlkHeight >> 2;
+  iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
+  iLineStride = pMCRefMem->iDstLineChroma;
+
+  for (int i = 0; i < 2; i++) {
+
+
+    //iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
+    iWoc =  pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iChromaWeight[iRefIdx][i];
+    iOoc = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iChromaOffset[iRefIdx][i];
+    pDst = i ? pMCRefMem->pDstV : pMCRefMem->pDstU;
+    //iLineStride = pMCRefMem->iDstLineChroma;
+
+    for (int i = 0; i < iBlkHeight ; i++) {
+      for (int j = 0; j < iBlkWidth; j++) {
+        iPixel = j + i * (iLineStride);
+        if (iLog2denom >= 1) {
+          iPredTemp = ((pDst[iPixel] * iWoc + (1 << (iLog2denom - 1))) >> iLog2denom) + iOoc;
+
+          pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+        } else {
+          iPredTemp = pDst[iPixel] * iWoc + iOoc;
+
+          pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+
+        }
+      }
+
+    }
+
+
+  }
+}
+
+
 void GetInterPred (uint8_t* pPredY, uint8_t* pPredCb, uint8_t* pPredCr, PWelsDecoderContext pCtx) {
   sMCRefMember pMCRefMem;
   PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
@@ -242,6 +310,9 @@
 
   pMCRefMem.iDstLineLuma   = iDstLineLuma;
   pMCRefMem.iDstLineChroma = iDstLineChroma;
+
+  int32_t iRefIndex = 0;
+
   switch (iMBType) {
   case MB_TYPE_SKIP:
   case MB_TYPE_16x16:
@@ -249,6 +320,11 @@
     iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
     GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0);
     BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
+
+    if (pCurDqLayer->bUseWeightPredictionFlag) {
+      iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
+      WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 16, 16);
+    }
     break;
   case MB_TYPE_16x8:
     iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
@@ -256,6 +332,11 @@
     GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0);
     BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 8, iMVs);
 
+    if (pCurDqLayer->bUseWeightPredictionFlag) {
+      iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
+      WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 16, 8);
+    }
+
     iMVs[0] = pCurDqLayer->pMv[0][iMBXY][8][0];
     iMVs[1] = pCurDqLayer->pMv[0][iMBXY][8][1];
     GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 8);
@@ -263,6 +344,11 @@
     pMCRefMem.pDstU = pPredCb + (iDstLineChroma << 2);
     pMCRefMem.pDstV = pPredCr + (iDstLineChroma << 2);
     BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY + 8, pMCFunc, 16, 8, iMVs);
+
+    if (pCurDqLayer->bUseWeightPredictionFlag) {
+      iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][8];
+      WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 16, 8);
+    }
     break;
   case MB_TYPE_8x16:
     iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
@@ -269,6 +355,10 @@
     iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
     GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0);
     BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 8, 16, iMVs);
+    if (pCurDqLayer->bUseWeightPredictionFlag) {
+      iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
+      WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 8, 16);
+    }
 
     iMVs[0] = pCurDqLayer->pMv[0][iMBXY][2][0];
     iMVs[1] = pCurDqLayer->pMv[0][iMBXY][2][1];
@@ -277,6 +367,11 @@
     pMCRefMem.pDstU = pPredCb + 4;
     pMCRefMem.pDstV = pPredCr + 4;
     BaseMC (&pMCRefMem, iMBOffsetX + 8, iMBOffsetY, pMCFunc, 8, 16, iMVs);
+
+    if (pCurDqLayer->bUseWeightPredictionFlag) {
+      iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][2];
+      WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 8, 16);
+    }
     break;
   case MB_TYPE_8x8:
   case MB_TYPE_8x8_REF0: {
@@ -292,6 +387,7 @@
 
       iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
       GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], iIIdx);
+      iRefIndex = pCurDqLayer->bUseWeightPredictionFlag ? pCurDqLayer->pRefIndex[0][iMBXY][iIIdx] : 0;
 
       pDstY = pPredY + iBlk8X + iBlk8Y * iDstLineLuma;
       pDstU = pPredCb + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
@@ -304,12 +400,22 @@
         iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
         iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
         BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
+        if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+          WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 8, 8);
+        }
+
         break;
       case SUB_MB_TYPE_8x4:
         iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
         iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
         BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
+        if (pCurDqLayer->bUseWeightPredictionFlag) {
 
+          WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 8, 4);
+        }
+
+
         iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 4][0];
         iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 4][1];
         pMCRefMem.pDstY += (iDstLineLuma << 2);
@@ -316,12 +422,22 @@
         pMCRefMem.pDstU += (iDstLineChroma << 1);
         pMCRefMem.pDstV += (iDstLineChroma << 1);
         BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
+        if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+          WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 8, 4);
+        }
+
         break;
       case SUB_MB_TYPE_4x8:
         iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
         iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
         BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
+        if (pCurDqLayer->bUseWeightPredictionFlag) {
 
+          WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 4, 8);
+        }
+
+
         iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 1][0];
         iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 1][1];
         pMCRefMem.pDstY += 4;
@@ -328,6 +444,11 @@
         pMCRefMem.pDstU += 2;
         pMCRefMem.pDstV += 2;
         BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
+        if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+          WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 4, 8);
+        }
+
         break;
       case SUB_MB_TYPE_4x4: {
         for (j = 0; j < 4; j++) {
@@ -345,6 +466,11 @@
           iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + iJIdx][0];
           iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + iJIdx][1];
           BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
+          if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+            WeightPrediction (pCurDqLayer, &pMCRefMem, iRefIndex, 4, 4);
+          }
+
         }
       }
       break;