shithub: openh264

ref: 99faf1ec4a47c5362a6bde552d6097166e2fda16
dir: /processing/src/common/WelsFrameWork.cpp/

View raw version
/*!
 * \copy
 *     Copyright (c)  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.
 *
 */

#include "WelsFrameWork.h"
#include "cpu.h"
#include "../denoise/denoise.h"
#include "../downsample/downsample.h"
#include "../scenechangedetection/SceneChangeDetection.h"
#include "../vaacalc/vaacalculation.h"
#include "../backgounddetection/BackgroundDetection.h"
#include "../adaptivequantization/AdaptiveQuantization.h"
#include "../complexityanalysis/ComplexityAnalysis.h"
#include "../imagerotate/imagerotate.h"


/* interface API implement */

EResult WELSAPI CreateVpInterface  (void **ppCtx, int iVersion)
{
	if (iVersion & 0x8000)
		return nsWelsVP::CreateSpecificVpInterface((IWelsVP **)ppCtx);
	else if (iVersion & 0x7fff)
		return nsWelsVP::CreateSpecificVpInterface((IWelsVPc **)ppCtx);
	else
		return RET_INVALIDPARAM;
}

EResult WELSAPI DestroyVpInterface  (void *pCtx, int iVersion)
{
	if (iVersion & 0x8000)
		return nsWelsVP::DestroySpecificVpInterface((IWelsVP *)pCtx);
	else if (iVersion & 0x7fff)
		return nsWelsVP::DestroySpecificVpInterface((IWelsVPc *)pCtx);
	else
		return RET_INVALIDPARAM;
}

WELSVP_NAMESPACE_BEGIN

///////////////////////////////////////////////////////////////////////

EResult CreateSpecificVpInterface(IWelsVP **ppCtx)
{
	EResult  eReturn = RET_FAILED;

	CVpFrameWork *pFr = new CVpFrameWork(1, eReturn);  
	if (pFr)
	{
		*ppCtx  = (IWelsVP *)pFr;
		eReturn = RET_SUCCESS;
	}

	return eReturn;
}

