Ethan HuggInitial Commit70e5e6212 years agoHistory
1592 lines · 56.6 KB · C++
RawDownload
/*!
 * \copy
 *     Copyright (c)  2010-2013, Cisco Systems
 *     All rights reserved.
 *
 *     Redistribution and use in source and binary forms, with or without
 *     modification, are permitted provided that the following conditions
 *     are met:
 *
 *        * Redistributions of source code must retain the above copyright
 *          notice, this list of conditions and the following disclaimer.
 *
 *        * Redistributions in binary form must reproduce the above copyright
 *          notice, this list of conditions and the following disclaimer in
 *          the documentation and/or other materials provided with the
 *          distribution.
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *     POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * \file	slice_multi_threading.h
 *
 * \brief	pSlice based multiple threading
 *
 * \date	04/16/2010 Created
 *
 *************************************************************************************
 */

#if defined(MT_ENABLED)

#include <assert.h>
#ifdef __GNUC__
#include <semaphore.h>
#ifndef SEM_NAME_MAX
// length of semaphore name should be system constrained at least on mac 10.7
#define  SEM_NAME_MAX 32
#endif//SEM_NAME_MAX
#endif//__GNUC__
#include "slice_multi_threading.h"
#include "mt_defs.h"
#include "nal_encap.h"
#include "utils.h"
#include "encoder.h"
#include "svc_encode_slice.h"
#include "deblocking.h"
#include "svc_enc_golomb.h"
#include "crt_util_safe_x.h"	// for safe crt like calls
#include "rc.h"

#if defined(X86_ASM)
#include "cpu.h"
#endif//X86_ASM

#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG)
#include "measure_time.h"
#endif//DYNAMIC_SLICE_ASSIGN
namespace WelsSVCEnc {
void UpdateMbListNeighborParallel(	SSliceCtx *pSliceCtx,
									  SMB *pMbList,
									  const int32_t uiSliceIdc	)
{
	const uint8_t *kpMbMap			= pSliceCtx->pOverallMbMap;
	const int32_t kiMbWidth			= pSliceCtx->iMbWidth;
	int32_t iIdx						= pSliceCtx->pFirstMbInSlice[uiSliceIdc];
	const int32_t kiEndMbInSlice	= iIdx + pSliceCtx->pCountMbNumInSlice[uiSliceIdc] - 1;
	
	do {
		SMB *pMb							= &pMbList[iIdx];
		uint32_t uiNeighborAvailFlag	= 0;
		const int32_t kiMbXY				= pMb->iMbXY;
		const int32_t kiMbX				= pMb->iMbX;
		const int32_t kiMbY				= pMb->iMbY;
		BOOL_T     bLeft;
		BOOL_T     bTop;
		BOOL_T     bLeftTop;
		BOOL_T     bRightTop;		
		int32_t   iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;		

		iLeftXY = kiMbXY - 1;
		iTopXY = kiMbXY - kiMbWidth;
		iLeftTopXY = iTopXY - 1;
		iRightTopXY = iTopXY + 1;
		
		bLeft = (kiMbX > 0) && (uiSliceIdc == kpMbMap[iLeftXY]);
		bTop = (kiMbY > 0) && (uiSliceIdc == kpMbMap[iTopXY]);
		bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == kpMbMap[iLeftTopXY]);
		bRightTop = (kiMbX < (kiMbWidth-1)) && (kiMbY > 0) && (uiSliceIdc == kpMbMap[iRightTopXY]);		
		
		if( bLeft ){
			uiNeighborAvailFlag |= LEFT_MB_POS;
		}		
		if( bTop ){
			uiNeighborAvailFlag |= TOP_MB_POS;
		}
		if( bLeftTop ){
			uiNeighborAvailFlag |= TOPLEFT_MB_POS;
		}		
		if( bRightTop ){
			uiNeighborAvailFlag |= TOPRIGHT_MB_POS;
		}		
		pMb->uiNeighborAvail	= (uint8_t)uiNeighborAvailFlag;
		pMb->uiSliceIdc		= uiSliceIdc;

		++ iIdx;
	} while(iIdx <= kiEndMbInSlice);
}

