555 lines
17 KiB
C++
555 lines
17 KiB
C++
|
/*!
|
||
|
* \copy
|
||
|
* Copyright (c) 2009-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 encoder.c
|
||
|
*
|
||
|
* \brief core encoder
|
||
|
*
|
||
|
* \date 5/14/2009 Created
|
||
|
*
|
||
|
*************************************************************************************
|
||
|
*/
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <assert.h>
|
||
|
#include "encoder.h"
|
||
|
#include "extern.h"
|
||
|
#include "cpu.h"
|
||
|
#include "cpu_core.h"
|
||
|
#include "utils.h"
|
||
|
|
||
|
#include "encode_mb_aux.h"
|
||
|
#include "decode_mb_aux.h"
|
||
|
#include "get_intra_predictor.h"
|
||
|
#include "svc_encode_mb.h"
|
||
|
|
||
|
#include "deblocking.h"
|
||
|
#include "expand_pic.h"
|
||
|
|
||
|
#include "mc.h"
|
||
|
#include "sample.h"
|
||
|
|
||
|
#include "svc_encode_slice.h"
|
||
|
#include "svc_base_layer_md.h"
|
||
|
#include "svc_mode_decision.h"
|
||
|
#include "set_mb_syn_cavlc.h"
|
||
|
#include "crt_util_safe_x.h" // Safe CRT routines like utils for cross_platforms
|
||
|
#include "codec_def.h"
|
||
|
#ifdef MT_ENABLED
|
||
|
#include "slice_multi_threading.h"
|
||
|
#endif//MT_ENABLED
|
||
|
|
||
|
// global function pointers definition
|
||
|
namespace WelsSVCEnc {
|
||
|
/* Motion compensation */
|
||
|
|
||
|
|
||
|
/*!
|
||
|
* \brief initialize source picture body
|
||
|
* \param pSrc SSourcePicture*
|
||
|
* \param csp internal csp format
|
||
|
* \param iWidth widht of picture in pixels
|
||
|
* \param iHeight iHeight of picture in pixels
|
||
|
* \return successful - 0; otherwise none 0 for failed
|
||
|
*/
|
||
|
int32_t InitPic( const void *kpSrc, const int32_t kiColorspace, const int32_t kiWidth, const int32_t kiHeight )
|
||
|
{
|
||
|
SSourcePicture *pSrcPic = (SSourcePicture *)kpSrc;
|
||
|
|
||
|
if ( NULL == pSrcPic || kiWidth == 0 || kiHeight == 0 )
|
||
|
return 1;
|
||
|
|
||
|
pSrcPic->iColorFormat = kiColorspace;
|
||
|
pSrcPic->iPicWidth = kiWidth;
|
||
|
pSrcPic->iPicHeight = kiHeight;
|
||
|
|
||
|
switch( kiColorspace & (~videoFormatVFlip) ) {
|
||
|
case videoFormatI420:
|
||
|
case videoFormatYV12:
|
||
|
pSrcPic->pData[0] = NULL;
|
||
|
pSrcPic->pData[1] = NULL;
|
||
|
pSrcPic->pData[2] = NULL;
|
||
|
pSrcPic->pData[3] = NULL;
|
||
|
pSrcPic->iStride[0] = kiWidth;
|
||
|
pSrcPic->iStride[2] = pSrcPic->iStride[1] = kiWidth >> 1;
|
||
|
pSrcPic->iStride[3] = 0;
|
||
|
break;
|
||
|
case videoFormatYUY2:
|
||
|
case videoFormatYVYU:
|
||
|
case videoFormatUYVY:
|
||
|
pSrcPic->pData[0] = NULL;
|
||
|
pSrcPic->pData[1] = NULL;
|
||
|
pSrcPic->pData[2] = NULL;
|
||
|
pSrcPic->pData[3] = NULL;
|
||
|
pSrcPic->iStride[0] = CALC_BI_STRIDE(kiWidth, 16);
|
||
|
pSrcPic->iStride[3] = pSrcPic->iStride[2] = pSrcPic->iStride[1] = 0;
|
||
|
break;
|
||
|
case videoFormatRGB:
|
||
|
case videoFormatBGR:
|
||
|
pSrcPic->pData[0] = NULL;
|
||
|
pSrcPic->pData[1] = NULL;
|
||
|
pSrcPic->pData[2] = NULL;
|
||
|
pSrcPic->pData[3] = NULL;
|
||
|
pSrcPic->iStride[0] = CALC_BI_STRIDE(kiWidth, 24);
|
||
|
pSrcPic->iStride[3] = pSrcPic->iStride[2] = pSrcPic->iStride[1] = 0;
|
||
|
if( kiColorspace & videoFormatVFlip )
|
||
|
pSrcPic->iColorFormat = kiColorspace & (~videoFormatVFlip);
|
||
|
else
|
||
|
pSrcPic->iColorFormat = kiColorspace | videoFormatVFlip;
|
||
|
break;
|
||
|
case videoFormatBGRA:
|
||
|
case videoFormatRGBA:
|
||
|
case videoFormatARGB:
|
||
|
case videoFormatABGR:
|
||
|
pSrcPic->pData[0] = NULL;
|
||
|
pSrcPic->pData[1] = NULL;
|
||
|
pSrcPic->pData[2] = NULL;
|
||
|
pSrcPic->pData[3] = NULL;
|
||
|
pSrcPic->iStride[0] = kiWidth << 2;
|
||
|
pSrcPic->iStride[3] = pSrcPic->iStride[2] = pSrcPic->iStride[1] = 0;
|
||
|
if( kiColorspace & videoFormatVFlip )
|
||
|
pSrcPic->iColorFormat = kiColorspace & (~videoFormatVFlip);
|
||
|
else
|
||
|
pSrcPic->iColorFormat = kiColorspace | videoFormatVFlip;
|
||
|
break;
|
||
|
default:
|
||
|
return 2; // any else?
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void WelsInitBGDFunc( SWelsFuncPtrList *pFuncList, const bool_t kbEnableBackgroundDetection )
|
||
|
{
|
||
|
if ( kbEnableBackgroundDetection )
|
||
|
{
|
||
|
pFuncList->pfInterMdBackgroundDecision = (PInterMdBackgroundDecisionFunc)WelsMdInterJudgeBGDPskip;
|
||
|
pFuncList->pfInterMdBackgroundInfoUpdate = (PInterMdBackgroundInfoUpdateFunc)WelsMdInterUpdateBGDInfo;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pFuncList->pfInterMdBackgroundDecision = (PInterMdBackgroundDecisionFunc)WelsMdInterJudgeBGDPskipFalse;
|
||
|
pFuncList->pfInterMdBackgroundInfoUpdate = (PInterMdBackgroundInfoUpdateFunc)WelsMdInterUpdateBGDInfoNULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \brief initialize function pointers that potentially used in Wels encoding
|
||
|
* \param pEncCtx sWelsEncCtx*
|
||
|
* \return successful - 0; otherwise none 0 for failed
|
||
|
*/
|
||
|
int32_t InitFunctionPointers( SWelsFuncPtrList *pFuncList, SWelsSvcCodingParam *pParam, uint32_t uiCpuFlag )
|
||
|
{
|
||
|
int32_t iReturn = 0;
|
||
|
|
||
|
/* Functionality utilization of CPU instructions dependency */
|
||
|
pFuncList->pfSetMemZeroSize8 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage
|
||
|
pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage
|
||
|
pFuncList->pfSetMemZeroSize64 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage
|
||
|
#if defined(X86_ASM)
|
||
|
if ( uiCpuFlag & WELS_CPU_MMXEXT )
|
||
|
{
|
||
|
pFuncList->pfSetMemZeroSize8 = WelsSetMemZeroSize8_mmx; // confirmed_safe_unsafe_usage
|
||
|
pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZeroSize64_mmx; // confirmed_safe_unsafe_usage
|
||
|
pFuncList->pfSetMemZeroSize64 = WelsSetMemZeroSize64_mmx; // confirmed_safe_unsafe_usage
|
||
|
}
|
||
|
if ( uiCpuFlag & WELS_CPU_SSE2 )
|
||
|
{
|
||
|
pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZeroAligned64_sse2; // confirmed_safe_unsafe_usage
|
||
|
}
|
||
|
#endif//X86_ASM
|
||
|
|
||
|
InitExpandPictureFunc( pFuncList, uiCpuFlag );
|
||
|
|
||
|
/* Intra_Prediction_fn*/
|
||
|
WelsInitFillingPredFuncs( uiCpuFlag );
|
||
|
WelsInitIntraPredFuncs( pFuncList, uiCpuFlag );
|
||
|
|
||
|
/* sad, satd, average */
|
||
|
WelsInitSampleSadFunc(pFuncList, uiCpuFlag);
|
||
|
|
||
|
//
|
||
|
WelsInitBGDFunc(pFuncList, pParam->bEnableBackgroundDetection );
|
||
|
// for pfGetVarianceFromIntraVaa function ptr adaptive by CPU features, 6/7/2010
|
||
|
InitIntraAnalysisVaaInfo( pFuncList, uiCpuFlag );
|
||
|
|
||
|
/* Motion compensation */
|
||
|
/*init pixel average function*/
|
||
|
/*get one column or row pixel when refinement*/
|
||
|
WelsInitMcFuncs(pFuncList, uiCpuFlag);
|
||
|
InitCoeffFunc( uiCpuFlag );
|
||
|
|
||
|
WelsInitEncodingFuncs( pFuncList, uiCpuFlag );
|
||
|
WelsInitReconstructionFuncs( pFuncList, uiCpuFlag );
|
||
|
|
||
|
DeblockingInit( &pFuncList->pfDeblocking, uiCpuFlag );
|
||
|
WelsBlockFuncInit( &pFuncList->pfSetNZCZero, uiCpuFlag );
|
||
|
|
||
|
InitFillNeighborCacheInterFunc ( pFuncList, pParam->bEnableBackgroundDetection );
|
||
|
|
||
|
return iReturn;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \brief initialize frame coding
|
||
|
*/
|
||
|
void InitFrameCoding( sWelsEncCtx *pEncCtx, const EFrameType keFrameType )
|
||
|
{
|
||
|
// for bitstream writing
|
||
|
pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position
|
||
|
pEncCtx->pOut->iNalIndex = 0; // reset NAL index
|
||
|
|
||
|
InitBits( &pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize );
|
||
|
|
||
|
if ( keFrameType == WELS_FRAME_TYPE_P )
|
||
|
{
|
||
|
if ( pEncCtx->pSvcParam->uiIntraPeriod )
|
||
|
{
|
||
|
++pEncCtx->iFrameIndex;
|
||
|
}
|
||
|
|
||
|
++pEncCtx->uiFrameIdxRc;
|
||
|
|
||
|
if ( pEncCtx->iPOC < ( 1 << pEncCtx->pSps->iLog2MaxPocLsb ) - 2 ) // if iPOC type is no 0, this need be modification
|
||
|
pEncCtx->iPOC += 2; // for POC type 0
|
||
|
else
|
||
|
pEncCtx->iPOC = 0;
|
||
|
|
||
|
if ( pEncCtx->eLastNalPriority != 0 )
|
||
|
{
|
||
|
if ( pEncCtx->iFrameNum < (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1 )
|
||
|
++ pEncCtx->iFrameNum;
|
||
|
else
|
||
|
pEncCtx->iFrameNum = 0; // if iFrameNum overflow
|
||
|
}
|
||
|
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
|
||
|
pEncCtx->eSliceType = P_SLICE;
|
||
|
pEncCtx->eNalPriority = NRI_PRI_HIGH;
|
||
|
}
|
||
|
else if ( keFrameType == WELS_FRAME_TYPE_IDR )
|
||
|
{
|
||
|
pEncCtx->iFrameNum = 0;
|
||
|
pEncCtx->iPOC = 0;
|
||
|
pEncCtx->bEncCurFrmAsIdrFlag = false;
|
||
|
if ( pEncCtx->pSvcParam->uiIntraPeriod )
|
||
|
{
|
||
|
pEncCtx->iFrameIndex = 0;
|
||
|
}
|
||
|
pEncCtx->uiFrameIdxRc = 0;
|
||
|
|
||
|
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE_IDR;
|
||
|
pEncCtx->eSliceType = I_SLICE;
|
||
|
pEncCtx->eNalPriority = NRI_PRI_HIGHEST;
|
||
|
|
||
|
pEncCtx->iCodingIndex = 0;
|
||
|
|
||
|
// reset_ref_list
|
||
|
|
||
|
// rc_init_gop
|
||
|
}
|
||
|
else if ( keFrameType == WELS_FRAME_TYPE_I )
|
||
|
{
|
||
|
if ( pEncCtx->iPOC < ( 1 << pEncCtx->pSps->iLog2MaxPocLsb ) - 2 ) // if iPOC type is no 0, this need be modification
|
||
|
pEncCtx->iPOC += 2; // for POC type 0
|
||
|
else
|
||
|
pEncCtx->iPOC = 0;
|
||
|
|
||
|
if ( pEncCtx->eLastNalPriority != 0 )
|
||
|
{
|
||
|
if ( pEncCtx->iFrameNum < (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1 )
|
||
|
++ pEncCtx->iFrameNum;
|
||
|
else
|
||
|
pEncCtx->iFrameNum = 0; // if iFrameNum overflow
|
||
|
}
|
||
|
|
||
|
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
|
||
|
pEncCtx->eSliceType = I_SLICE;
|
||
|
pEncCtx->eNalPriority = NRI_PRI_HIGHEST;
|
||
|
|
||
|
// rc_init_gop
|
||
|
}
|
||
|
else // B pictures are not supported now, any else?
|
||
|
{
|
||
|
assert( 0 );
|
||
|
}
|
||
|
|
||
|
#if defined(STAT_OUTPUT)
|
||
|
memset( &pEncCtx->sPerInfo, 0, sizeof(SStatSliceInfo) );
|
||
|
#endif//FRAME_INFO_OUTPUT
|
||
|
|
||
|
#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
|
||
|
if ( pEncCtx->pSvcParam->iMultipleThreadIdc > 1 )
|
||
|
reset_env_mt( pEncCtx );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
EFrameType DecideFrameType( sWelsEncCtx *pEncCtx, const int8_t kiSpatialNum )
|
||
|
{
|
||
|
SWelsSvcCodingParam *pSvcParam = pEncCtx->pSvcParam;
|
||
|
EFrameType iFrameType = WELS_FRAME_TYPE_AUTO;
|
||
|
bool_t bSceneChangeFlag = false;
|
||
|
|
||
|
// perform scene change detection
|
||
|
if ( (!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag ||
|
||
|
(kiSpatialNum < pSvcParam->iNumDependencyLayer) || (pEncCtx->uiFrameIdxRc < (VGOP_SIZE << 1)) ) // avoid too frequent I frame coding, rc control
|
||
|
{
|
||
|
bSceneChangeFlag = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag;
|
||
|
}
|
||
|
|
||
|
//scene_changed_flag: RC enable && iSpatialNum == pSvcParam->iNumDependencyLayer
|
||
|
//bIdrPeriodFlag: RC disable || iSpatialNum != pSvcParam->iNumDependencyLayer
|
||
|
//pEncCtx->bEncCurFrmAsIdrFlag: 1. first frame should be IDR; 2. idr pause; 3. idr request
|
||
|
iFrameType = ( pEncCtx->pVaa->bIdrPeriodFlag || bSceneChangeFlag || pEncCtx->bEncCurFrmAsIdrFlag ) ? WELS_FRAME_TYPE_IDR : WELS_FRAME_TYPE_P;
|
||
|
|
||
|
if ( WELS_FRAME_TYPE_P == iFrameType && pEncCtx->iSkipFrameFlag > 0 ) // for frame skip, 1/5/2010
|
||
|
{
|
||
|
-- pEncCtx->iSkipFrameFlag;
|
||
|
iFrameType = WELS_FRAME_TYPE_SKIP;
|
||
|
}
|
||
|
else if ( WELS_FRAME_TYPE_IDR == iFrameType )
|
||
|
{
|
||
|
pEncCtx->iCodingIndex = 0;
|
||
|
}
|
||
|
|
||
|
return iFrameType;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \brief Dump reconstruction for dependency layer
|
||
|
*/
|
||
|
|
||
|
extern "C" void DumpDependencyRec( SPicture *pCurPicture, const str_t *kpFileName, const int8_t kiDid )
|
||
|
{
|
||
|
FILE *pDumpRecFile = NULL;
|
||
|
static bool_t bDependencyRecFlag[MAX_DEPENDENCY_LAYER] = {0};
|
||
|
int32_t iWrittenSize = 0;
|
||
|
|
||
|
if ( NULL == pCurPicture || NULL == kpFileName || kiDid >= MAX_DEPENDENCY_LAYER )
|
||
|
return;
|
||
|
|
||
|
if ( bDependencyRecFlag[kiDid] )
|
||
|
{
|
||
|
if ( STRNLEN(kpFileName, MAX_FNAME_LEN) > 0 ) // confirmed_safe_unsafe_usage
|
||
|
#if defined(__GNUC__) || (defined(WIN32) && defined(_MSC_VER) && (_MSC_VER<1500))
|
||
|
pDumpRecFile = FOPEN( kpFileName, "ab" );
|
||
|
#elif defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
FOPEN(&pDumpRecFile, kpFileName, "ab");
|
||
|
#endif//__GNUC__..
|
||
|
else
|
||
|
{
|
||
|
str_t sDependencyRecFileName[16] = {0};
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
SNPRINTF( sDependencyRecFileName, 16, 16, "rec%d.yuv", kiDid ); // confirmed_safe_unsafe_usage
|
||
|
FOPEN( &pDumpRecFile, sDependencyRecFileName, "ab" );
|
||
|
#else
|
||
|
SNPRINTF( sDependencyRecFileName, 16, "rec%d.yuv", kiDid ); // confirmed_safe_unsafe_usage
|
||
|
pDumpRecFile = FOPEN( sDependencyRecFileName, "ab" );
|
||
|
#endif//WIN32..
|
||
|
}
|
||
|
if ( NULL != pDumpRecFile)
|
||
|
fseek( pDumpRecFile, 0, SEEK_END );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( STRNLEN(kpFileName, MAX_FNAME_LEN) > 0 ) // confirmed_safe_unsafe_usage
|
||
|
{
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
FOPEN(&pDumpRecFile, kpFileName, "wb");
|
||
|
#else
|
||
|
pDumpRecFile = FOPEN( kpFileName, "wb" );
|
||
|
#endif//WIN32..
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
str_t sDependencyRecFileName[16] = {0};
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
SNPRINTF( sDependencyRecFileName, 16, 16, "rec%d.yuv", kiDid ); // confirmed_safe_unsafe_usage
|
||
|
FOPEN(&pDumpRecFile, sDependencyRecFileName, "wb");
|
||
|
#else
|
||
|
SNPRINTF( sDependencyRecFileName, 16, "rec%d.yuv", kiDid ); // confirmed_safe_unsafe_usage
|
||
|
pDumpRecFile = FOPEN( sDependencyRecFileName, "wb");
|
||
|
#endif//WIN32..
|
||
|
}
|
||
|
bDependencyRecFlag[kiDid] = true;
|
||
|
}
|
||
|
|
||
|
if ( NULL != pDumpRecFile )
|
||
|
{
|
||
|
int32_t i = 0;
|
||
|
int32_t j = 0;
|
||
|
const int32_t kiStrideY = pCurPicture->iLineSize[0];
|
||
|
const int32_t kiLumaWidth = pCurPicture->iWidthInPixel;
|
||
|
const int32_t kiLumaHeight = pCurPicture->iHeightInPixel;
|
||
|
const int32_t kiChromaWidth = kiLumaWidth >> 1;
|
||
|
const int32_t kiChromaHeight = kiLumaHeight >> 1;
|
||
|
|
||
|
for( j = 0; j < kiLumaHeight; ++ j)
|
||
|
{
|
||
|
iWrittenSize = fwrite( &pCurPicture->pData[0][j*kiStrideY], 1, kiLumaWidth, pDumpRecFile );
|
||
|
assert( iWrittenSize == kiLumaWidth );
|
||
|
if ( iWrittenSize < kiLumaWidth )
|
||
|
{
|
||
|
assert( 0 ); // make no sense for us if writing failed
|
||
|
fclose(pDumpRecFile);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
for( i = 1; i < I420_PLANES; ++ i)
|
||
|
{
|
||
|
const int32_t kiStrideUV = pCurPicture->iLineSize[i];
|
||
|
for ( j = 0; j < kiChromaHeight; ++ j)
|
||
|
{
|
||
|
iWrittenSize = fwrite( &pCurPicture->pData[i][j*kiStrideUV], 1, kiChromaWidth, pDumpRecFile );
|
||
|
assert(iWrittenSize == kiChromaWidth );
|
||
|
if ( iWrittenSize < kiChromaWidth )
|
||
|
{
|
||
|
assert( 0 ); // make no sense for us if writing failed
|
||
|
fclose(pDumpRecFile);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(pDumpRecFile);
|
||
|
pDumpRecFile = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \brief Dump the reconstruction pictures
|
||
|
*/
|
||
|
|
||
|
void DumpRecFrame( SPicture *pCurPicture, const str_t *kpFileName )
|
||
|
{
|
||
|
FILE *pDumpRecFile = NULL;
|
||
|
static bool_t bRecFlag = false;
|
||
|
int32_t iWrittenSize = 0;
|
||
|
|
||
|
if ( NULL == pCurPicture || NULL == kpFileName )
|
||
|
return;
|
||
|
|
||
|
if ( bRecFlag )
|
||
|
{
|
||
|
if ( STRNLEN(kpFileName, MAX_FNAME_LEN) > 0 ) // confirmed_safe_unsafe_usage
|
||
|
{
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
FOPEN(&pDumpRecFile, kpFileName, "ab");
|
||
|
#else
|
||
|
pDumpRecFile = FOPEN( kpFileName, "ab" );
|
||
|
#endif//WIN32
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
FOPEN(&pDumpRecFile, "rec.yuv", "ab");
|
||
|
#else
|
||
|
pDumpRecFile = FOPEN( "rec.yuv", "ab" );
|
||
|
#endif//WIN32
|
||
|
}
|
||
|
if ( NULL != pDumpRecFile)
|
||
|
fseek( pDumpRecFile, 0, SEEK_END );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( STRNLEN(kpFileName, MAX_FNAME_LEN) > 0 ) // confirmed_safe_unsafe_usage
|
||
|
{
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
FOPEN(&pDumpRecFile, kpFileName, "wb");
|
||
|
#else
|
||
|
pDumpRecFile = FOPEN( kpFileName, "wb" );
|
||
|
#endif//WIN32
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER>=1500) // vs2008
|
||
|
FOPEN(&pDumpRecFile, "rec.yuv", "wb");
|
||
|
#else
|
||
|
pDumpRecFile = FOPEN( "rec.yuv", "wb");
|
||
|
#endif//WIN32..
|
||
|
}
|
||
|
bRecFlag = true;
|
||
|
}
|
||
|
|
||
|
if ( NULL != pDumpRecFile )
|
||
|
{
|
||
|
int32_t i = 0;
|
||
|
int32_t j = 0;
|
||
|
const int32_t kiStrideY = pCurPicture->iLineSize[0];
|
||
|
const int32_t kiLumaWidth = pCurPicture->iWidthInPixel;
|
||
|
const int32_t kiLumaHeight = pCurPicture->iHeightInPixel;
|
||
|
const int32_t kiChromaWidth = kiLumaWidth >> 1;
|
||
|
const int32_t kiChromaHeight = kiLumaHeight >> 1;
|
||
|
|
||
|
for( j = 0; j < kiLumaHeight; ++ j)
|
||
|
{
|
||
|
iWrittenSize = fwrite( &pCurPicture->pData[0][j*kiStrideY], 1, kiLumaWidth, pDumpRecFile );
|
||
|
assert( iWrittenSize == kiLumaWidth );
|
||
|
if ( iWrittenSize < kiLumaWidth )
|
||
|
{
|
||
|
assert( 0 ); // make no sense for us if writing failed
|
||
|
fclose(pDumpRecFile);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
for( i = 1; i < I420_PLANES; ++ i)
|
||
|
{
|
||
|
const int32_t kiStrideUV = pCurPicture->iLineSize[i];
|
||
|
for ( j = 0; j < kiChromaHeight; ++ j)
|
||
|
{
|
||
|
iWrittenSize = fwrite( &pCurPicture->pData[i][j*kiStrideUV], 1, kiChromaWidth, pDumpRecFile );
|
||
|
assert(iWrittenSize == kiChromaWidth );
|
||
|
if ( iWrittenSize < kiChromaWidth )
|
||
|
{
|
||
|
assert( 0 ); // make no sense for us if writing failed
|
||
|
fclose(pDumpRecFile);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(pDumpRecFile);
|
||
|
pDumpRecFile = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************/
|
||
|
void WelsSetMemZero_c(void *pDst, int32_t iSize) // confirmed_safe_unsafe_usage
|
||
|
{
|
||
|
memset(pDst, 0, iSize);
|
||
|
}
|
||
|
}
|