WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiCurDid) {
  CWelsBaseTask* pTask = NULL;
  int32_t kiTaskCount;
  uint32_t uiSliceMode = pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument.uiSliceMode;

  if (uiSliceMode != SM_SIZELIMITED_SLICE) {
    kiTaskCount = m_iTaskNum[kiCurDid] = pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument.uiSliceNum;
  } else {
    kiTaskCount = m_iTaskNum[kiCurDid] = pEncCtx->iActiveThreadsNum;
  }

  for (int idx = 0; idx < kiTaskCount; idx++) {
    pTask = WELS_NEW_OP (CWelsUpdateMbMapTask (this, pEncCtx, idx), CWelsUpdateMbMapTask);
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cPreEncodingTaskList[kiCurDid]->push_back (pTask);
  }

  for (int idx = 0; idx < kiTaskCount; idx++) {
    if (uiSliceMode==SM_SIZELIMITED_SLICE) {
      pTask = WELS_NEW_OP (CWelsConstrainedSizeSlicingEncodingTask (this, pEncCtx, idx), CWelsConstrainedSizeSlicingEncodingTask);
    } else {
    if (pEncCtx->pSvcParam->bUseLoadBalancing) {
      pTask = WELS_NEW_OP (CWelsLoadBalancingSlicingEncodingTask (this, pEncCtx, idx), CWelsLoadBalancingSlicingEncodingTask);
    } else {
      pTask = WELS_NEW_OP (CWelsSliceEncodingTask (this, pEncCtx, idx), CWelsSliceEncodingTask);
    }
    }
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cEncodingTaskList[kiCurDid]->push_back (pTask);
  }

  //printf ("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
  return ENC_RETURN_SUCCESS;
}
IWelsTaskManage*   IWelsTaskManage::CreateTaskManage (sWelsEncCtx* pCtx, const int32_t iSpatialLayer,
    const bool bNeedLock) {
  if (NULL == pCtx) {
    return NULL;
  }

  IWelsTaskManage* pTaskManage;
  if (iSpatialLayer > 1) {
    pTaskManage = WELS_NEW_OP (CWelsTaskManageMultiD(), CWelsTaskManageMultiD);
  } else {
    pTaskManage = WELS_NEW_OP (CWelsTaskManageBase(), CWelsTaskManageBase);
  }

  if (pTaskManage) {
    pTaskManage->Init (pCtx);
  }
  return pTaskManage;
}
WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount) {
  CWelsBaseTask* pTask = NULL;

  for (int idx = 0; idx < kiTaskCount; idx++) {
    pTask = WELS_NEW_OP (CWelsSliceEncodingTask (pEncCtx, idx), CWelsSliceEncodingTask);
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cTaskList->push_back (pTask);
  }
  m_iTaskNum = kiTaskCount;

  //printf("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
  return ENC_RETURN_SUCCESS;
}
WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount) {
  CWelsBaseTask* pTask = NULL;

  for (int idx = 0; idx < kiTaskCount; idx++) {
    pTask = WELS_NEW_OP (CWelsUpdateMbMapTask (pEncCtx, idx), CWelsUpdateMbMapTask);
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cPreEncodingTaskList->push_back (pTask);
  }

  for (int idx = 0; idx < kiTaskCount; idx++) {
    if (pEncCtx->pSvcParam->bUseLoadBalancing) {
      pTask = WELS_NEW_OP (CWelsLoadBalancingSlicingEncodingTask (pEncCtx, idx), CWelsLoadBalancingSlicingEncodingTask);
    } else {
      pTask = WELS_NEW_OP (CWelsSliceEncodingTask (pEncCtx, idx), CWelsSliceEncodingTask);
    }
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cEncodingTaskList->push_back (pTask);
  }
  m_iTotalTaskNum = kiTaskCount;

  //printf ("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
  return ENC_RETURN_SUCCESS;
}
WelsErrorType CWelsTaskManageBase::Init (sWelsEncCtx* pEncCtx) {
  m_pEncCtx = pEncCtx;

  m_iThreadNum = m_pEncCtx->pSvcParam->iMultipleThreadIdc;
  m_pThreadPool = WELS_NEW_OP (WelsCommon::CWelsThreadPool (this, m_iThreadNum),
                               WelsCommon::CWelsThreadPool);
  WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)

  m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_ENCODING] = m_cEncodingTaskList;
  m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_UPDATEMBMAP] = m_cPreEncodingTaskList;

  m_iCurrentTaskNum = pEncCtx->pSvcParam->sSpatialLayers[0].sSliceArgument.uiSliceNum;
  //printf ("CWelsTaskManageBase Init m_iThreadNum %d m_iCurrentTaskNum %d pEncCtx->iMaxSliceCount %d\n", m_iThreadNum, m_iCurrentTaskNum, pEncCtx->iMaxSliceCount);
  return CreateTasks (pEncCtx, pEncCtx->iMaxSliceCount);
}
WelsErrorType CWelsTaskManageBase::Init (sWelsEncCtx* pEncCtx) {
  m_pEncCtx = pEncCtx;

  m_iThreadNum = m_pEncCtx->pSvcParam->iMultipleThreadIdc;
  m_pThreadPool = WELS_NEW_OP (WelsCommon::CWelsThreadPool (this, m_iThreadNum),
                               WelsCommon::CWelsThreadPool);
  WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)

  int32_t iReturn = 0;
  for (int32_t iDid = 0; iDid < MAX_DEPENDENCY_LAYER; iDid++) {
    m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_ENCODING][iDid] = m_cEncodingTaskList[iDid];
    m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_UPDATEMBMAP][iDid] = m_cPreEncodingTaskList[iDid];
    iReturn |= CreateTasks (pEncCtx, iDid);
  }

  //printf ("CWelsTaskManageBase Init m_iThreadNum %d m_iCurrentTaskNum %d pEncCtx->iMaxSliceCount %d\n", m_iThreadNum, m_iCurrentTaskNum, pEncCtx->iMaxSliceCount);
  return iReturn;
}