void CalcSliceComplexRatio( void *pRatio, SSliceCtx *pSliceCtx, uint32_t *pSliceConsume )
{
	float *pRatioList			= (float *)pRatio;
	float fAvI[MAX_SLICES_NUM];
	float fSumAv				= .0f;
	uint32_t *pSliceTime		= (uint32_t *)pSliceConsume;
	int32_t *pCountMbInSlice	= (int32_t *)pSliceCtx->pCountMbNumInSlice;	
	const int32_t kiSliceCount	= pSliceCtx->iSliceNumInFrame;
	int32_t iSliceIdx			= 0;

#if defined(X86_ASM)
	WelsEmms();
#endif //X86_ASM
	
	while ( iSliceIdx < kiSliceCount )
	{
		fAvI[iSliceIdx]	= 1.0f * pCountMbInSlice[iSliceIdx] / pSliceTime[iSliceIdx];
#if defined(ENABLE_TRACE_MT)
		WelsLog(NULL, WELS_LOG_DEBUG, "[MT] CalcSliceComplexRatio(), pSliceConsumeTime[%d]= %d us, slice_run= %d\n", iSliceIdx, pSliceTime[iSliceIdx], pCountMbInSlice[iSliceIdx]);
#endif//ENABLE_TRACE_MT
		fSumAv += fAvI[iSliceIdx];
		
		++ iSliceIdx;
	}
	while ( -- iSliceIdx >= 0 )
	{
		pRatioList[iSliceIdx] = fAvI[iSliceIdx] / fSumAv;
	}
}

#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) && defined(NOT_ABSOLUTE_BALANCING)
int32_t NeedDynamicAdjust( void *pConsumeTime, const int32_t iSliceNum )
{	
#if !defined(USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING)
	const float fRatioLower	= TOLERANT_BALANCING_RATIO_LOWER( uiSliceNum );
	const float fRatioUpper	= TOLERANT_BALANCING_RATIO_UPPER( uiSliceNum );
#endif//USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING
	uint32_t *pSliceConsume	= (uint32_t *)pConsumeTime;
	uint32_t uiTotalConsume	= 0;
	int32_t iSliceIdx		= 0;
	int32_t iNeedAdj		= false;

#if defined(X86_ASM)
	WelsEmms();
#endif //X86_ASM
	
	while( iSliceIdx < iSliceNum )
	{
		uiTotalConsume += pSliceConsume[iSliceIdx] + pSliceConsume[1+iSliceIdx];
		iSliceIdx += 2;
	}
	if (uiTotalConsume == 0)
	{
#if defined(ENABLE_TRACE_MT)
		WelsLog( NULL, WELS_LOG_DEBUG, "[MT] NeedDynamicAdjust(), herein do no adjust due first picture, iCountSliceNum= %d\n", iSliceNum );
#endif//ENABLE_TRACE_MT
		return false;
	}

	iSliceIdx = 0;
#if defined(USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING)
	float fThr				= EPSN;	// threshold for various cores cases
	float fRmse				= .0f;	// root mean square error of pSlice consume ratios
	const float kfMeanRatio	= 1.0f / iSliceNum;
	do{
		const float fRatio = 1.0f * pSliceConsume[iSliceIdx] / uiTotalConsume;
		const float fDiffRatio = fRatio - kfMeanRatio;
		fRmse += (fDiffRatio * fDiffRatio);		
		++ iSliceIdx;
	} while ( iSliceIdx+1 < iSliceNum );	
	fRmse = sqrtf(fRmse/iSliceNum);
	if ( iSliceNum >= 8 )
	{
		fThr += THRESHOLD_RMSE_CORE8;		
	}
	else if ( iSliceNum >= 4 )
	{
		fThr += THRESHOLD_RMSE_CORE4;
	}
	else if ( iSliceNum >= 2 )
	{
		fThr += THRESHOLD_RMSE_CORE2;
	}
	else
		fThr = 1.0f;
	if ( fRmse > fThr )
		iNeedAdj	= true;
#if defined(ENABLE_TRACE_MT)
	WelsLog(NULL, WELS_LOG_DEBUG, "[MT] NeedDynamicAdjust(), herein adjustment decision is made (iNeedAdj= %d) by: fRmse of pSlice complexity ratios %.6f, the corresponding threshold %.6f, iCountSliceNum %d\n",
		iNeedAdj, fRmse, fThr, iSliceNum);
#endif//ENABLE_TRACE_MT
#else
	do{
		const float kfRatio = 1.0f * pSliceConsume[uiSliceIdx] / uiTotalConsume;
		if ( kfRatio+EPSN < fRatioLower || kfRatio > ratio_upper+EPSN )
		{
#if defined(ENABLE_TRACE_MT)
			WelsLog(NULL, WELS_LOG_DEBUG, "[MT] NeedDynamicAdjust(), herein adjustment decision is made by pSlice consume time not balanced at all, uiSliceIdx= %d, comp_ratio= %.6f, pSliceConsumeTime= %d, total_consume_time= %d, iCountSliceNum= %d\n",
				uiSliceIdx, kfRatio, pSliceConsume[uiSliceIdx], uiTotalConsume, uiSliceNum);
#endif//ENABLE_TRACE_MT
			iNeedAdj = true;
			break;
		}
		++ uiSliceIdx;
	} while ( uiSliceIdx+1 < uiSliceNum );
#endif//USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING

	return iNeedAdj;
}
#endif//..

