Esempio n. 1
0
WelsErrorType CWelsSliceEncodingTask::InitTask() {
  m_eNalType          = m_pCtx->eNalType;
  m_eNalRefIdc        = m_pCtx->eNalPriority;
  m_bNeedPrefix       = m_pCtx->bNeedPrefixNalFlag;

  WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
  m_iThreadIdx = QueryEmptyThread (m_pCtx->pSliceThreading->bThreadBsBufferUsage);
  WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);

  WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
           "[MT] CWelsSliceEncodingTask()InitTask for m_iSliceIdx %d, lock thread %d",
           m_iSliceIdx, m_iThreadIdx);
  if (m_iThreadIdx < 0) {
    WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
             "[MT] CWelsSliceEncodingTask InitTask(), Cannot find available thread for m_iSliceIdx = %d", m_iSliceIdx);
    return ENC_RETURN_UNEXPECTED;
  }
  SetOneSliceBsBufferUnderMultithread (m_pCtx, m_iThreadIdx, m_iSliceIdx);

  m_pSlice = &m_pCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[m_iSliceIdx];
  m_pSliceBs = &m_pCtx->pSliceBs[m_iSliceIdx];

  m_pSliceBs->uiBsPos       = 0;
  m_pSliceBs->iNalIndex     = 0;

  assert ((void*) (&m_pSliceBs->sBsWrite) == (void*)m_pSlice->pSliceBsa);
  InitBits (&m_pSliceBs->sBsWrite, m_pSliceBs->pBsBuffer, m_pSliceBs->uiSize);
  //printf ("CWelsSliceEncodingTask_InitTask slice %d\n", m_iSliceIdx);

  return ENC_RETURN_SUCCESS;
}
Esempio n. 2
0
void CWelsSliceEncodingTask::FinishTask() {
  WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
  m_pCtx->pSliceThreading->bThreadBsBufferUsage[m_iThreadIdx] = false;
  WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);

  WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
           "[MT] CWelsSliceEncodingTask()FinishTask for m_iSliceIdx %d, unlock thread %d",
           m_iSliceIdx, m_iThreadIdx);

  //sync multi-threading error
  WelsMutexLock (&m_pCtx->mutexEncoderError);
  if (ENC_RETURN_SUCCESS != m_eTaskResult) {
    m_pCtx->iEncoderError |= m_eTaskResult;
  }
  WelsMutexUnlock (&m_pCtx->mutexEncoderError);
}
WelsErrorType CWelsSliceEncodingTask::InitTask() {
  m_eNalType          = m_pCtx->eNalType;
  m_eNalRefIdc        = m_pCtx->eNalPriority;
  m_bNeedPrefix       = m_pCtx->bNeedPrefixNalFlag;

  WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
  m_iThreadIdx = QueryEmptyThread (m_pCtx->pSliceThreading->bThreadBsBufferUsage);
  WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);

  WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
           "[MT] CWelsSliceEncodingTask()InitTask for m_iSliceIdx %d, lock thread %d",
           m_iSliceIdx, m_iThreadIdx);
  if (m_iThreadIdx < 0) {
    WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
             "[MT] CWelsSliceEncodingTask InitTask(), Cannot find available thread for m_iSliceIdx = %d", m_iSliceIdx);
    return ENC_RETURN_UNEXPECTED;
  }

  int32_t iReturn = InitOneSliceInThread (m_pCtx, m_pSlice, m_iThreadIdx, m_pCtx->uiDependencyId, m_iSliceIdx);
  WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
  m_pSliceBs = &m_pSlice->sSliceBs;

  iReturn   = SetSliceBoundaryInfo(m_pCtx->pCurDqLayer, m_pSlice, m_iSliceIdx);
  WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)

  SetOneSliceBsBufferUnderMultithread (m_pCtx, m_iThreadIdx, m_pSlice);

  assert ((void*) (&m_pSliceBs->sBsWrite) == (void*)m_pSlice->pSliceBsa);
  InitBits (&m_pSliceBs->sBsWrite, m_pSliceBs->pBsBuffer, m_pSliceBs->uiSize);
  //printf ("CWelsSliceEncodingTask_InitTask slice %d\n", m_iSliceIdx);

  return ENC_RETURN_SUCCESS;
}
Esempio n. 4
0
void CWelsSliceEncodingTask::FinishTask() {
  WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
  m_pCtx->pSliceThreading->bThreadBsBufferUsage[m_iThreadIdx] = false;
  WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);

  WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
           "[MT] CWelsSliceEncodingTask()FinishTask for m_iSliceIdx %d, unlock thread %d",
           m_iSliceIdx, m_iThreadIdx);
}
// thread process for coding one pSlice
WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
  SSliceThreadPrivateData* pPrivateData = (SSliceThreadPrivateData*)arg;
  sWelsEncCtx* pEncPEncCtx      = NULL;
  SDqLayer* pCurDq              = NULL;
  SSlice* pSlice                = NULL;
  SWelsSliceBs* pSliceBs        = NULL;
  WELS_EVENT pEventsList[3];
  int32_t iEventCount           = 0;
  WELS_THREAD_ERROR_CODE iWaitRet = WELS_THREAD_ERROR_GENERAL;
  uint32_t uiThrdRet            = 0;
  int32_t iSliceSize            = 0;
  int32_t iSliceIdx             = -1;
  int32_t iThreadIdx            = -1;
  int32_t iEventIdx             = -1;
  bool bNeedPrefix              = false;
  EWelsNalUnitType eNalType     = NAL_UNIT_UNSPEC_0;
  EWelsNalRefIdc eNalRefIdc     = NRI_PRI_LOWEST;
  int32_t iReturn = ENC_RETURN_SUCCESS;

  if (NULL == pPrivateData)
    WELS_THREAD_ROUTINE_RETURN (1);

  pEncPEncCtx   = (sWelsEncCtx*)pPrivateData->pWelsPEncCtx;

  iThreadIdx    = pPrivateData->iThreadIndex;
  iEventIdx     = iThreadIdx;

  pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pReadySliceCodingEvent[iEventIdx];
  pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pExitEncodeEvent[iEventIdx];
  pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pUpdateMbListEvent[iEventIdx];

  WelsThreadSetName ("OpenH264Enc_CodingSliceThreadProc");

  do {
    MT_TRACE_LOG (pEncPEncCtx, WELS_LOG_INFO,
                  "[MT] CodingSliceThreadProc(), try to call WelsMultipleEventsWaitSingleBlocking(pEventsList= %p %p %p), pEncPEncCtx= %p!",
                  pEventsList[0], pEventsList[1], pEventsList[1], (void*)pEncPEncCtx);
    iWaitRet = WelsMultipleEventsWaitSingleBlocking (iEventCount,
               &pEventsList[0],
               &pEncPEncCtx->pSliceThreading->pThreadMasterEvent[iEventIdx]); // blocking until at least one event is signalled
    if (WELS_THREAD_ERROR_WAIT_OBJECT_0 == iWaitRet) { // start pSlice coding signal waited
      //int             iLayerIndex  = pEncPEncCtx->pOut->iLayerBsIndex;
      //SFrameBSInfo*   pFrameBsInfo = pPrivateData->pFrameBsInfo;
      //SLayerBSInfo*   pLbi = &pFrameBsInfo->sLayerInfo [iLayerIndex];

      const int32_t kiCurDid            = pEncPEncCtx->uiDependencyId;
      SWelsSvcCodingParam* pCodingParam = pEncPEncCtx->pSvcParam;
      SSpatialLayerConfig* pParamD      = &pCodingParam->sSpatialLayers[kiCurDid];

      pCurDq            = pEncPEncCtx->pCurDqLayer;
      eNalType          = pEncPEncCtx->eNalType;
      eNalRefIdc        = pEncPEncCtx->eNalPriority;
      bNeedPrefix       = pEncPEncCtx->bNeedPrefixNalFlag;

      if (pParamD->sSliceArgument.uiSliceMode != SM_SIZELIMITED_SLICE) {
        int64_t iSliceStart = 0;
        bool bDsaFlag = false;
        iSliceIdx               = pPrivateData->iSliceIndex;
        pSlice                  = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx];
        pSliceBs                = &pEncPEncCtx->pSliceBs[iSliceIdx];

        bDsaFlag = ((pParamD->sSliceArgument.uiSliceMode == SM_FIXEDSLCNUM_SLICE) &&
                    pCodingParam->iMultipleThreadIdc > 1 &&
                    pCodingParam->iMultipleThreadIdc >= pParamD->sSliceArgument.uiSliceNum);
        if (bDsaFlag)
          iSliceStart = WelsTime();

        pSliceBs->uiBsPos       = 0;
        pSliceBs->iNalIndex     = 0;
        assert ((void*) (&pSliceBs->sBsWrite) == (void*)pSlice->pSliceBsa);
        InitBits (&pSliceBs->sBsWrite, pSliceBs->pBsBuffer, pSliceBs->uiSize);

#if MT_DEBUG_BS_WR
        pSliceBs->bSliceCodedFlag = false;
#endif//MT_DEBUG_BS_WR

        if (bNeedPrefix) {
          if (eNalRefIdc != NRI_PRI_LOWEST) {
            WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc);
            WelsWriteSVCPrefixNal (&pSliceBs->sBsWrite, eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == eNalType));
            WelsUnloadNalForSlice (pSliceBs);
          } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension
            WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc);
            // No need write any syntax of prefix NAL Unit RBSP here
            WelsUnloadNalForSlice (pSliceBs);
          }
        }

        WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc);

        iReturn = WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
        if (ENC_RETURN_SUCCESS != iReturn) {
          uiThrdRet = iReturn;
          WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
                                        pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                        iEventIdx);
        }

        WelsUnloadNalForSlice (pSliceBs);

        int32_t iLeftBufferSize = (iSliceIdx > 0) ?
                                  (pSliceBs->uiSize - pSliceBs->uiBsPos)
                                  : (pEncPEncCtx->iFrameBsSize - pEncPEncCtx->iPosBsBuffer);
        iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs,
                                &pSliceBs->iNalLen[0],
                                iLeftBufferSize,
                                iSliceIdx, iSliceSize);
        if (ENC_RETURN_SUCCESS != iReturn) {
          uiThrdRet = iReturn;
          WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
                                        pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                        iEventIdx);
        }
        if (0 == iSliceIdx) {
          pEncPEncCtx->iPosBsBuffer += iSliceSize;
        }

        pEncPEncCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx);

        if (bDsaFlag) {
            pEncPEncCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[iSliceIdx].uiSliceConsumeTime = (uint32_t) (
                WelsTime() - iSliceStart);
          MT_TRACE_LOG (& (pEncPEncCtx->sLogCtx), WELS_LOG_INFO,
                        "[MT] CodingSliceThreadProc(), coding_idx %d, uiSliceIdx %d, uiSliceConsumeTime %d, iSliceSize %d, iFirstMbInSlice %d, count_num_mb_in_slice %d",
                        pEncPEncCtx->iCodingIndex, iSliceIdx,
                        pEncPEncCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[iSliceIdx].uiSliceConsumeTime, iSliceSize,
                        pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx].sSliceHeaderExt.sSliceHeader.iFirstMbInSlice,
                        pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx].iCountMbNumInSlice);
        }

