shithub: openh264

Download patch

ref: 8af088af93490de580881e038d04ab3269435c22
parent: 3bcf6069ab6751bbfac8c23a061bae03900a5957
parent: 7e9fdc181f05264fd471800e139bb362ded59fcc
author: Guangwei Wang <guangwwa@cisco.com>
date: Wed Dec 9 06:36:02 EST 2015

merge changed Makefile to master

--- a/codec/decoder/core/inc/decoder.h
+++ b/codec/decoder/core/inc/decoder.h
@@ -55,6 +55,11 @@
 int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpParam);
 
 /*!
+ * \brief   fill in default values of decoder context
+ */
+void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx);
+
+/*!
  *************************************************************************************
  * \brief   Initialize Wels decoder parameters and memory
  *
@@ -68,7 +73,7 @@
  * \note    N/A
  *************************************************************************************
  */
-int32_t WelsInitDecoder (PWelsDecoderContext pCtx, const bool bParseOnly, SLogContext* pLogCtx);
+int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx);
 
 /*!
  *************************************************************************************
@@ -110,9 +115,9 @@
 
 
 /*
- *  free memory blocks in avc
+ *  free memory dynamically allocated during decoder
  */
-void WelsFreeMem (PWelsDecoderContext pCtx);
+void WelsFreeDynamicMemory (PWelsDecoderContext pCtx);
 
 /*!
  * \brief   make sure synchonozization picture resolution (get from slice header) among different parts (i.e, memory related and so on)
@@ -125,7 +130,19 @@
  */
 int32_t SyncPictureResolutionExt (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight);
 
-void AssignFuncPointerForRec (PWelsDecoderContext pCtx);
+/*!
+ * \brief   init decoder predictive function pointers including ASM functions during MB reconstruction
+ * \param   pCtx        Wels decoder context
+ * \param   uiCpuFlag   cpu assembly indication
+ */
+void InitPredFunc (PWelsDecoderContext pCtx, uint32_t uiCpuFlag);
+
+/*!
+ * \brief   init decoder internal function pointers including ASM functions
+ * \param   pCtx        Wels decoder context
+ * \param   uiCpuFlag   cpu assembly indication
+ */
+void InitDecFuncs (PWelsDecoderContext pCtx, uint32_t uiCpuFlag);
 
 void GetVclNalTemporalId (PWelsDecoderContext pCtx); //get the info that whether or not have VCL NAL in current AU,
 //and if YES, get the temporal ID
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -375,7 +375,6 @@
   ERROR_CON_IDC eErrorConMethod; //
 
 //for Parse only
-  bool bParseOnly;
   bool bFramePending;
   bool bFrameFinish;
   int32_t iNalNum;
--- a/codec/decoder/core/inc/decoder_core.h
+++ b/codec/decoder/core/inc/decoder_core.h
@@ -72,21 +72,21 @@
 int32_t CheckBsBuffer (PWelsDecoderContext pCtx, const int32_t kiSrcLen);
 
 /*
- * WelsInitMemory
- * Memory request for introduced data
+ * WelsInitStaticMemory
+ * Memory request for introduced data at decoder start
  * Especially for:
  * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache.
  * return:
  *  0 - success; otherwise returned error_no defined in error_no.h.
  */
-int32_t WelsInitMemory (PWelsDecoderContext pCtx);
+int32_t WelsInitStaticMemory (PWelsDecoderContext pCtx);
 
 /*
- * WelsFreeMemory
- * Free memory introduced in WelsInitMemory at destruction of decoder.
+ * WelsFreeStaticMemory
+ * Free memory introduced in WelsInitStaticMemory at destruction of decoder.
  *
  */