#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
void DynamicAdjustSlicing(	sWelsEncCtx *pCtx,
								SDqLayer *pCurDqLayer,
								void *pComplexRatio,
								int32_t iCurDid )
{	
	SSliceCtx *pSliceCtx	= pCurDqLayer->pSliceEncCtx;
	const int32_t kiCountSliceNum	= pSliceCtx->iSliceNumInFrame;	
	const int32_t kiCountNumMb		= pSliceCtx->iMbNumInFrame;
	int32_t iMinimalMbNum			= pSliceCtx->iMbWidth;	// in theory we need only 1 SMB, here let it as one SMB row required
	int32_t iMaximalMbNum			= 0;	// dynamically assign later
	float *pSliceComplexRatio	= (float *)pComplexRatio;	
	int32_t iMbNumLeft					= kiCountNumMb;
	int32_t iRunLen[MAX_THREADS_NUM]	= {0};
	int32_t iSliceIdx					= 0;

	int32_t iNumMbInEachGom;
	SWelsSvcRc *pWelsSvcRc = &pCtx->pWelsSvcRc[iCurDid];
	if(pCtx->pSvcParam->bEnableRc)
	{
		iNumMbInEachGom = pWelsSvcRc->iNumberMbGom;

		if ( iNumMbInEachGom <= 0 )
		{
			WelsLog(pCtx, WELS_LOG_ERROR, "[MT] DynamicAdjustSlicing(), invalid iNumMbInEachGom= %d from RC, iDid= %d, iCountNumMb= %d\n", iNumMbInEachGom, iCurDid, kiCountNumMb);
			return;
		}

		// do not adjust in case no extra iNumMbInEachGom based left for slicing adjustment,
		// extra MB of non integrated GOM assigned at the last pSlice in default, keep up on early initial result.
		if ( iNumMbInEachGom * kiCountSliceNum >= kiCountNumMb )
		{
			return;
		}		
		iMinimalMbNum	= iNumMbInEachGom;		
	}
	
	if ( kiCountSliceNum < 2 || (kiCountSliceNum & 0x01) )	// we need suppose uiSliceNum is even for multiple threading
		return;

	iMaximalMbNum	= kiCountNumMb - (kiCountSliceNum - 1) * iMinimalMbNum;

#if defined(X86_ASM)
	WelsEmms();
#endif //X86_ASM
	
#if defined(ENABLE_TRACE_MT)
	WelsLog(pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), iDid= %d, iCountNumMb= %d\n", iCurDid, kiCountNumMb);
#endif//ENABLE_TRACE_MT

	iSliceIdx	= 0;
	while (iSliceIdx+1 < kiCountSliceNum) {
		int32_t iNumMbAssigning = (int32_t)(kiCountNumMb * pSliceComplexRatio[iSliceIdx] + EPSN);			

		// GOM boundary aligned
		if(pCtx->pSvcParam->bEnableRc)
		{
			iNumMbAssigning=(int32_t)(1.0f * iNumMbAssigning / iNumMbInEachGom + 0.5f + EPSN) * iNumMbInEachGom;			
		}

		// make sure one GOM at least in each pSlice for safe
		if ( iNumMbAssigning < iMinimalMbNum )
			iNumMbAssigning	= iMinimalMbNum;
		else if ( iNumMbAssigning > iMaximalMbNum )
			iNumMbAssigning	= iMaximalMbNum;

		assert( iNumMbAssigning > 0 );

		iMbNumLeft -= iNumMbAssigning;
		if ( iMbNumLeft <= 0 )	// error due to we can not support slice_skip now yet, do not adjust this time
		{
			assert( 0 );
			return;
		}
		iRunLen[iSliceIdx]	= iNumMbAssigning;
#if defined(ENABLE_TRACE_MT)
		WelsLog(pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), uiSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n", 
			iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iNumMbAssigning);
#endif//ENABLE_TRACE_MT
		++ iSliceIdx;
		iMaximalMbNum	= iMbNumLeft - (kiCountSliceNum - iSliceIdx - 1) * iMinimalMbNum;	// get maximal num_mb in left parts
	}
	iRunLen[iSliceIdx] = iMbNumLeft;
