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; }
int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pDst, int32_t* pNalLen, int32_t iTotalLeftLength, const int32_t iSliceIdx, int32_t& iSliceSize) { SWelsSliceBs* pSliceBs = &pCtx->pSliceBs[iSliceIdx]; SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; const int32_t kiNalCnt = pSliceBs->iNalIndex; int32_t iNalIdx = 0; int32_t iNalSize = 0; int32_t iReturn = ENC_RETURN_SUCCESS; iSliceSize = 0; assert (kiNalCnt <= 2); if (kiNalCnt > 2) return 0; while (iNalIdx < kiNalCnt) { iNalSize = 0; iReturn = WelsEncodeNal (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, iTotalLeftLength - iSliceSize, pDst, &iNalSize); WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) pNalLen[iNalIdx] = iNalSize; iSliceSize += iNalSize; pDst += iNalSize; ++ iNalIdx; } pSliceBs->uiBsPos = iSliceSize; return iReturn; }
// the return value of this function is not suitable, it need report failure info to upper layer. int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "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"); if (NULL == m_pDecContext) return cmMallocMemeError; int32_t iCacheLineSize = 16; // on chip cache line size in byte m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize); WELS_VERIFY_RETURN_PROC_IF (1, (NULL == m_pDecContext->pMemAlign), 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), "SDecodingParam"); WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder()); 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; }
WelsErrorType CWelsSliceEncodingTask::Execute() { WelsThreadSetName ("OpenH264Enc_CWelsSliceEncodingTask_Execute"); m_eTaskResult = InitTask(); WELS_VERIFY_RETURN_IFNEQ (m_eTaskResult, ENC_RETURN_SUCCESS) m_eTaskResult = ExecuteTask(); FinishTask(); return m_eTaskResult; }
WelsErrorType CWelsSliceEncodingTask::Execute() { WelsThreadSetName ("OpenH264Enc_CWelsSliceEncodingTask_Execute"); int32_t iReturn = InitTask(); WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) iReturn = ExecuteTask(); FinishTask(); return ENC_RETURN_SUCCESS; }
WelsErrorType CWelsSliceEncodingTask::Execute() { //fprintf(stdout, "OpenH264Enc_CWelsSliceEncodingTask_Execute, %x, sink=%x\n", this, m_pSink); m_eTaskResult = InitTask(); WELS_VERIFY_RETURN_IFNEQ (m_eTaskResult, ENC_RETURN_SUCCESS) m_eTaskResult = ExecuteTask(); FinishTask(); //fprintf(stdout, "OpenH264Enc_CWelsSliceEncodingTask_Execute Ends\n"); return m_eTaskResult; }
//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; }