-void WelsFreeMemory (PWelsDecoderContext pCtx);
+void WelsFreeStaticMemory (PWelsDecoderContext pCtx);
 
 /*!
  * \brief   request memory when maximal picture width and height are available
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -317,7 +317,7 @@
       iNalSize        -= NAL_UNIT_HEADER_EXT_SIZE;
       *pConsumedBytes += NAL_UNIT_HEADER_EXT_SIZE;
 
-      if (pCtx->bParseOnly) {
+      if (pCtx->pParam->bParseOnly) {
         pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
         int32_t iTrailingZeroByte = 0;
         while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) //remove final trailing 0 bytes
@@ -346,7 +346,7 @@
         pSavedData->pCurPos += iActualLen - iOffset;
       }
     } else {
-      if (pCtx->bParseOnly) {
+      if (pCtx->pParam->bParseOnly) {
         pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
         int32_t iTrailingZeroByte = 0;
         while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) //remove final trailing 0 bytes
@@ -1119,7 +1119,7 @@
   WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //vui_parameters_present_flag
   pSps->bVuiParamPresentFlag = !!uiCode;
 
-  if (pCtx->bParseOnly) {
+  if (pCtx->pParam->bParseOnly) {
     if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //sps bs exceeds!
       pCtx->iErrorCode |= dsOutOfMemory;
       return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
@@ -1422,7 +1422,7 @@
     memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
     pCtx->bPpsAvailFlags[uiPpsId] = true;
   }
-  if (pCtx->bParseOnly) {
+  if (pCtx->pParam->bParseOnly) {
     if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //pps bs exceeds
       pCtx->iErrorCode |= dsOutOfMemory;
       return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
--- a/codec/decoder/core/src/decode_slice.cpp
+++ b/codec/decoder/core/src/decode_slice.cpp
@@ -90,7 +90,7 @@
       break;
     }
 
-    if (!pCtx->bParseOnly) { //for parse only, actual recon MB unnecessary
+    if (!pCtx->pParam->bParseOnly) { //for parse only, actual recon MB unnecessary
       if (WelsTargetMbConstruction (pCtx)) {
         WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
                  "WelsTargetSliceConstruction():::MB(%d, %d) construction error. pCurSlice_type:%d",
@@ -134,7 +134,7 @@
   if ((pCurSlice->eSliceType != I_SLICE) && (pCurSlice->eSliceType != P_SLICE))
     return 0;
 
-  if (pCtx->bParseOnly) //for parse only, deblocking should not go on
+  if (pCtx->pParam->bParseOnly) //for parse only, deblocking should not go on
     return 0;
 
   pDeblockMb = WelsDeblockingMb;
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -272,14 +272,13 @@
   pPicBuf = NULL;
   *ppPicBuf = NULL;
 }
+
 /*
  * fill data fields in default for decoder context
  */
-void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx, CMemoryAlign* pMa) {
+void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
   int32_t iCpuCores               = 1;
-  memset (pCtx, 0, sizeof (SWelsDecoderContext));       // fill zero first
   pCtx->sLogCtx = *pLogCtx;
-  pCtx->pMemAlign = pMa;
 
   pCtx->pArgDec                   = NULL;
 
@@ -441,18 +440,20 @@
 }
 
 /*
- *  free memory blocks in avc
+ *  free memory dynamically allocated during decoder
  */