#if defined(SLICE_INFO_OUTPUT)
        fprintf (stderr,
                 "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n",
                 iSliceIdx,
                 (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'),
                 eNalRefIdc,
                 iSliceSize
                );
#endif//SLICE_INFO_OUTPUT

#if MT_DEBUG_BS_WR
        pSliceBs->bSliceCodedFlag = true;
#endif//MT_DEBUG_BS_WR

        WelsEventSignal (
          &pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice
        WelsEventSignal (
          &pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent);
      } else { // for SM_SIZELIMITED_SLICE parallelization
        SSliceCtx* pSliceCtx                    = &pCurDq->sSliceEncCtx;
        const int32_t kiPartitionId             = iThreadIdx;
        const int32_t kiSliceIdxStep            = pEncPEncCtx->iActiveThreadsNum;
        const int32_t kiFirstMbInPartition      = pPrivateData->iStartMbIndex;  // inclusive
        const int32_t kiEndMbInPartition        = pPrivateData->iEndMbIndex;            // exclusive
        int32_t iAnyMbLeftInPartition           = kiEndMbInPartition - kiFirstMbInPartition;

        iSliceIdx = pPrivateData->iSliceIndex;
        SSliceHeaderExt* pStartSliceHeaderExt                   = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx].sSliceHeaderExt;
        pStartSliceHeaderExt->sSliceHeader.iFirstMbInSlice      = kiFirstMbInPartition;
        pCurDq->pNumSliceCodedOfPartition[kiPartitionId]        =
          1;    // one pSlice per partition intialized, dynamic slicing inside
        pCurDq->pLastMbIdxOfPartition[kiPartitionId]            = kiEndMbInPartition - 1;

        pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]       = 0;

        while (iAnyMbLeftInPartition > 0) {
          if (iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint) {
            // TODO: need exception handler for not large enough of MAX_SLICES_NUM related memory usage
            // No idea about its solution due MAX_SLICES_NUM is fixed lenght in relevent pData structure
            uiThrdRet = 1;
            WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
                                          pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                          iEventIdx);
          }

          SetOneSliceBsBufferUnderMultithread (pEncPEncCtx, kiPartitionId, iSliceIdx);
          pSlice                = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx];
          pSliceBs              = &pEncPEncCtx->pSliceBs[iSliceIdx];

          pSliceBs->uiBsPos     = 0;
          pSliceBs->iNalIndex   = 0;
          InitBits (&pSliceBs->sBsWrite, pSliceBs->pBsBuffer, pSliceBs->uiSize);

          if (bNeedPrefix) {
            if (eNalRefIdc != NRI_PRI_LOWEST) {
              WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc);
              WelsWriteSVCPrefixNal (&pSliceBs->sBsWrite, eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == eNalType));
              WelsUnloadNalForSlice (pSliceBs);
            } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension
              WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc);
              // No need write any syntax of prefix NAL Unit RBSP here
              WelsUnloadNalForSlice (pSliceBs);
            }
          }


          WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc);

          iReturn = WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
          if (ENC_RETURN_SUCCESS != iReturn) {
            uiThrdRet = iReturn;
            WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
                                          pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                          iEventIdx);
          }

          WelsUnloadNalForSlice (pSliceBs);

          int32_t iLeftBufferSize = (iSliceIdx > 0) ? (pSliceBs->uiSize - pSliceBs->uiBsPos) : (pEncPEncCtx->iFrameBsSize - pEncPEncCtx->iPosBsBuffer);
          iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, &pSliceBs->iNalLen[0],
                                    iLeftBufferSize,
                                    iSliceIdx, iSliceSize);
          if (ENC_RETURN_SUCCESS != iReturn) {
            uiThrdRet = iReturn;
            WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
                                          pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                          iEventIdx);
          }
          if (0 == iSliceIdx) {
            pEncPEncCtx->iPosBsBuffer += iSliceSize;
          }

          pEncPEncCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx);