#if defined(ENABLE_TRACE_MT)
	WelsLog(pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), iSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n", 
		iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iMbNumLeft);
#endif//ENABLE_TRACE_MT


	if ( DynamicAdjustSlicePEncCtxAll( pSliceCtx, iRunLen ) == 0 )
	{
		const int32_t kiThreadNum	= pCtx->pSvcParam->iCountThreadsNum;
		int32_t iThreadIdx			= 0;
		do {
#ifdef WIN32
			WelsEventSignal( &pCtx->pSliceThreading->pUpdateMbListEvent[iThreadIdx] );
#else
			WelsEventSignal( pCtx->pSliceThreading->pUpdateMbListEvent[iThreadIdx] );
#endif//WIN32
			++ iThreadIdx;
		} while(iThreadIdx < kiThreadNum);

		WelsMultipleEventsWaitAllBlocking( kiThreadNum, &pCtx->pSliceThreading->pFinUpdateMbListEvent[0] );
	}
}
#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)

#ifdef PACKING_ONE_SLICE_PER_LAYER
void ResetEnvMt( sWelsEncCtx *pCtx)
{
	const int16_t kiSliceCount = pCtx->iMaxSliceCount;
	int32_t iIdx = 0;

	while ( iIdx < kiSliceCount )
	{
		SWelsSliceBs *pSliceBs	= &pCtx->pSliceBs[iIdx];
		pSliceBs->uiBsPos		= 0;	
		++ iIdx;
	}
}
#endif//PACKING_ONE_SLICE_PER_LAYER