-void WelsFreeMem (PWelsDecoderContext pCtx) {
+void WelsFreeDynamicMemory (PWelsDecoderContext pCtx) {
   int32_t iListIdx = 0;
   CMemoryAlign* pMa = pCtx->pMemAlign;
 
-  /* TODO: free memory blocks introduced in avc */
+  //free dq layer memory
+  UninitialDqLayersContext (pCtx);
+
+  //free FMO memory
   ResetFmoList (pCtx);
 
+  //free ref-pic list & picture memory
   WelsResetRefPic (pCtx);
-
-  // for sPicBuff
   for (iListIdx = LIST_0; iListIdx < LIST_A; ++ iListIdx) {
     PPicBuff* pPicBuff = &pCtx->pPicBuff[iListIdx];
     if (NULL != pPicBuff && NULL != *pPicBuff) {
@@ -467,6 +468,8 @@
   pCtx->iLastImgHeightInPixel = 0;
   pCtx->bFreezeOutput = true;
   pCtx->bHaveGotMemory = false;
+
+  //free CABAC memory
   pMa->WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
 }
 
@@ -474,19 +477,15 @@
  * \brief   Open decoder
  */
 int32_t WelsOpenDecoder (PWelsDecoderContext pCtx) {
-  // function pointers
-  //initial MC function pointer--
   int iRet = ERR_NONE;
-  InitMcFunc (& (pCtx->sMcFunc), pCtx->uiCpuFlag);
+  // function pointers
+  InitDecFuncs (pCtx, pCtx->uiCpuFlag);
 
-  InitExpandPictureFunc (& (pCtx->sExpandPicFunc), pCtx->uiCpuFlag);
-  AssignFuncPointerForRec (pCtx);
-
   // vlc tables
   InitVlcTable (&pCtx->sVlcTable);
 
-  // startup memory
-  iRet = WelsInitMemory (pCtx);
+  // static memory
+  iRet = WelsInitStaticMemory (pCtx);
   if (ERR_NONE != iRet)
     return iRet;
 
@@ -506,12 +505,10 @@
  * \brief   Close decoder
  */
 void WelsCloseDecoder (PWelsDecoderContext pCtx) {
-  WelsFreeMem (pCtx);
+  WelsFreeDynamicMemory (pCtx);
 
-  WelsFreeMemory (pCtx);
+  WelsFreeStaticMemory (pCtx);
 
-  UninitialDqLayersContext (pCtx);
-
 #ifdef LONG_TERM_REF
   pCtx->bParamSetsLostFlag       = false;
 #else
@@ -539,7 +536,7 @@
   }
   pCtx->eErrorConMethod = pCtx->pParam->eEcActiveIdc;
 
-  if (pCtx->bParseOnly) //parse only, disable EC method
+  if (pCtx->pParam->bParseOnly) //parse only, disable EC method
     pCtx->eErrorConMethod = ERROR_CON_DISABLE;
   InitErrorCon (pCtx);
 
@@ -567,15 +564,11 @@
  * \note    N/A
  *************************************************************************************
  */
-int32_t WelsInitDecoder (PWelsDecoderContext pCtx, const bool bParseOnly, SLogContext* pLogCtx) {
+int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
   if (pCtx == NULL) {
     return ERR_INFO_INVALID_PTR;
   }
 
-  // default
-  WelsDecoderDefaults (pCtx, pLogCtx, pCtx->pMemAlign);
-
-  pCtx->bParseOnly = bParseOnly;
   // open decoder
   return WelsOpenDecoder (pCtx);
 }
@@ -652,7 +645,7 @@
       pRawData->pCurPos = pRawData->pHead;
     }
 
-    if (pCtx->bParseOnly) {
+    if (pCtx->pParam->bParseOnly) {
       pSavedData = &pCtx->sSavedData;
       if ((kiBsLen + 4) > (pSavedData->pEnd - pSavedData->pCurPos)) {
         pSavedData->pCurPos = pSavedData->pHead;
@@ -847,7 +840,15 @@
   return iErr;
 }
 
-void AssignFuncPointerForRec (PWelsDecoderContext pCtx) {
+void InitDecFuncs (PWelsDecoderContext pCtx, uint32_t uiCpuFlag) {
+  WelsBlockFuncInit (&pCtx->sBlockFunc, uiCpuFlag);
+  InitPredFunc (pCtx, uiCpuFlag);
+  InitMcFunc (& (pCtx->sMcFunc), uiCpuFlag);
+  InitExpandPictureFunc (& (pCtx->sExpandPicFunc), uiCpuFlag);
+  DeblockingInit (&pCtx->sDeblockingFunc, uiCpuFlag);
+}
+
+void InitPredFunc (PWelsDecoderContext pCtx, uint32_t uiCpuFlag) {
   pCtx->pGetI16x16LumaPredFunc[I16_PRED_V     ] = WelsI16x16LumaPredV_c;
   pCtx->pGetI16x16LumaPredFunc[I16_PRED_H     ] = WelsI16x16LumaPredH_c;
   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC    ] = WelsI16x16LumaPredDc_c;
@@ -899,7 +900,7 @@
   pCtx->pIdctResAddPredFunc8x8  = IdctResAddPred8x8_c;
 
 #if defined(HAVE_NEON)
-  if (pCtx->uiCpuFlag & WELS_CPU_NEON) {
+  if (uiCpuFlag & WELS_CPU_NEON) {
     pCtx->pIdctResAddPredFunc   = IdctResAddPred_neon;
 
     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_neon;
@@ -924,7 +925,7 @@
 #endif//HAVE_NEON
 
 #if defined(HAVE_NEON_AARCH64)
-  if (pCtx->uiCpuFlag & WELS_CPU_NEON) {
+  if (uiCpuFlag & WELS_CPU_NEON) {
     pCtx->pIdctResAddPredFunc   = IdctResAddPred_AArch64_neon;
 
     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_AArch64_neon;
@@ -954,7 +955,7 @@
 #endif//HAVE_NEON_AARCH64
 
 #if defined(X86_ASM)
-  if (pCtx->uiCpuFlag & WELS_CPU_MMXEXT) {
+  if (uiCpuFlag & WELS_CPU_MMXEXT) {
     pCtx->pIdctResAddPredFunc   = IdctResAddPred_mmx;
 
     ///////mmx code opt---
@@ -969,7 +970,7 @@
     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL]  = WelsDecoderI4x4LumaPredDDL_mmx;
     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL ]  = WelsDecoderI4x4LumaPredVL_mmx;
   }
-  if (pCtx->uiCpuFlag & WELS_CPU_SSE2) {
+  if (uiCpuFlag & WELS_CPU_SSE2) {
     /////////sse2 code opt---
     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_sse2;
     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_sse2;
@@ -983,9 +984,6 @@
     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H]     = WelsDecoderI4x4LumaPredH_sse2;
   }
 #endif
-  DeblockingInit (&pCtx->sDeblockingFunc, pCtx->uiCpuFlag);
-
-  WelsBlockFuncInit (&pCtx->sBlockFunc, pCtx->uiCpuFlag);
 }
 
 //reset decoder number related statistics info
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -72,7 +72,7 @@
     }
   }
 
-  if (pCtx->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo
+  if (pCtx->pParam->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo
     PAccessUnit pCurAu = pCtx->pAccessUnitList;
     if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer
       SParserBsInfo* pParser = pCtx->pParserBsInfo;
@@ -467,7 +467,7 @@
   }
   pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead;
   pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte;
-  if (pCtx->bParseOnly) {
+  if (pCtx->pParam->bParseOnly) {
     pCtx->pParserBsInfo = static_cast<SParserBsInfo*> (pMa->WelsMallocz (sizeof (SParserBsInfo), "pCtx->pParserBsInfo"));
     if (pCtx->pParserBsInfo == NULL) {
       return ERR_INFO_OUT_OF_MEMORY;
@@ -538,7 +538,7 @@
 }
 
 /*
- * WelsInitMemory
+ * WelsInitStaticMemory
  * Memory request for new introduced data
  * Especially for:
  * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache.
@@ -545,7 +545,7 @@
  * return:
  *  0 - success; otherwise returned error_no defined in error_no.h.
 */
-int32_t WelsInitMemory (PWelsDecoderContext pCtx) {
+int32_t WelsInitStaticMemory (PWelsDecoderContext pCtx) {
   if (pCtx == NULL) {
     return ERR_INFO_INVALID_PTR;
   }
@@ -563,22 +563,16 @@
 }
 
 /*
- * WelsFreeMemory
- * Free memory introduced in WelsInitMemory at destruction of decoder.
+ * WelsFreeStaticMemory
+ * Free memory introduced in WelsInitStaticMemory at destruction of decoder.
  *
  */
-void WelsFreeMemory (PWelsDecoderContext pCtx) {
+void WelsFreeStaticMemory (PWelsDecoderContext pCtx) {
   if (pCtx == NULL)
     return;
 
   CMemoryAlign* pMa = pCtx->pMemAlign;
 
-  if (NULL != pCtx->pParam) {
-    pMa->WelsFree (pCtx->pParam, "pCtx->pParam");
-
-    pCtx->pParam = NULL;
-  }
-
   MemFreeNalList (&pCtx->pAccessUnitList, pMa);
 
   if (pCtx->sRawData.pHead) {
@@ -588,7 +582,7 @@
   pCtx->sRawData.pEnd                 = NULL;
   pCtx->sRawData.pStartPos            = NULL;
   pCtx->sRawData.pCurPos              = NULL;
-  if (pCtx->bParseOnly) {
+  if (pCtx->pParam->bParseOnly) {
     if (pCtx->sSavedData.pHead) {
       pMa->WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData->pHead");
     }
@@ -605,6 +599,12 @@
       pCtx->pParserBsInfo = NULL;
     }
   }
+
+  if (NULL != pCtx->pParam) {
+    pMa->WelsFree (pCtx->pParam, "pCtx->pParam");
+
+    pCtx->pParam = NULL;
+  }
 }
 /*
  *  DecodeNalHeaderExt
@@ -723,8 +723,9 @@
   pSliceHead->eSliceType = static_cast <EWelsSliceType> (uiSliceType);
 
   WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_parameter_set_id
-  WELS_CHECK_SE_UPPER_ERROR (uiCode, (MAX_PPS_COUNT - 1), "iPpsId out of range", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
-                             ERR_INFO_PPS_ID_OVERFLOW));
+  WELS_CHECK_SE_UPPER_ERROR (uiCode, (MAX_PPS_COUNT - 1), "iPpsId out of range",
+                             GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
+                                 ERR_INFO_PPS_ID_OVERFLOW));
   iPpsId = uiCode;
 
   //add check PPS available here
@@ -1974,7 +1975,7 @@
 
   if (ERR_NONE != iErr) {
     ForceResetCurrentAccessUnit (pCtx->pAccessUnitList);
-    if (!pCtx->bParseOnly)
+    if (!pCtx->pParam->bParseOnly)
       pDstInfo->iBufferStatus = 0;
     pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin;
     pCtx->bNextNewSeqBegin = false; // reset it
@@ -2339,7 +2340,7 @@
 
     if (dq_cur->uiLayerDqId == kuiTargetLayerDqId) {
       if (!pCtx->bInstantDecFlag) {
-        if (!pCtx->bParseOnly) {
+        if (!pCtx->pParam->bParseOnly) {
           //Do error concealment here
           if ((NeedErrorCon (pCtx)) && (pCtx->eErrorConMethod != ERROR_CON_DISABLE)) {
             ImplementErrorCon (pCtx);
@@ -2365,7 +2366,7 @@
             return iRet;
           }
         }
-        if (!pCtx->bParseOnly)
+        if (!pCtx->pParam->bParseOnly)
           ExpandReferencingPicture (pCtx->pDec->pData, pCtx->pDec->iWidthInPixel, pCtx->pDec->iHeightInPixel,
                                     pCtx->pDec->iLinesize,
                                     pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture);
@@ -2421,7 +2422,7 @@
       if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
         MarkECFrameAsRef (pCtx);
       }
-    } else if (pCtx->bParseOnly) { //clear parse only internal data status
+    } else if (pCtx->pParam->bParseOnly) { //clear parse only internal data status
       pCtx->pParserBsInfo->iNalNum = 0;
       pCtx->bFrameFinish = true; //clear frame pending status here!
     } else {
--- a/codec/decoder/core/src/pic_queue.cpp
+++ b/codec/decoder/core/src/pic_queue.cpp
@@ -83,7 +83,7 @@
   iLumaSize     = iPicWidth * iPicHeight;
   iChromaSize   = iPicChromaWidth * iPicChromaHeight;
 
-  if (pCtx->bParseOnly) {
+  if (pCtx->pParam->bParseOnly) {
     pPic->pBuffer[0] = pPic->pBuffer[1] = pPic->pBuffer[2] = NULL;
     pPic->pData[0] = pPic->pData[1] = pPic->pData[2] = NULL;
     pPic->iLinesize[0] = iPicWidth;
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -243,6 +243,7 @@
            "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
            VERSION_NUMBER, (int32_t)pParam->bParseOnly);
 
+  //reset decoder context
   if (m_pDecContext) //free
     UninitDecoder();
   m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
@@ -252,8 +253,8 @@
   m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize);
   WELS_VERIFY_RETURN_PROC_IF (1, (NULL == m_pDecContext->pMemAlign), UninitDecoder())
 
-  WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (m_pDecContext, pParam->bParseOnly,
-                              &m_pWelsTrace->m_sLogCtx), UninitDecoder())
+  //fill in default value into context
+  WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
 
   //check param and update decoder context
   m_pDecContext->pParam = (SDecodingParam*) m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
@@ -262,6 +263,9 @@
   int32_t iRet = DecoderConfigParam (m_pDecContext, pParam);
   WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
 
+  //init decoder
+  WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx), UninitDecoder())
+
   return cmResultSuccess;
 }
 
@@ -304,7 +308,7 @@
 
     iVal = * ((int*)pOption); // int value for error concealment idc
     iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
-    if ((m_pDecContext->bParseOnly) && (iVal != (int32_t) ERROR_CON_DISABLE)) {
+    if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t) ERROR_CON_DISABLE)) {
       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
                "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
       return cmInitParaError;
@@ -438,7 +442,7 @@
     const int kiSrcLen,
     unsigned char** ppDst,
     SBufferInfo* pDstInfo) {
-  if (m_pDecContext->bParseOnly) {
+  if (m_pDecContext->pParam->bParseOnly) {
     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
     m_pDecContext->iErrorCode |= dsInvalidArgument;
     return dsInvalidArgument;
@@ -583,7 +587,7 @@
 DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
     const int kiSrcLen,
     SParserBsInfo* pDstInfo) {
-  if (!m_pDecContext->bParseOnly) {
+  if (!m_pDecContext->pParam->bParseOnly) {
     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
     m_pDecContext->iErrorCode |= dsInvalidArgument;
     return dsInvalidArgument;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -1792,7 +1792,7 @@
   iCountBsLen = iNonVclLayersBsSizeCount + iVclLayersBsSizeCount;
 
   iMaxSliceBufferSize = WELS_MIN (iMaxSliceBufferSize, iTargetSpatialBsSize);
-  iTotalLength = (pParam->iMultipleThreadIdc == 1) ? iCountBsLen : (iCountBsLen + ((*ppCtx)->iMaxSliceCount - 1) *
+  iTotalLength = (pParam->iMultipleThreadIdc == 1) ? iCountBsLen : (iCountBsLen + (*ppCtx)->iMaxSliceCount  *
                  iMaxSliceBufferSize);
 
   pParam->iNumRefFrame = WELS_CLIP3 (pParam->iNumRefFrame, MIN_REF_PIC_COUNT,
@@ -3998,7 +3998,6 @@
         pLayerBsInfo->uiTemporalId  = pCtx->uiTemporalId;
         pLayerBsInfo->uiQualityId   = 0;
         pLayerBsInfo->iNalCount     = 0;
-        pCtx->pSliceBs[0].pBs = pLayerBsInfo->pBsBuf;
 
         pCtx->pTaskManage->ExecuteTasks();
         iLayerSize = AppendSliceToFrameBs (pCtx, pLayerBsInfo, iSliceCount);
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -259,8 +259,8 @@
     return ENC_RETURN_UNEXPECTED;
   }
   //slice 0
-  (*ppCtx)->pSliceBs[0].uiSize = iSlice0Len;
-  (*ppCtx)->pSliceBs[0].pBs    = (*ppCtx)->pFrameBs;
+  (*ppCtx)->pSliceBs[0].uiSize = iSlice1Len;
+  (*ppCtx)->pSliceBs[0].pBs    = (*ppCtx)->pFrameBs + iSlice0Len;
   (*ppCtx)->pSliceBs[0].uiBsPos = 0;
   (*ppCtx)->pSliceBs[0].pBsBuffer = pSmt->pThreadBsBuffer[0];
   if ((iMaxSliceNum == 1) && (!bDynamicSlice)) {
@@ -524,13 +524,11 @@
         assert (pSliceBs->bSliceCodedFlag);
 #endif//MT_DEBUG_BS_WR
 
-        if (iSliceIdx > 0) {
-          // pSlice 0 bs has been written to pFrameBs yet by now, so uiSliceIdx base should be 1
-          memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage
-          pCtx->iPosBsBuffer += pSliceBs->uiBsPos;
+        memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage
+        pCtx->iPosBsBuffer += pSliceBs->uiBsPos;
 
-          iLayerSize += pSliceBs->uiBsPos;
-        }
+        iLayerSize += pSliceBs->uiBsPos;
+
         while (iNalIdx < iCountNal) {
           pLbi->pNalLengthInByte[iNalIdxBase + iNalIdx] = pSliceBs->iNalLen[iNalIdx];
           ++ iNalIdx;
@@ -555,10 +553,8 @@
       while (iIdx < kiCountSlicesCoded) {
         pSliceBs = &pCtx->pSliceBs[iSliceIdx];
         if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) {
-          if (iSliceIdx > 0) {
-            memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage
-            pCtx->iPosBsBuffer += pSliceBs->uiBsPos;
-          }
+          memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage
+          pCtx->iPosBsBuffer += pSliceBs->uiBsPos;
 
           const int32_t iCountNal = pSliceBs->iNalIndex;
           iLayerSize += pSliceBs->uiBsPos;
@@ -586,8 +582,7 @@
   int32_t iNalIdx               = 0;
   int32_t iNalSize              = 0;
   int32_t iReturn               = ENC_RETURN_SUCCESS;
-  int32_t iTotalLeftLength      = (iSliceIdx > 0) ? (pSliceBs->uiSize - pSliceBs->uiBsPos)
-                                  : (pCtx->iFrameBsSize - pCtx->iPosBsBuffer);
+  int32_t iTotalLeftLength      = pSliceBs->uiSize - pSliceBs->uiBsPos;
   SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
   uint8_t* pDst                 = pSliceBs->pBs;
 
@@ -720,9 +715,6 @@
                                         pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                         iEventIdx);
         }
-        if (0 == iSliceIdx) {
-          pEncPEncCtx->iPosBsBuffer += iSliceSize;
-        }
 
         pEncPEncCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx);
 
@@ -822,9 +814,6 @@
                                           pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                           iEventIdx);
           }
-          if (0 == iSliceIdx) {
-            pEncPEncCtx->iPosBsBuffer += iSliceSize;
-          }
 
           pEncPEncCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx);
 
@@ -936,7 +925,6 @@
   pLbi->uiTemporalId  = pCtx->uiTemporalId;
   pLbi->uiQualityId   = 0;
   pLbi->iNalCount     = 0;
-  pCtx->pSliceBs[0].pBs = pLbi->pBsBuf;
 
   iIdx = 0;
   while (iIdx < kiEventCnt) {
--- a/codec/encoder/core/src/wels_task_encoder.cpp
+++ b/codec/encoder/core/src/wels_task_encoder.cpp
@@ -174,9 +174,6 @@
              m_iSliceIdx);
     return iReturn;
   }
-  if (0 == m_iSliceIdx) {
-    m_pCtx->iPosBsBuffer += m_iSliceSize;
-  }
 
   m_pCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (m_pCtx->pCurDqLayer, m_pCtx->pFuncList, m_iSliceIdx);
 
--- a/module/gmp-openh264.cpp
+++ b/module/gmp-openh264.cpp
@@ -187,7 +187,8 @@
     encoder_ (nullptr),
     max_payload_size_ (0),
     callback_ (nullptr),
-    stats_ ("Encoder") {
+    stats_ ("Encoder"),
+    shutting_down(false) {
       AddRef();
     }
 
@@ -361,6 +362,8 @@
   }
 
   virtual void EncodingComplete() {
+    shutting_down = true;
+
     // Release the reference to the external objects, because it is no longer safe to call them
     host_     = nullptr;
     callback_ = nullptr;
@@ -389,6 +392,12 @@
      }
    }
 
+  void TrySyncRunOnMainThread(GMPTask* aTask) {
+    if (!shutting_down && g_platform_api) {
+      g_platform_api->syncrunonmainthread (aTask);
+    }
+  }
+
   void Error (GMPErr error) {
     if (callback_) {
       callback_->Error (error);
@@ -466,20 +475,20 @@
 
     if (!has_frame) {
       // This frame must be destroyed on the main thread.
-      g_platform_api->syncrunonmainthread (WrapTask (
-                                             this,
-                                             &OpenH264VideoEncoder::DestroyInputFrame_m,
-                                             inputImage));
+      TrySyncRunOnMainThread (WrapTask (
+                                   this,
+                                   &OpenH264VideoEncoder::DestroyInputFrame_m,
+                                   inputImage));
       return;
     }
 
     // Synchronously send this back to the main thread for delivery.
-    g_platform_api->syncrunonmainthread (WrapTask (
-                                           this,
-                                           &OpenH264VideoEncoder::Encode_m,
-                                           inputImage,
-                                           &encoded,
-                                           encoded_type));
+    TrySyncRunOnMainThread (WrapTask (
+                                   this,
+                                   &OpenH264VideoEncoder::Encode_m,
+                                   inputImage,
+                                   &encoded,
+                                   encoded_type));
   }
 
   void Encode_m (GMPVideoi420Frame* frame, SFrameBSInfo* encoded,
@@ -574,6 +583,7 @@
   uint32_t max_payload_size_;
   GMPVideoEncoderCallback* callback_;
   FrameStats stats_;
+  bool shutting_down;
 };
 
 uint16_t readU16BE(const uint8_t* in) {
@@ -593,7 +603,8 @@
     worker_thread_ (nullptr),
     callback_ (nullptr),
     decoder_ (nullptr),
-    stats_ ("Decoder") {
+    stats_ ("Decoder"),
+    shutting_down(false) {
       AddRef();
     }
 
@@ -739,6 +750,8 @@
   }
 
   virtual void DecodingComplete() {
+    shutting_down = true;
+
     // Release the reference to the external objects, because it is no longer safe to call them
     host_     = nullptr;
     callback_ = nullptr;
@@ -766,6 +779,13 @@
       decoder_ = nullptr;
     }
   }
+
+  void TrySyncRunOnMainThread(GMPTask* aTask) {
+    if (!shutting_down && g_platform_api) {
+      g_platform_api->syncrunonmainthread (aTask);
+    }
+  }
+
   void Error (GMPErr error) {
     if (callback_) {
       callback_->Error (error);
@@ -795,14 +815,14 @@
       valid = true;
     }
 
-    g_platform_api->syncrunonmainthread (WrapTask (
-                                           this,
-                                           &OpenH264VideoDecoder::Decode_m,
-                                           inputFrame,
-                                           &decoded,
-                                           data,
-                                           renderTimeMs,
-                                           valid));
+    TrySyncRunOnMainThread (WrapTask (
+                                 this,
+                                 &OpenH264VideoDecoder::Decode_m,
+                                 inputFrame,
+                                 &decoded,
+                                 data,
+                                 renderTimeMs,
+                                 valid));
   }
 
   // Return the decoded data back to the parent.
@@ -883,6 +903,7 @@
   GMPVideoDecoderCallback* callback_;
   ISVCDecoder* decoder_;
   FrameStats stats_;
+  bool shutting_down;
 };
 
 extern "C" {
--- a/test/decoder/DecUT_DecExt.cpp
+++ b/test/decoder/DecUT_DecExt.cpp
@@ -26,6 +26,8 @@
   }
   //Init members
   void Init();
+  //Init valid members
+  void ValidInit();
   //Uninit members
   void Uninit();
   //Mock input data for test
@@ -94,6 +96,24 @@
   ASSERT_EQ (eRet, cmResultSuccess);
 }
 
+void DecoderInterfaceTest::ValidInit() {
+  memset (&m_sBufferInfo, 0, sizeof (SBufferInfo));
+  memset (&m_sDecParam, 0, sizeof (SDecodingParam));
+  m_sDecParam.pFileNameRestructed = NULL;
+  m_sDecParam.uiCpuLoad = 1;
+  m_sDecParam.uiTargetDqLayer = 1;
+  m_sDecParam.eEcActiveIdc = (ERROR_CON_IDC) (rand() & 7);
+  m_sDecParam.sVideoProperty.size = sizeof (SVideoProperty);
+  m_sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+  
+  m_pData[0] = m_pData[1] = m_pData[2] = NULL;
+  m_szBuffer[0] = m_szBuffer[1] = m_szBuffer[2] = 0;
+  m_szBuffer[3] = 1;
+  m_iBufLength = 4;
+  CM_RETURN eRet = (CM_RETURN) m_pDec->Initialize (&m_sDecParam);
+  ASSERT_EQ (eRet, cmResultSuccess);
+}
+
 void DecoderInterfaceTest::Uninit() {
   if (m_pDec) {
     CM_RETURN eRet = (CM_RETURN) m_pDec->Uninitialize();
@@ -310,7 +330,7 @@
   int iTmp, iOut;
   CM_RETURN eRet;
 
-  Init();
+  ValidInit();
 
   //invalid input
   eRet = (CM_RETURN) m_pDec->SetOption (DECODER_OPTION_END_OF_STREAM, NULL);
@@ -372,7 +392,7 @@
   int iTmp, iOut;
   CM_RETURN eRet;
 
-  Init();
+  ValidInit();
 
   //Test SetOption
   //VclNal never supports SetOption
@@ -481,7 +501,7 @@
   SDecoderStatistics sDecStatic;
   int32_t iError = 0;
 
-  Init();
+  ValidInit();
   // setoption not support,
   eRet = (CM_RETURN)m_pDec->SetOption (DECODER_OPTION_GET_STATISTICS, NULL);
   EXPECT_EQ (eRet, cmInitParaError);
@@ -504,7 +524,7 @@
   Uninit();
 
   //Decoder error bs when the first IDR lost
-  Init();
+  ValidInit();
   iError = 2;
   m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
   DecoderBs ("res/BA_MW_D_IDR_LOST.264");
@@ -522,7 +542,7 @@
   Uninit();
 
   //ecoder error bs when the first P lost
-  Init();
+  ValidInit();
   iError = 2;
   m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
 
@@ -543,7 +563,7 @@
   //EC enable
 
   //EC Off UT just correc bitstream
-  Init();
+  ValidInit();
   iError = 0;
   m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
   DecoderBs ("res/test_vd_1d.264");
--- a/test/decoder/DecUT_ParseSyntax.cpp
+++ b/test/decoder/DecUT_ParseSyntax.cpp
@@ -86,12 +86,15 @@
       return cmMallocMemeError;
   }
 
-  WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (pCtx, pParam->bParseOnly, pLogCtx), UninitDecoder (pCtx));
+  pCtx->sLogCtx = *pLogCtx;
+
   //check param and update decoder context
   pCtx->pParam = (SDecodingParam*) pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam), "SDecodingParam");
   WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoder (pCtx));
-  int32_t iRet = DecoderConfigParam (pCtx, pCtx->pParam);
+  int32_t iRet = DecoderConfigParam (pCtx, pParam);
   WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
+
+  WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (pCtx, pLogCtx), UninitDecoder (pCtx));
 
   return cmResultSuccess;
 }