#if defined(SLICE_INFO_OUTPUT)
          fprintf (stderr,
                   "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n",
                   iSliceIdx,
                   (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'),
                   eNalRefIdc,
                   iSliceSize
                  );
#endif//SLICE_INFO_OUTPUT

          MT_TRACE_LOG (pEncPEncCtx, WELS_LOG_INFO,
                        "[MT] CodingSliceThreadProc(), coding_idx %d, iPartitionId %d, uiSliceIdx %d, iSliceSize %d, count_mb_slice %d, iEndMbInPartition %d, pCurDq->pLastCodedMbIdxOfPartition[%d] %d\n",
                        pEncPEncCtx->iCodingIndex, kiPartitionId, iSliceIdx, iSliceSize,
                        pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx].iCountMbNumInSlice,
                        kiEndMbInPartition, kiPartitionId, pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]);

          iAnyMbLeftInPartition = kiEndMbInPartition - (1 + pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]);
          iSliceIdx += kiSliceIdxStep;
        }

        if (uiThrdRet) { // any exception??
          WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
                                        pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
                                        iEventIdx);
        }

        WelsEventSignal (&pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice
        WelsEventSignal (&pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent);
      }
    } else if (WELS_THREAD_ERROR_WAIT_OBJECT_0 + 1 == iWaitRet) { // exit thread signal
      uiThrdRet = 0;
      break;
    } else if (WELS_THREAD_ERROR_WAIT_OBJECT_0 + 2 == iWaitRet) { // update pMb list singal
      iSliceIdx =
        iEventIdx; // pPrivateData->iSliceIndex; old threads can not be terminated, pPrivateData is not correct for applicable
      pCurDq = pEncPEncCtx->pCurDqLayer;
      UpdateMbListNeighborParallel (pCurDq, pCurDq->sMbDataP, iSliceIdx);
      WelsEventSignal (
        &pEncPEncCtx->pSliceThreading->pFinUpdateMbListEvent[iEventIdx]); // mean finished update pMb list for this pSlice
    } else { // WELS_THREAD_ERROR_WAIT_TIMEOUT, or WELS_THREAD_ERROR_WAIT_FAILED
      WelsLog (& (pEncPEncCtx->sLogCtx), WELS_LOG_WARNING,
               "[MT] CodingSliceThreadProc(), waiting pReadySliceCodingEvent[%d] failed(%d) and thread%d terminated!", iEventIdx,
               iWaitRet, iThreadIdx);
      uiThrdRet = 1;
      break;
    }
  } while (1);

  //sync multi-threading error
  WelsMutexLock (&pEncPEncCtx->mutexEncoderError);
  if (uiThrdRet) pEncPEncCtx->iEncoderError |= uiThrdRet;
  WelsMutexUnlock (&pEncPEncCtx->mutexEncoderError);

  WELS_THREAD_ROUTINE_RETURN (uiThrdRet);
}
//CWelsConstrainedSizeSlicingEncodingTask
WelsErrorType CWelsConstrainedSizeSlicingEncodingTask::ExecuteTask() {

  SDqLayer* pCurDq                        = m_pCtx->pCurDqLayer;
  const int32_t kiSliceIdxStep            = m_pCtx->iActiveThreadsNum;
  SSpatialLayerInternal* pParamInternal   = &m_pCtx->pSvcParam->sDependencyLayers[m_pCtx->uiDependencyId];
  const int32_t kiPartitionId             = m_iSliceIdx % kiSliceIdxStep;
  const int32_t kiFirstMbInPartition      = pCurDq->FirstMbIdxOfPartition[kiPartitionId];
  const int32_t kiEndMbIdxInPartition     = pCurDq->EndMbIdxOfPartition[kiPartitionId];
  const int32_t kiCodedSliceNumByThread   = pCurDq->sSliceBufferInfo[m_iThreadIdx].iCodedSliceNum;
  m_pSlice                                = &pCurDq->sSliceBufferInfo[m_iThreadIdx].pSliceBuffer[kiCodedSliceNumByThread];
  m_pSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice  = kiFirstMbInPartition;
  int32_t iReturn      = 0;
  bool bNeedReallocate = false;

  int32_t iDiffMbIdx = kiEndMbIdxInPartition - kiFirstMbInPartition;
  if( 0 == iDiffMbIdx) {
    m_pSlice->iSliceIdx = -1;
    return ENC_RETURN_SUCCESS;
  }

  int32_t iAnyMbLeftInPartition = iDiffMbIdx + 1;
  int32_t iLocalSliceIdx = m_iSliceIdx;
  while (iAnyMbLeftInPartition > 0) {
      bNeedReallocate = (pCurDq->sSliceBufferInfo[m_iThreadIdx].iCodedSliceNum
                         >=  pCurDq->sSliceBufferInfo[m_iThreadIdx].iMaxSliceNum -1) ? true : false;
      if (bNeedReallocate) {
          WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadSlcBuffReallocate);
          //for memory statistic variable
          iReturn = ReallocateSliceInThread(m_pCtx, pCurDq, m_pCtx->uiDependencyId, m_iThreadIdx);
          WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadSlcBuffReallocate);
          if (ENC_RETURN_SUCCESS != iReturn) {
              return iReturn;
          }
      }

    iReturn = InitOneSliceInThread (m_pCtx, m_pSlice, m_iThreadIdx, m_pCtx->uiDependencyId, iLocalSliceIdx);
    WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
    m_pSliceBs = &m_pSlice->sSliceBs;
    InitBits (&m_pSliceBs->sBsWrite, m_pSliceBs->pBsBuffer, m_pSliceBs->uiSize);

    if (m_bNeedPrefix) {
      if (m_eNalRefIdc != NRI_PRI_LOWEST) {
        WelsLoadNalForSlice (m_pSliceBs, NAL_UNIT_PREFIX, m_eNalRefIdc);
        WelsWriteSVCPrefixNal (&m_pSliceBs->sBsWrite, m_eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == m_eNalType));
        WelsUnloadNalForSlice (m_pSliceBs);
      } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension
        WelsLoadNalForSlice (m_pSliceBs, NAL_UNIT_PREFIX, m_eNalRefIdc);
        // No need write any syntax of prefix NAL Unit RBSP here
        WelsUnloadNalForSlice (m_pSliceBs);
      }
    }

    WelsLoadNalForSlice (m_pSliceBs, m_eNalType, m_eNalRefIdc);

    assert (iLocalSliceIdx == (int) m_pSlice->iSliceIdx);
    int32_t iReturn = WelsCodeOneSlice (m_pCtx, m_pSlice, m_eNalType);
    if (ENC_RETURN_SUCCESS != iReturn) {
      return iReturn;
    }
    WelsUnloadNalForSlice (m_pSliceBs);

    iReturn    = WriteSliceBs (m_pCtx, m_pSliceBs, iLocalSliceIdx, m_iSliceSize);
    if (ENC_RETURN_SUCCESS != iReturn) {
      WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
               "[MT] CWelsConstrainedSizeSlicingEncodingTask ExecuteTask(), WriteSliceBs not successful: coding_idx %d, uiLocalSliceIdx %d, BufferSize %d, m_iSliceSize %d, iPayloadSize %d",
               pParamInternal->iCodingIndex,
               iLocalSliceIdx, m_pSliceBs->uiSize, m_iSliceSize, m_pSliceBs->sNalList[0].iPayloadSize);
      return iReturn;
    }
    m_pCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (pCurDq, m_pCtx->pFuncList, m_pSlice);

    WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DETAIL,
             "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n",
             iLocalSliceIdx,
             (m_pCtx->eSliceType == P_SLICE ? 'P' : 'I'),
             m_eNalRefIdc,
             m_iSliceSize
            );

    WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
             "[MT] CWelsConstrainedSizeSlicingEncodingTask(), coding_idx %d, iPartitionId %d, m_iThreadIdx %d, iLocalSliceIdx %d, m_iSliceSize %d, ParamValidationExt(), invalid uiMaxNalSizeiEndMbInPartition %d, pCurDq->LastCodedMbIdxOfPartition[%d] %d\n",
             pParamInternal->iCodingIndex, kiPartitionId, m_iThreadIdx, iLocalSliceIdx, m_iSliceSize,
             kiEndMbIdxInPartition, kiPartitionId, pCurDq->LastCodedMbIdxOfPartition[kiPartitionId]);

    iAnyMbLeftInPartition = kiEndMbIdxInPartition - pCurDq->LastCodedMbIdxOfPartition[kiPartitionId];
    iLocalSliceIdx += kiSliceIdxStep;
    m_pCtx->pCurDqLayer->sSliceBufferInfo[m_iThreadIdx].iCodedSliceNum ++;
  }

  return ENC_RETURN_SUCCESS;
}