EResult DestroySpecificVpInterface  (IWelsVP *pCtx)
{
	_SafeDelete(pCtx);

	return RET_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////

CVpFrameWork::CVpFrameWork(uint32_t uiThreadsNum, EResult &eReturn)
{
	int32_t iCoreNum = 1;
#ifndef X86_ASM
	uint32_t uiCPUFlag = 0;
#else
	uint32_t uiCPUFlag = WelsCPUFeatureDetect(&iCoreNum);
#endif

	for (int32_t i = 0; i < MAX_STRATEGY_NUM; i++)
	{
		IStrategy *pStrategy = m_pStgChain[i];
		pStrategy = CreateStrategy(WelsStaticCast(EMethods, i + 1), uiCPUFlag);
		m_pStgChain[i] = pStrategy;	
	}
	
	WelsMutexInit(&m_mutes);

	eReturn = RET_SUCCESS;	
}

CVpFrameWork::~CVpFrameWork()
{
	for (int32_t i = 0; i < MAX_STRATEGY_NUM; i++)
	{
		if (m_pStgChain[i])
		{
			Uninit(m_pStgChain[i]->m_eMethod);
			_SafeDelete(m_pStgChain[i]);
		}		
	}
 
	WelsMutexDestroy(&m_mutes);
}

EResult CVpFrameWork::Init(int32_t iType, void *pCfg)
{
	EResult eReturn   = RET_SUCCESS;
	int32_t iCurIdx    = WelsStaticCast(int32_t, WelsVpGetValidMethod(iType)) - 1;	

	Uninit(iType);

	WelsMutexLock(&m_mutes);

	IStrategy *pStrategy = m_pStgChain[iCurIdx];
	if (pStrategy)
		eReturn = pStrategy->Init(0, pCfg);

	WelsMutexUnlock(&m_mutes);

	return eReturn;
}

EResult CVpFrameWork::Uninit(int32_t iType)
{
	EResult eReturn        = RET_SUCCESS;
	int32_t iCurIdx    = WelsStaticCast(int32_t, WelsVpGetValidMethod(iType)) - 1;

	WelsMutexLock(&m_mutes);

	IStrategy *pStrategy = m_pStgChain[iCurIdx];
	if (pStrategy)
		eReturn = pStrategy->Uninit(0);

	WelsMutexUnlock(&m_mutes);

	return eReturn;
}

EResult CVpFrameWork::Flush(int32_t iType)
{
	EResult eReturn        = RET_SUCCESS;

	return eReturn;
}

EResult CVpFrameWork::Process(int32_t iType, SPixMap *pSrcPixMap, SPixMap *pDstPixMap)
{
	EResult eReturn        = RET_NOTSUPPORTED;
	EMethods eMethod    = WelsVpGetValidMethod(iType);
	int32_t iCurIdx    = WelsStaticCast(int32_t, eMethod) - 1;
	SPixMap sSrcPic;
	SPixMap sDstPic;
    memset(&sSrcPic, 0, sizeof(sSrcPic));// confirmed_safe_unsafe_usage
    memset(&sDstPic, 0, sizeof(sDstPic));// confirmed_safe_unsafe_usage

	if (pSrcPixMap) sSrcPic = *pSrcPixMap;
	if (pDstPixMap) sDstPic = *pDstPixMap;
	if (!CheckValid(eMethod, sSrcPic, sDstPic))
		return RET_INVALIDPARAM;

	WelsMutexLock(&m_mutes);

	IStrategy *pStrategy = m_pStgChain[iCurIdx];
	if (pStrategy)
		eReturn = pStrategy->Process(0, &sSrcPic, &sDstPic);

	WelsMutexUnlock(&m_mutes);

	return eReturn;
}

EResult CVpFrameWork::Get(int32_t iType, void *pParam)
{
	EResult eReturn        = RET_SUCCESS;
	int32_t iCurIdx    = WelsStaticCast(int32_t, WelsVpGetValidMethod(iType)) - 1;

	if (!pParam)
		return RET_INVALIDPARAM;

	WelsMutexLock(&m_mutes);

	IStrategy *pStrategy = m_pStgChain[iCurIdx];
	if (pStrategy)
		eReturn = pStrategy->Get(0, pParam);

	WelsMutexUnlock(&m_mutes);

	return eReturn;
}

EResult CVpFrameWork::Set(int32_t iType, void *pParam)
{
	EResult eReturn        = RET_SUCCESS;
	int32_t iCurIdx    = WelsStaticCast(int32_t, WelsVpGetValidMethod(iType)) - 1;

	if (!pParam)
		return RET_INVALIDPARAM;

	WelsMutexLock(&m_mutes);

	IStrategy *pStrategy = m_pStgChain[iCurIdx];
	if (pStrategy)
		eReturn = pStrategy->Set(0, pParam);

	WelsMutexUnlock(&m_mutes);

	return eReturn;
}

EResult CVpFrameWork::SpecialFeature(int32_t iType, void *pIn, void *pOut)
{
	EResult eReturn        = RET_SUCCESS;

	return eReturn;
}

bool_t  CVpFrameWork::CheckValid(EMethods eMethod, SPixMap &pSrcPixMap, SPixMap &pDstPixMap)
{
	bool_t eReturn = FALSE;

	if (eMethod == METHOD_NULL)
		goto exit;

	if (eMethod != METHOD_COLORSPACE_CONVERT)
	{
		if (pSrcPixMap.pPixel[0])
		{
			if (pSrcPixMap.eFormat != VIDEO_FORMAT_I420 && pSrcPixMap.eFormat != VIDEO_FORMAT_YV12)
				goto exit;
		}
		if (pSrcPixMap.pPixel[0] && pDstPixMap.pPixel[0])
		{
			if (pDstPixMap.eFormat != pSrcPixMap.eFormat)
				goto exit;
		}
	}

	if (pSrcPixMap.pPixel[0])
	{
		if (pSrcPixMap.sRect.iRectWidth <= 0 || pSrcPixMap.sRect.iRectWidth > MAX_WIDTH || pSrcPixMap.sRect.iRectHeight <= 0 || pSrcPixMap.sRect.iRectHeight > MAX_HEIGHT)
			goto exit;
		if (pSrcPixMap.sRect.iRectTop >= pSrcPixMap.sRect.iRectHeight || pSrcPixMap.sRect.iRectLeft >= pSrcPixMap.sRect.iRectWidth || pSrcPixMap.sRect.iRectWidth > pSrcPixMap.iStride[0])
			goto exit;
	}
	if (pDstPixMap.pPixel[0])
	{
		if (pDstPixMap.sRect.iRectWidth <= 0 || pDstPixMap.sRect.iRectWidth > MAX_WIDTH || pDstPixMap.sRect.iRectHeight <= 0 || pDstPixMap.sRect.iRectHeight > MAX_HEIGHT)
			goto exit;
		if (pDstPixMap.sRect.iRectTop >= pDstPixMap.sRect.iRectHeight || pDstPixMap.sRect.iRectLeft >= pDstPixMap.sRect.iRectWidth || pDstPixMap.sRect.iRectWidth > pDstPixMap.iStride[0])
			goto exit;
	}
	eReturn = TRUE;

exit:
	return eReturn;
}

IStrategy* CVpFrameWork::CreateStrategy(EMethods m_eMethod, int32_t iCpuFlag)
{
	IStrategy *pStrategy = NULL;

	switch (m_eMethod)
	{
	case METHOD_COLORSPACE_CONVERT:
		//not support yet
		break;
	case METHOD_DENOISE:
		pStrategy = WelsDynamicCast(IStrategy *, new CDenoiser(iCpuFlag));
		break;
	case METHOD_SCENE_CHANGE_DETECTION:
		pStrategy = WelsDynamicCast(IStrategy *, new CSceneChangeDetection(iCpuFlag));
		break;
	case METHOD_DOWNSAMPLE:
		pStrategy = WelsDynamicCast(IStrategy *, new CDownsampling(iCpuFlag));
		break;
	case METHOD_VAA_STATISTICS:
		pStrategy = WelsDynamicCast(IStrategy *, new CVAACalculation(iCpuFlag));
		break;
	case METHOD_BACKGROUND_DETECTION:
		pStrategy = WelsDynamicCast(IStrategy *, new CBackgroundDetection(iCpuFlag));
		break;
	case METHOD_ADAPTIVE_QUANT:
		pStrategy = WelsDynamicCast(IStrategy *, new CAdaptiveQuantization(iCpuFlag));
		break;
	case METHOD_COMPLEXITY_ANALYSIS:
		pStrategy = WelsDynamicCast(IStrategy *, new CComplexityAnalysis(iCpuFlag));
		break;
	case METHOD_IMAGE_ROTATE:
		pStrategy = WelsDynamicCast(IStrategy *, new CImageRotating(iCpuFlag));
		break;
	default:
		break;
	}

	return pStrategy;
}

WELSVP_NAMESPACE_END