int32_t RequestMtResource( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pCodingParam, const int32_t iCountBsLen, const int32_t iTargetSpatialBsSize )
{	
	CMemoryAlign *pMa			= NULL;
	SWelsSvcCodingParam *pPara= NULL;
	SSliceThreading *pSmt		= NULL;
	SWelsSliceBs *pSliceB		= NULL;
	uint8_t *pBsBase			= NULL;
	int32_t iNumSpatialLayers	= 0;
	int32_t iThreadNum			= 0;	
	int32_t iIdx					= 0;
	int32_t iSliceBsBufferSize= 0;
	int16_t iMaxSliceNum		= 1;
	
	if ( NULL == ppCtx || NULL == pCodingParam || NULL == *ppCtx || iCountBsLen <= 0 )
		return 1;
	
	pMa	= (*ppCtx)->pMemAlign;
	pPara= pCodingParam;
	iNumSpatialLayers	= pPara->iNumDependencyLayer;
	iThreadNum	= pPara->iCountThreadsNum;
	iMaxSliceNum = (*ppCtx)->iMaxSliceCount;

	pSmt	= (SSliceThreading *)pMa->WelsMalloc(sizeof(SSliceThreading), "SSliceThreading");
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt), FreeMemorySvc(ppCtx) )
	(*ppCtx)->pSliceThreading	= pSmt;
	pSmt->pThreadPEncCtx	= (SSliceThreadPrivateData *)pMa->WelsMalloc( sizeof(SSliceThreadPrivateData) * iThreadNum, "pThreadPEncCtx" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pThreadPEncCtx), FreeMemorySvc(ppCtx) )
	pSmt->pThreadHandles	= (WELS_THREAD_HANDLE *)pMa->WelsMalloc( sizeof(WELS_THREAD_HANDLE) * iThreadNum, "pThreadHandles" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pThreadHandles), FreeMemorySvc(ppCtx) )

#ifdef WIN32
	pSmt->pSliceCodedEvent	= (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pSliceCodedEvent" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pSliceCodedEvent), FreeMemorySvc(ppCtx) )
	pSmt->pReadySliceCodingEvent	= (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pReadySliceCodingEvent" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pReadySliceCodingEvent), FreeMemorySvc(ppCtx) )
	pSmt->pFinSliceCodingEvent	= (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pFinSliceCodingEvent" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pFinSliceCodingEvent), FreeMemorySvc(ppCtx) )
#endif//WIN32

#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
#if defined(__GNUC__)
	pSmt->pUpdateMbListThrdHandles	= (WELS_THREAD_HANDLE *)pMa->WelsMalloc( sizeof(WELS_THREAD_HANDLE) * iThreadNum, "pUpdateMbListThrdHandles" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pUpdateMbListThrdHandles), FreeMemorySvc(ppCtx) )	
#endif//__GNUC__
#ifdef WIN32
	pSmt->pUpdateMbListEvent	= (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pUpdateMbListEvent" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pUpdateMbListEvent), FreeMemorySvc(ppCtx) )
	pSmt->pFinUpdateMbListEvent	= (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pFinUpdateMbListEvent" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pFinUpdateMbListEvent), FreeMemorySvc(ppCtx) )
#endif//WIN32
#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)

#ifdef WIN32
	pSmt->pExitEncodeEvent	= (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pExitEncodeEvent" );
	WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pExitEncodeEvent), FreeMemorySvc(ppCtx) )
#endif//WIN32

#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG)
	iIdx = 0;
	while ( iIdx < iNumSpatialLayers )
	{		
		SMulSliceOption *pMso	= &pPara->sDependencyLayers[iIdx].sMso;
		const int32_t kiSliceNum= pMso->sSliceArgument.iSliceNum;
		if (pMso->uiSliceMode == SM_FIXEDSLCNUM_SLICE && pPara->iMultipleThreadIdc > 1 && pPara->iMultipleThreadIdc >= kiSliceNum )
		{
			pSmt->pSliceConsumeTime[iIdx]	= (uint32_t *)pMa->WelsMallocz( kiSliceNum * sizeof(uint32_t), "pSliceConsumeTime[]" );
			WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pSliceConsumeTime[iIdx]), FreeMemorySvc(ppCtx) )
#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
			pSmt->pSliceComplexRatio[iIdx]	= (float *)pMa->WelsMalloc( kiSliceNum * sizeof(float), "pSliceComplexRatio[]" );
			WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pSliceComplexRatio[iIdx]), FreeMemorySvc(ppCtx) )
#endif//TRY_SLICING_BALANCE
		}
		else
		{
			pSmt->pSliceConsumeTime[iIdx]	= NULL;
#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
			pSmt->pSliceComplexRatio[iIdx]	= NULL;
#endif//TRY_SLICING_BALANCE
		}		
		++ iIdx;
	}
	// NULL for pSliceConsumeTime[iIdx]: iIdx from iNumSpatialLayers to MAX_DEPENDENCY_LAYERS	
#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG)
	
#ifdef MT_DEBUG
	// file handle for MT debug
	pSmt->pFSliceDiff = NULL;

	if ( pSmt->pFSliceDiff )
	{
		fclose( pSmt->pFSliceDiff );
		pSmt->pFSliceDiff = NULL;
	}
#ifdef WIN32
	pSmt->pFSliceDiff	= fopen(".\\slice_time.txt", "wt+" );
#else
	pSmt->pFSliceDiff	= fopen("/tmp/slice_time.txt", "wt+" );
#endif//WIN32
#endif//MT_DEBUG
	
#if defined(ENABLE_TRACE_MT)
	WelsLog((*ppCtx), WELS_LOG_INFO, "encpEncCtx= 0x%p\n", (void *)(*ppCtx));
#endif//ENABLE_TRACE_MT

	iIdx = 0;
	while ( iIdx < iThreadNum )
	{
#ifdef __GNUC__	// for posix threading
		str_t name[SEM_NAME_MAX] = {0};
		int32_t used_len = 0;
		WELS_THREAD_ERROR_CODE err = 0;
#endif//__GNUC__
		pSmt->pThreadPEncCtx[iIdx].pWelsPEncCtx	= (void *)(*ppCtx);
		pSmt->pThreadPEncCtx[iIdx].iSliceIndex	= iIdx;
		pSmt->pThreadPEncCtx[iIdx].iThreadIndex	= iIdx;
		pSmt->pThreadHandles[iIdx]				= 0;

#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
#ifdef WIN32
		WelsEventInit( &pSmt->pUpdateMbListEvent[iIdx] );
		WelsEventInit( &pSmt->pFinUpdateMbListEvent[iIdx] );		
#else
		// length of semaphore name should be system constrained at least on mac 10.7
		SNPRINTF( name, SEM_NAME_MAX, "ud%d%p", iIdx, (void *)(*ppCtx) );
		err = WelsEventOpen( &pSmt->pUpdateMbListEvent[iIdx], name );
#if defined(ENABLE_TRACE_MT)
		WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pUpdateMbListEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno);
#endif
		used_len = SNPRINTF( name, SEM_NAME_MAX, "fu%d%p", iIdx, (void *)(*ppCtx) );
		name[used_len] = '\0';
		err = WelsEventOpen( &pSmt->pFinUpdateMbListEvent[iIdx], name );
#if defined(ENABLE_TRACE_MT)
		WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pFinUpdateMbListEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno);
#endif
#endif//WIN32
#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
		
#ifdef WIN32
		WelsEventInit( &pSmt->pSliceCodedEvent[iIdx] );
		WelsEventInit( &pSmt->pReadySliceCodingEvent[iIdx] );
		WelsEventInit( &pSmt->pFinSliceCodingEvent[iIdx] );
		WelsEventInit( &pSmt->pExitEncodeEvent[iIdx] );
#else
		used_len = SNPRINTF( name, SEM_NAME_MAX, "sc%d%p", iIdx, (void *)(*ppCtx) );
		name[used_len] = '\0';
		err = WelsEventOpen( &pSmt->pSliceCodedEvent[iIdx], name );
#if defined(ENABLE_TRACE_MT)
		WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pSliceCodedEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno);

Lines 1–500 of 1592.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t