/*! * \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 #include "welsEncoderExt.h" #include "welsCodecTrace.h" #include "typedefs.h" #include "wels_const.h" #include "utils.h" #include "macros.h" #include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms #include "ref_list_mgr_svc.h" #include #if defined(WIN32) /*&& defined(_DEBUG)*/ #include #include #include #include #include #else #include #endif namespace WelsSVCEnc { /* * CWelsH264SVCEncoder class implementation */ CWelsH264SVCEncoder::CWelsH264SVCEncoder() : m_pEncContext ( NULL ), #if defined(WIN32)||defined(_MACH_PLATFORM)||defined(__GNUC__) m_pWelsTrace ( NULL ), #endif m_pSrcPicList ( NULL ), m_iSrcListSize ( 0 ), m_iMaxPicWidth ( 0 ), m_iMaxPicHeight ( 0 ), m_iCspInternal ( 0 ), m_bInitialFlag ( FALSE ) { #ifdef REC_FRAME_COUNT int32_t m_uiCountFrameNum = 0; #endif//REC_FRAME_COUNT #ifdef OUTPUT_BIT_STREAM str_t strStreamFileName[1024] = { 0 }; //for .264 int32_t iBufferUsed = 0; int32_t iBufferLeft = 1023; str_t strLenFileName[1024] = { 0 }; //for .len int32_t iBufferUsedSize = 0; int32_t iBufferLeftSize = 1023; #endif//OUTPUT_BIT_STREAM #ifdef OUTPUT_BIT_STREAM time_t tTime; #if defined( WIN32 ) #if defined(_MSC_VER) #if _MSC_VER>=1500 struct tm tTimeNow; #else struct tm *tTimeNow; #endif//_MSC_VER>=1500 #endif//_MSC_VER struct _timeb tTimeb; time(&tTime); #if defined(_MSC_VER) #if _MSC_VER>=1500 LOCALTIME(&tTimeNow, &tTime); #else tTimeNow = LOCALTIME(&tTime); if ( NULL == tTimeNow ) return; #endif//_MSC_VER>=1500 #endif//_MSC_VER FTIME(&tTimeb); #elif defined( __GNUC__ ) struct tm* tTimeNow; struct timeval tTimev; time(&tTime); tTimeNow = (struct tm *)localtime(&tTime); gettimeofday(&tTimev,NULL); #endif//WIN32 #ifdef WIN32 #if defined(_MSC_VER) #if _MSC_VER>=1500 iBufferUsed += SNPRINTF(strStreamFileName, iBufferLeft, iBufferLeft, "enc_bs_0x%p_", (void*)this); iBufferUsedSize += SNPRINTF(strLenFileName, iBufferLeftSize, iBufferLeftSize, "enc_size_0x%p_", (void*)this); #else iBufferUsed += SNPRINTF(strStreamFileName, iBufferLeft, "enc_bs_0x%p_", (void*)this); iBufferUsedSize += SNPRINTF(strLenFileName, iBufferLeftSize, "enc_size_0x%p_", (void*)this); #endif//_MSC_VER>=1500 #endif//_MSC_VER #else iBufferUsed += SNPRINTF(strStreamFileName, iBufferLeft, "/tmp/enc_bs_0x%p_", (void*)this); iBufferUsedSize += SNPRINTF(strLenFileName, iBufferLeftSize, "/tmp/enc_size_0x%p", (void*)this); #endif//WIN32 iBufferLeft -= iBufferUsed; if ( iBufferLeft > iBufferUsed ) { #if defined(_GNUC__) iBufferUsed += strftime(&strStreamFileName[iBufferUsed], iBufferLeft, "%y%m%d%H%M%S", tTimeNow); #else #if defined(_MSC_VER) iBufferUsed += strftime(&strStreamFileName[iBufferUsed], iBufferLeft, "%y%m%d%H%M%S", #if _MSC_VER>=1500 &tTimeNow #else tTimeNow #endif//_MSC_VER>=1500 ); #endif//_MSC_VER #endif//__GNUC__ iBufferLeft -= iBufferUsed; } iBufferLeftSize -= iBufferUsedSize; if ( iBufferLeftSize> iBufferUsedSize ) { #if defined(_GNUC__) iBufferUsedSize += strftime(&strLenFileName[iBufferUsedSize], iBufferLeftSize, "%y%m%d%H%M%S", tTimeNow); #else #if defined(_MSC_VER) iBufferUsedSize += strftime(&strLenFileName[iBufferUsedSize], iBufferLeftSize, "%y%m%d%H%M%S", #if _MSC_VER>=1500 &tTimeNow #else tTimeNow #endif//_MSC_VER>=1500 ); #endif//_MSC_VER #endif//__GNUC__ iBufferLeftSize -= iBufferUsedSize; } if ( iBufferLeft > iBufferUsed ) { #ifdef WIN32 #if defined(_MSC_VER) #if _MSC_VER>=1500 iBufferUsed += SNPRINTF(&strStreamFileName[iBufferUsed], iBufferLeft, iBufferLeft, ".%03.3u.264", tTimeb.millitm); #else iBufferUsed += SNPRINTF(&strStreamFileName[iBufferUsed], iBufferLeft, ".%03.3u.264", tTimeb.millitm); #endif//_MSC_VER>=1500 #endif//_MSC_VER #else iBufferUsed += SNPRINTF(&strStreamFileName[iBufferUsed], iBufferLeft, ".%03.3u.264", tTimev.tv_usec/1000); #endif//WIN32 iBufferLeft -= iBufferUsed; } if ( iBufferLeftSize > iBufferUsedSize ) { #ifdef WIN32 #if defined(_MSC_VER) #if _MSC_VER>=1500 iBufferUsedSize += SNPRINTF(&strLenFileName[iBufferUsedSize], iBufferLeftSize, iBufferLeftSize, ".%03.3u.len", tTimeb.millitm); #else iBufferUsedSize += SNPRINTF(&strLenFileName[iBufferUsedSize], iBufferLeftSize, ".%03.3u.len", tTimeb.millitm); #endif//_MSC_VER>=1500 #endif//_MSC_VER #else iBufferUsedSize += SNPRINTF(&strLenFileName[iBufferUsedSize], iBufferLeftSize, ".%03.3u.len", tTimev.tv_usec/1000); #endif//WIN32 iBufferLeftSize -= iBufferUsedSize; } #if defined(__GNUC__) m_pFileBs = FOPEN(strStreamFileName, "wb"); m_pFileBsSize = FOPEN(strLenFileName, "wb"); #else #if defined(_MSC_VER) #if _MSC_VER>=1500 FOPEN(&m_pFileBs, strStreamFileName, "wb"); FOPEN(&m_pFileBsSize, strLenFileName, "wb"); #else m_pFileBs = FOPEN(strStreamFileName, "wb"); m_pFileBsSize = FOPEN(strLenFileName, "wb"); #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif//__GNUC__ m_bSwitch = FALSE; m_iSwitchTimes = 0; #endif//OUTPUT_BIT_STREAM InitEncoder(); } CWelsH264SVCEncoder::~CWelsH264SVCEncoder() { WelsLog(NULL, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()\n"); #if defined(WIN32)||defined(_MACH_PLATFORM)||defined(__GNUC__) if ( m_pWelsTrace != NULL ) { delete m_pWelsTrace; m_pWelsTrace = NULL; } #endif #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder(), m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif #ifdef REC_FRAME_COUNT m_uiCountFrameNum = 0; #endif//REC_FRAME_COUNT #ifdef OUTPUT_BIT_STREAM if ( m_pFileBs ) { fclose( m_pFileBs ); m_pFileBs = NULL; } if ( m_pFileBsSize ) { fclose( m_pFileBsSize ); m_pFileBsSize = NULL; } m_bSwitch = FALSE; m_iSwitchTimes = 0; #endif//OUTPUT_BIT_STREAM Unintialize(); } void CWelsH264SVCEncoder::InitEncoder( void ) { #if defined(WIN32)||defined(_MACH_PLATFORM)||defined(__GNUC__) #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::InitEncoder, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif m_pWelsTrace = new welsCodecTrace(); if ( m_pWelsTrace != NULL ) { const int32_t iWelsTraceExistingFlag = m_pWelsTrace->WelsTraceModuleIsExist(); if ( iWelsTraceExistingFlag ) { m_pWelsTrace->SetTraceLevel( WELS_LOG_DEFAULT ); WelsSetLogCallback( welsCodecTrace::CODEC_TRACE ); } } // initialization WelsSetLogLevel( WELS_LOG_DEFAULT ); // no output, WELS_LOG_QUIET #endif } /* Interfaces override from ISVCEncoder */ /* * SVC Encoder Initialization */ int CWelsH264SVCEncoder::Initialize(SVCEncodingParam* argv, const INIT_TYPE iInitType) { if ( INIT_TYPE_PARAMETER_BASED != iInitType || NULL == argv ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInitType= %d, argv= 0x%p\n", iInitType, (void *)argv); return cmInitParaError; } if ( m_bInitialFlag ) { WelsLog(m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d\n", m_bInitialFlag); Unintialize(); } SVCEncodingParam sEncodingParam; SWelsSvcCodingParam sConfig( true ); memcpy(&sEncodingParam, argv, sizeof(SVCEncodingParam)); // confirmed_safe_unsafe_usage #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Initialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); WelsLog( m_pEncContext, WELS_LOG_INFO, "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d;coding_param->iRCMode= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->iKeyPicCodingMode= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableCropPic= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n", sEncodingParam.iPicWidth, sEncodingParam.iPicHeight, sEncodingParam.iTargetBitrate, sEncodingParam.iRCMode, sEncodingParam.iTemporalLayerNum, sEncodingParam.iSpatialLayerNum, sEncodingParam.fFrameRate, sEncodingParam.iInputCsp, sEncodingParam.iKeyPicCodingMode, sEncodingParam.iIntraPeriod, sEncodingParam.bEnableSpsPpsIdAddition, sEncodingParam.bPrefixNalAddingCtrl, sEncodingParam.bEnableDenoise, sEncodingParam.bEnableBackgroundDetection, sEncodingParam.bEnableAdaptiveQuant, sEncodingParam.bEnableCropPic, sEncodingParam.bEnableLongTermReference, sEncodingParam.iLtrMarkPeriod); int32_t i = 0; while (i < sEncodingParam.iSpatialLayerNum) { SSpatialLayerConfig *spatial_cfg = &sEncodingParam.sSpatialLayers[i]; WelsLog( m_pEncContext, WELS_LOG_INFO, "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iQualityLayerNum= %d; .iSpatialBitrate= %d; .iCgsSnrRefined= %d; .iInterSpatialLayerPredFlag= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.uiSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n", i, spatial_cfg->iVideoWidth, spatial_cfg->iVideoHeight, spatial_cfg->fFrameRate, spatial_cfg->iQualityLayerNum, spatial_cfg->iSpatialBitrate, spatial_cfg->iCgsSnrRefined, spatial_cfg->iInterSpatialLayerPredFlag, spatial_cfg->sSliceCfg.uiSliceMode, spatial_cfg->sSliceCfg.sSliceArgument.uiSliceNum, spatial_cfg->sSliceCfg.sSliceArgument.uiSliceSizeConstraint ); ++ i; } #endif//REC_FRAME_COUNT // Convert SVCEncodingParam into WelsSVCParamConfig here.. if ( sConfig.ParamTranscode( sEncodingParam, true ) ){ WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n"); Unintialize(); return cmInitParaError; } m_iSrcListSize = 1; return Initialize((void *)&sConfig, INIT_TYPE_CONFIG_BASED); } int CWelsH264SVCEncoder::Initialize(void * argv, const INIT_TYPE iInitType) { if ( INIT_TYPE_CONFIG_BASED != iInitType || NULL == argv ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInitType= %d, argv= 0x%p.\n", iInitType, (void *)argv); return cmInitParaError; } if ( m_bInitialFlag ) { WelsLog(m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n", m_bInitialFlag); Unintialize(); } SWelsSvcCodingParam *pCfg = static_cast(argv); const int32_t iColorspace = pCfg->iInputCsp; if ( 0 == iColorspace ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n", iColorspace); Unintialize(); return cmInitParaError; } // Check valid parameters const int32_t iNumOfLayers = pCfg->iNumDependencyLayer; if ( iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER ){ WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iNumDependencyLayer= %d, valid at range of [1, %d].\n", iNumOfLayers, MAX_DEPENDENCY_LAYER); Unintialize(); return cmInitParaError; } if ( pCfg->iNumTemporalLayer < 1 ) pCfg->iNumTemporalLayer = 1; if ( pCfg->iNumTemporalLayer > MAX_TEMPORAL_LEVEL ){ WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iNumTemporalLayer= %d, valid at range of [1, %d].\n", pCfg->iNumTemporalLayer, MAX_TEMPORAL_LEVEL); Unintialize(); return cmInitParaError; } // assert( cfg.uiGopSize >= 1 && ( cfg.uiIntraPeriod && (cfg.uiIntraPeriod % cfg.uiGopSize) == 0) ); if ( pCfg->uiGopSize < 1 || pCfg->uiGopSize > MAX_GOP_SIZE ){ WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d].\n", pCfg->uiGopSize, MAX_GOP_SIZE); Unintialize(); return cmInitParaError; } if ( !WELS_POWER2_IF(pCfg->uiGopSize) ){ WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d] and yield to power of 2.\n", pCfg->uiGopSize, MAX_GOP_SIZE); Unintialize(); return cmInitParaError; } if ( pCfg->uiIntraPeriod && pCfg->uiIntraPeriod < pCfg->uiGopSize ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d.\n", pCfg->uiIntraPeriod, pCfg->uiGopSize); Unintialize(); return cmInitParaError; } if ( ( pCfg->uiIntraPeriod && (pCfg->uiIntraPeriod & (pCfg->uiGopSize-1)) != 0) ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d also multiple of it.\n", pCfg->uiIntraPeriod, pCfg->uiGopSize); Unintialize(); return cmInitParaError; } // Fine tune num_ref_num if (pCfg->bEnableLongTermReference){ pCfg->iLTRRefNum = LONG_TERM_REF_NUM; }else{ pCfg->iLTRRefNum = 0; } pCfg->iNumRefFrame = ((pCfg->uiGopSize>>1)>1)?((pCfg->uiGopSize>>1)+pCfg->iLTRRefNum):(MIN_REF_PIC_COUNT+pCfg->iLTRRefNum); pCfg->iNumRefFrame = WELS_CLIP3(pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM); if (pCfg->uiLtrMarkPeriod == 0) { pCfg->uiLtrMarkPeriod = 30; } const int32_t kiDecStages = WELS_LOG2( pCfg->uiGopSize ); pCfg->iInputCsp = iColorspace; pCfg->iNumTemporalLayer = (int8_t)(1 + kiDecStages); pCfg->iLoopFilterAlphaC0Offset = WELS_CLIP3( pCfg->iLoopFilterAlphaC0Offset, -6, 6 ); pCfg->iLoopFilterBetaOffset = WELS_CLIP3( pCfg->iLoopFilterBetaOffset, -6, 6 ); // m_pSrcPicList = (SSourcePicture **)WelsMalloc( pCfg->iNumDependencyLayer * sizeof(SSourcePicture *), "m_pSrcPicList" ); // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched) m_pSrcPicList = new SSourcePicture* [iNumOfLayers]; if ( NULL == m_pSrcPicList ){ WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), pOut of memory due m_pSrcPicList memory request.\n"); Unintialize(); return cmMallocMemeError; } // decide property list size between INIT_TYPE_PARAMETER_BASED/INIT_TYPE_CONFIG_BASED m_iMaxPicWidth = pCfg->iActualPicWidth; m_iMaxPicHeight = pCfg->iActualPicHeight; m_iSrcListSize = iNumOfLayers; for (int32_t i = 0; i < m_iSrcListSize; ++ i) { // m_pSrcPicList[i] = (SSourcePicture *)WelsMalloc( sizeof(SSourcePicture), "m_pSrcPicList[]" ); // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched) m_pSrcPicList[i] = new SSourcePicture; if ( NULL == m_pSrcPicList[i] ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), pOut of memory due m_pSrcPicList[%d] memory request.\n", i); Unintialize(); m_iSrcListSize = 0; return cmMallocMemeError; } InitPic( m_pSrcPicList[i], iColorspace, m_iMaxPicWidth, m_iMaxPicHeight ); } #if defined(OUTPUT_BIT_STREAM) || defined(ENABLE_TRACE_FILE) str_t fpath[MAX_FNAME_LEN] = {0}; #if defined(__GNUC__) SNPRINTF(fpath, MAX_FNAME_LEN, "/tmp/"); // confirmed_safe_unsafe_usage #else//__GNUC__ #if defined (_MSC_VER) #if _MSC_VER>=1500 SNPRINTF(fpath, MAX_FNAME_LEN, MAX_FNAME_LEN, ".\\" ); // confirmed_safe_unsafe_usage #else SNPRINTF(fpath, MAX_FNAME_LEN, ".\\" ); // confirmed_safe_unsafe_usage #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif //__GNUC__ strcpy(pCfg->sTracePath, fpath); // confirmed_safe_unsafe_usage #endif //#if defined(OUTPUT_BIT_STREAM) || defined(ENABLE_TRACE_FILE) if ( WelsInitEncoderExt( &m_pEncContext, pCfg ) ) { WelsLog(m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.\n"); Unintialize(); return cmInitParaError; } m_iCspInternal = iColorspace; m_bInitialFlag = TRUE; return cmResultSuccess; } /* * SVC Encoder Uninitialization */ int32_t CWelsH264SVCEncoder::Unintialize() { if ( !m_bInitialFlag ) { return 0; } WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Unintialize()..\n" ); #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Unintialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT if ( NULL != m_pEncContext ) { if ( NULL != m_pSrcPicList ) { for (int32_t i = 0; i < m_iSrcListSize; i++) { SSourcePicture *pic = m_pSrcPicList[i]; if ( NULL != pic ) { // WelsFree( pic, "m_pSrcPicList[]" ); // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched) delete pic; pic = NULL; } } // WelsFree( m_pSrcPicList, "m_pSrcPicList" ); // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched) delete [] m_pSrcPicList; m_pSrcPicList = NULL; m_iSrcListSize= 0; } WelsUninitEncoderExt( &m_pEncContext ); m_pEncContext = NULL; } m_bInitialFlag = FALSE; return 0; } int32_t CWelsH264SVCEncoder::RawData2SrcPic(const uint8_t * pSrc) { assert( m_iSrcListSize > 0 ); int32_t y_length = m_iMaxPicWidth * m_iMaxPicHeight; m_pSrcPicList[0]->pData[0] = const_cast(pSrc); switch(m_iCspInternal & (~videoFormatVFlip)) { case videoFormatYVYU: case videoFormatUYVY: case videoFormatYUY2: case videoFormatRGB: case videoFormatBGR: case videoFormatBGRA: case videoFormatRGBA: case videoFormatARGB: case videoFormatABGR: m_pSrcPicList[0]->pData[1] = m_pSrcPicList[0]->pData[2] = NULL; break; case videoFormatI420: case videoFormatYV12: m_pSrcPicList[0]->pData[1] = m_pSrcPicList[0]->pData[0] + y_length; m_pSrcPicList[0]->pData[2] = m_pSrcPicList[0]->pData[1] + ( y_length >> 2 ); break; default: return 1; } return 0; } /* * SVC core encoding */ int CWelsH264SVCEncoder::EncodeFrame(const unsigned char* pSrc, SFrameBSInfo* pBsInfo) { if ( !(pSrc && m_pEncContext && m_bInitialFlag) ) { return videoFrameTypeInvalid; } int32_t uiFrameType = videoFrameTypeInvalid; if( RawData2SrcPic((uint8_t *)pSrc) == 0 ){ uiFrameType = EncodeFrame(const_cast(m_pSrcPicList), 1, pBsInfo); } #ifdef REC_FRAME_COUNT ++ m_uiCountFrameNum; WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::EncodeFrame(), m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT #ifdef DUMP_SRC_PICTURE DumpSrcPicture(pSrc); #endif // DUMP_SRC_PICTURE return uiFrameType; } int CWelsH264SVCEncoder::EncodeFrame(const SSourcePicture ** pSrcPicList, int nSrcPicNum, SFrameBSInfo * pBsInfo) { if ( !(pSrcPicList && m_pEncContext && m_bInitialFlag) ) { return videoFrameTypeInvalid; } int32_t iFrameTypeReturned = 0; int32_t iFrameType = videoFrameTypeInvalid; if (nSrcPicNum > 0) { iFrameTypeReturned = WelsEncoderEncodeExt( m_pEncContext, pBsInfo, pSrcPicList, nSrcPicNum); } else { assert ( 0 ); return videoFrameTypeInvalid; } switch( iFrameTypeReturned ) { case WELS_FRAME_TYPE_P: iFrameType = videoFrameTypeP; break; case WELS_FRAME_TYPE_IDR: iFrameType = videoFrameTypeIDR; break; case WELS_FRAME_TYPE_SKIP: iFrameType = videoFrameTypeSkip; break; case WELS_FRAME_TYPE_I: iFrameType = videoFrameTypeI; break; case WELS_FRAME_TYPE_AUTO: case WELS_FRAME_TYPE_B: // not support B pictures iFrameType = videoFrameTypeInvalid; break; default: break; } ///////////////////for test #ifdef OUTPUT_BIT_STREAM if ( iFrameType != videoFrameTypeInvalid && iFrameType != videoFrameTypeSkip ) { SLayerBSInfo* pLayer = NULL; int32_t i = 0, j = 0, iCurLayerBits = 0, total_bits = 0; if ( m_bSwitch ) { if ( m_pFileBs ) { fclose( m_pFileBs ); m_pFileBs = NULL; } if ( m_pFileBsSize ) { fclose( m_pFileBsSize ); m_pFileBsSize = NULL; } str_t strStreamFileName[128] = {0}; #if defined(__GNUC__) int32_t iLen = SNPRINTF(strStreamFileName, 128, "%sadj%d_w%d.264", m_pEncContext->sTracePath, m_iSwitchTimes, m_pEncContext->pSvcParam->iActualPicWidth); m_pFileBs = FOPEN( strStreamFileName, "wb" ); SNPRINTF(strStreamFileName, 128, "%sadj%d_w%d_size.iLen", m_pEncContext->sTracePath, m_iSwitchTimes, m_pEncContext->pSvcParam->iActualPicWidth); m_pFileBsSize = FOPEN( strStreamFileName, "wb"); #else//__GNUC__ #if defined (_MSC_VER) #if _MSC_VER>=1500 int32_t iLen = SNPRINTF(strStreamFileName, 128, 128, "adj%d_w%d.264", m_iSwitchTimes, m_pEncContext->pSvcParam->iActualPicWidth); FOPEN( &m_pFileBs, strStreamFileName, "wb" ); SNPRINTF(strStreamFileName, 128, 128, "adj%d_w%d_size.iLen", m_iSwitchTimes, m_pEncContext->pSvcParam->iActualPicWidth); FOPEN( &m_pFileBsSize, strStreamFileName, "wb"); #else int32_t iLen = SNPRINTF(strStreamFileName, 128, "adj%d_w%d.264", m_iSwitchTimes, m_pEncContext->pSvcParam->iActualPicWidth); m_pFileBs = FOPEN( strStreamFileName, "wb" ); SNPRINTF(strStreamFileName, 128, "adj%d_w%d_size.iLen", m_iSwitchTimes, m_pEncContext->pSvcParam->iActualPicWidth); m_pFileBsSize = FOPEN( strStreamFileName, "wb"); #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif//__GNUC__ m_bSwitch = FALSE; } for ( i = 0; i < pBsInfo->iLayerNum; i++ ) { pLayer = &pBsInfo->sLayerInfo[i]; iCurLayerBits = 0; for ( j = 0; j < pLayer->iNalCount; j++ ) { iCurLayerBits += pLayer->iNalLengthInByte[j]; } total_bits += iCurLayerBits; if ( m_pFileBs != NULL ) fwrite( pLayer->pBsBuf, 1, iCurLayerBits, m_pFileBs ); } if ( m_pFileBsSize != NULL ) fwrite( &total_bits, sizeof(int32_t), 1, m_pFileBsSize ); } #endif //OUTPUT_BIT_STREAM #ifdef DUMP_SRC_PICTURE DumpSrcPicture(pSrcPicList[0]->pData[0]); #endif // DUMP_SRC_PICTURE return iFrameType; } /* * return: 0 - success; otherwise - failed; */ int CWelsH264SVCEncoder::PauseFrame(const unsigned char* kpSrc, SFrameBSInfo* pBsInfo) { int32_t iReturn = 1; ForceIntraFrame(true); if( EncodeFrame(kpSrc, pBsInfo) != videoFrameTypeInvalid ){ iReturn = 0; } // to avoid pause frame bitstream and // normal bitstream use different video channel. ForceIntraFrame(true); return (int)iReturn; } /* * Force key frame */ int CWelsH264SVCEncoder::ForceIntraFrame(bool bIDR) { if ( !(m_pEncContext && m_bInitialFlag) ) { return 1; } #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::ForceIntraFrame(), bIDR= %d, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", bIDR, m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT ForceCodingIDR( m_pEncContext ); return 0; } /************************************************************************ * InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,.. ************************************************************************/ int CWelsH264SVCEncoder::SetOption(ENCODER_OPTION eOptionId, void* pOption) { if ( NULL == pOption ){ return cmInitParaError; } if ( NULL == m_pEncContext || FALSE == m_bInitialFlag ){ return cmInitExpected; } switch( eOptionId ) { case ENCODER_OPTION_INTER_SPATIAL_PRED: // Inter spatial layer prediction flag { WelsLog( m_pEncContext, WELS_LOG_INFO, "ENCODER_OPTION_INTER_SPATIAL_PRED, this feature not supported at present.\n" ); } break; case ENCODER_OPTION_DATAFORMAT: // Input color space { int32_t iValue = *((int32_t*)pOption); int32_t iColorspace = iValue; if ( iColorspace == 0 ){ return cmInitParaError; } #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_DATAFORMAT, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n", m_uiCountFrameNum, m_iCspInternal, iValue ); #endif//REC_FRAME_COUNT int32_t iPicIdx = m_iSrcListSize -1; while ( iPicIdx >= 0 ) { if ( m_pSrcPicList[iPicIdx] == NULL ) { -- iPicIdx; if (iPicIdx < 0) return cmInitParaError; continue; } if ( m_pSrcPicList[iPicIdx]->iColorFormat == iColorspace ) { -- iPicIdx; continue; } InitPic( m_pSrcPicList[iPicIdx], iColorspace, m_iMaxPicWidth, m_iMaxPicHeight ); } m_iCspInternal = iColorspace; #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_DATAFORMAT, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT } break; case ENCODER_OPTION_IDR_INTERVAL: // IDR Interval { int32_t iValue = *((int32_t*)pOption); #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_IDR_INTERVAL, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n", m_uiCountFrameNum, m_iCspInternal, iValue ); #endif//REC_FRAME_COUNT if ( iValue < -1 || iValue == 0 ) iValue = 1; if ( iValue == (int32_t)m_pEncContext->pSvcParam->uiIntraPeriod ){ return cmResultSuccess; } m_pEncContext->pSvcParam->uiIntraPeriod = (uint32_t)iValue; } break; case ENCODER_OPTION_SVC_ENCODE_PARAM: // SVC Encoding Parameter { SVCEncodingParam sEncodingParam; SWelsSvcCodingParam sConfig( true ); int32_t iInputColorspace = 0; int32_t iTargetWidth = 0; int32_t iTargetHeight= 0; memcpy(&sEncodingParam, pOption, sizeof(SVCEncodingParam)); // confirmed_safe_unsafe_usage WelsLog( m_pEncContext, WELS_LOG_INFO, "ENCODER_OPTION_SVC_ENCODE_PARAM, sEncodingParam.iInputCsp= 0x%x\n", sEncodingParam.iInputCsp ); WelsLog( m_pEncContext, WELS_LOG_INFO, "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d;coding_param->iRCMode= %d;coding_param->iPaddingFlag= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->iKeyPicCodingMode= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableCropPic= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n", sEncodingParam.iPicWidth, sEncodingParam.iPicHeight, sEncodingParam.iTargetBitrate, sEncodingParam.iRCMode, sEncodingParam.iPaddingFlag, sEncodingParam.iTemporalLayerNum, sEncodingParam.iSpatialLayerNum, sEncodingParam.fFrameRate, sEncodingParam.iInputCsp, sEncodingParam.iKeyPicCodingMode, sEncodingParam.iIntraPeriod, sEncodingParam.bEnableSpsPpsIdAddition, sEncodingParam.bPrefixNalAddingCtrl, sEncodingParam.bEnableDenoise, sEncodingParam.bEnableBackgroundDetection, sEncodingParam.bEnableAdaptiveQuant, sEncodingParam.bEnableCropPic, sEncodingParam.bEnableLongTermReference, sEncodingParam.iLtrMarkPeriod); int32_t i = 0; while (i < sEncodingParam.iSpatialLayerNum) { SSpatialLayerConfig *pSpatialCfg = &sEncodingParam.sSpatialLayers[i]; WelsLog( m_pEncContext, WELS_LOG_INFO, "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iQualityLayerNum= %d; .iSpatialBitrate= %d; .iCgsSnrRefined= %d; .iInterSpatialLayerPredFlag= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.iSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n", i, pSpatialCfg->iVideoWidth, pSpatialCfg->iVideoHeight, pSpatialCfg->fFrameRate, pSpatialCfg->iQualityLayerNum, pSpatialCfg->iSpatialBitrate, pSpatialCfg->iCgsSnrRefined, pSpatialCfg->iInterSpatialLayerPredFlag, pSpatialCfg->sSliceCfg.uiSliceMode, pSpatialCfg->sSliceCfg.sSliceArgument.uiSliceNum, pSpatialCfg->sSliceCfg.sSliceArgument.uiSliceSizeConstraint ); ++ i; } #ifdef OUTPUT_BIT_STREAM if ( sEncodingParam.sSpatialLayers[sEncodingParam.iSpatialLayerNum-1].iVideoWidth != m_pEncContext->pSvcParam->sDependencyLayers[m_pEncContext->pSvcParam->iNumDependencyLayer-1].iFrameWidth ) { ++ m_iSwitchTimes; m_bSwitch = TRUE; } #endif//OUTPUT_BIT_STREAM if ( sEncodingParam.iSpatialLayerNum < 1 || sEncodingParam.iSpatialLayerNum > MAX_SPATIAL_LAYER_NUM ) // verify number of spatial layer { return cmInitParaError; } iInputColorspace = sEncodingParam.iInputCsp; if ( sConfig.ParamTranscode( sEncodingParam, true ) ) { return cmInitParaError; } if ( sConfig.iNumDependencyLayer < 1 ) { return cmInitParaError; } iTargetWidth = sConfig.iActualPicWidth; iTargetHeight = sConfig.iActualPicHeight; if ( m_pSrcPicList[0] == NULL ) { return cmInitParaError; } if ( m_iCspInternal != iInputColorspace || m_iMaxPicWidth != iTargetWidth || m_iMaxPicHeight != iTargetHeight ){ // for color space due to changed InitPic( m_pSrcPicList[0], iInputColorspace, iTargetWidth, iTargetHeight ); m_iMaxPicWidth = iTargetWidth; m_iMaxPicHeight = iTargetHeight; m_iCspInternal = iInputColorspace; } #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT /* New configuration available here */ sConfig.iInputCsp = m_iCspInternal; // I420 in default designed for presentation in encoder used internal sConfig.DetermineTemporalSettings(); /* Check every field whether there is new request for memory block changed or else, Oct. 24, 2008 */ WelsEncoderParamAdjust( &m_pEncContext, &sConfig ); } break; case ENCODER_OPTION_FRAME_RATE: // Maximal input frame rate { float iValue = *((float*)pOption); #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_FRAME_RATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n", m_uiCountFrameNum, m_iCspInternal, iValue ); #endif//REC_FRAME_COUNT m_pEncContext->pSvcParam->fMaxFrameRate = iValue; } break; case ENCODER_OPTION_iBitRate: // Target bit-rate { int32_t iValue = *((int32_t*)pOption); #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_iBitRate, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n", m_uiCountFrameNum, m_iCspInternal, iValue ); #endif//REC_FRAME_COUNT m_pEncContext->pSvcParam->iTargetBitrate = iValue; } break; case ENCODER_OPTION_RC_MODE: // 0:quality mode;1:bit-rate mode { int32_t iValue = *((int32_t*)pOption); m_pEncContext->pSvcParam->iRCMode = iValue; } break; case ENCODER_PADDING_PADDING: // 0:disable padding;1:padding { int32_t iValue = *((int32_t*)pOption); m_pEncContext->pSvcParam->iPaddingFlag = iValue; } break; case ENCODER_LTR_RECOVERY_REQUEST: { SLTRRecoverRequest* pLTR_Recover_Request = (SLTRRecoverRequest*)(pOption); FilterLTRRecoveryRequest(m_pEncContext,pLTR_Recover_Request); } break; case ENCODER_LTR_MARKING_FEEDBACK: { SLTRMarkingFeedback* fb = (SLTRMarkingFeedback*)(pOption); FilterLTRMarkingFeedback(m_pEncContext,fb); } break; case ENCOCER_LTR_MARKING_PERIOD: { uint32_t iValue = *((uint32_t*)(pOption)); m_pEncContext->pSvcParam->uiLtrMarkPeriod = iValue; } break; case ENCODER_OPTION_LTR: { uint32_t iValue = *((uint32_t*)(pOption)); m_pEncContext->pSvcParam->bEnableLongTermReference = iValue?true:false; WelsLog(m_pEncContext,WELS_LOG_WARNING," CWelsH264SVCEncoder::SetOption enable LTR = %d",m_pEncContext->pSvcParam->bEnableLongTermReference); } break; case ENCODER_OPTION_ENABLE_SSEI: { bool_t iValue = *((bool_t*)pOption); m_pEncContext->pSvcParam->bEnableSSEI = iValue; WelsLog( m_pEncContext, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption enable SSEI = %d \n", m_pEncContext->pSvcParam->bEnableSSEI ); } break; case ENCODER_OPTION_ENABLE_PREFIX_NAL_ADDING: { bool_t iValue = *((bool_t*)pOption); m_pEncContext->pSvcParam->bPrefixNalAddingCtrl = iValue; WelsLog( m_pEncContext, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption bPrefixNalAddingCtrl = %d \n", m_pEncContext->pSvcParam->bPrefixNalAddingCtrl ); } break; case ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION: { bool_t iValue = *((bool_t*)pOption); m_pEncContext->pSvcParam->bEnableSpsPpsIdAddition = iValue; WelsLog( m_pEncContext, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption enable SPS/PPS ID = %d \n", m_pEncContext->pSvcParam->bEnableSpsPpsIdAddition ); } break; case ENCODER_OPTION_CURRENT_PATH: { if (m_pEncContext->pSvcParam != NULL) { str_t * path = static_cast(pOption); m_pEncContext->pSvcParam->pCurPath = path; } } break; default: return cmInitParaError; } return 0; } int CWelsH264SVCEncoder::GetOption(ENCODER_OPTION eOptionId, void* pOption) { if ( NULL == pOption ){ return cmInitParaError; } if ( NULL == m_pEncContext || FALSE == m_bInitialFlag ){ return cmInitExpected; } switch( eOptionId ) { case ENCODER_OPTION_INTER_SPATIAL_PRED: // Inter spatial layer prediction flag { WelsLog( m_pEncContext, WELS_LOG_INFO, "ENCODER_OPTION_INTER_SPATIAL_PRED, this feature not supported at present.\n" ); } break; case ENCODER_OPTION_DATAFORMAT: // Input color space { #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_DATAFORMAT, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT *((int32_t*)pOption) = m_iCspInternal; } break; case ENCODER_OPTION_IDR_INTERVAL: // IDR Interval { #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_IDR_INTERVAL, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT *((int32_t*)pOption) = m_pEncContext->pSvcParam->uiIntraPeriod; } break; case ENCODER_OPTION_SVC_ENCODE_PARAM: // SVC Encoding Parameter { #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_SVC_ENCODE_PARAM, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT memcpy( pOption, m_pEncContext->pSvcParam, sizeof(SWelsSvcCodingParam) ); // confirmed_safe_unsafe_usage } break; case ENCODER_OPTION_FRAME_RATE: // Maximal input frame rate { #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_FRAME_RATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT *((float*)pOption) = m_pEncContext->pSvcParam->fMaxFrameRate; } break; case ENCODER_OPTION_iBitRate: // Target bit-rate { #ifdef REC_FRAME_COUNT WelsLog( m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_iBitRate, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal ); #endif//REC_FRAME_COUNT *((int32_t*)pOption) = m_pEncContext->pSvcParam->iTargetBitrate; } break; default: return cmInitParaError; } return 0; } void CWelsH264SVCEncoder::DumpSrcPicture(const uint8_t *pSrc) { #ifdef DUMP_SRC_PICTURE FILE *pFile = NULL; str_t strFileName[256] = {0}; const int32_t iDataLength = m_iMaxPicWidth * m_iMaxPicHeight; #if defined(__GNUC__) STRNCPY(strFileName, 256, "/tmp/pic_in_", STRNLEN("/tmp/pic_in_", 255)); // confirmed_safe_unsafe_usage #else STRNCPY(strFileName, 256, "d:\\incoming\\mosaic_st\\pic_in_", STRNLEN("d:\\incoming\\mosaic_st\\pic_in_", 255)); // confirmed_safe_unsafe_usage #endif//__GNUC__ if ( m_iMaxPicWidth == 640 ) { STRCAT(strFileName, 256, "360p."); // confirmed_safe_unsafe_usage } else if ( m_iMaxPicWidth == 320 ) { STRCAT(strFileName, 256, "180p."); // confirmed_safe_unsafe_usage } else if ( m_iMaxPicWidth == 160 ) { STRCAT(strFileName, 256, "90p."); // confirmed_safe_unsafe_usage } switch( m_iCspInternal) { case videoFormatI420: case videoFormatYV12: STRCAT(strFileName, 256, "yuv"); // confirmed_safe_unsafe_usage #if defined(__GNUC__) pFile = FOPEN(strFileName, "ab+"); #else #if defined(_MSC_VER) #if _MSC_VER>=1500 FOPEN(&pFile, strFileName, "ab+"); #else pFile = FOPEN(strFileName, "ab+"); #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif//__GNUC__ // WelsLog( m_pEncContext, WELS_LOG_INFO, "WELS_CSP_I420, m_iCspInternal= 0x%x\n", m_iCspInternal); if (NULL != pFile) { fwrite( pSrc, sizeof(uint8_t), (iDataLength * 3)>>1, pFile ); fflush( pFile ); fclose(pFile); } break; case videoFormatRGB: STRCAT(strFileName, 256, "rgb"); // confirmed_safe_unsafe_usage #if defined(__GNUC__) pFile = FOPEN(strFileName, "ab+"); #else #if defined(_MSC_VER) #if _MSC_VER>=1500 FOPEN(&pFile, strFileName, "ab+"); #else pFile = FOPEN(strFileName, "ab+"); #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif//__GNUC__ if ( NULL != pFile ) { fwrite( pSrc, sizeof(uint8_t), iDataLength * 3, pFile ); fflush( pFile ); fclose( pFile ); } case videoFormatBGR: STRCAT(strFileName, 256, "bgr"); // confirmed_safe_unsafe_usage #if defined(__GNUC__) pFile = FOPEN(strFileName, "ab+"); #else #if defined(_MSC_VER) #if _MSC_VER>=1500 FOPEN(&pFile, strFileName, "ab+"); #else pFile = FOPEN(strFileName, "ab+"); #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif//__GNUC__ // WelsLog( m_pEncContext, WELS_LOG_INFO, "WELS_CSP_BGR, m_iCspInternal= 0x%x\n", m_iCspInternal); if ( NULL != pFile ) { fwrite( pSrc, sizeof(uint8_t), iDataLength * 3, pFile ); fflush( pFile ); fclose( pFile ); } break; case videoFormatYUY2: STRCAT(strFileName, 256, "yuy2"); // confirmed_safe_unsafe_usage #if defined(__GNUC__) pFile = FOPEN(strFileName, "ab+"); #else #if defined(_MSC_VER) #if _MSC_VER>=1500 FOPEN(&pFile, strFileName, "ab+"); #else pFile = FOPEN(strFileName, "ab+"); #endif//_MSC_VER>=1500 #endif//_MSC_VER #endif//__GNUC__ if ( NULL != pFile ) { fwrite( pSrc, sizeof(uint8_t), (CALC_BI_STRIDE(m_iMaxPicWidth, 16)) * m_iMaxPicHeight, pFile ); fflush( pFile ); fclose( pFile ); } break; default: WelsLog( m_pEncContext, WELS_LOG_INFO, "Exclusive case, m_iCspInternal= 0x%x\n", m_iCspInternal); break; } #endif//DUMP_SRC_PICTURE return; } } using namespace WelsSVCEnc; int32_t CreateSVCEncoder(ISVCEncoder** ppEncoder) { assert( ppEncoder ); if ( NULL == ppEncoder ) return 1; if( ( *ppEncoder = new CWelsH264SVCEncoder() ) != NULL ) { return 0; } return 1; } void DestroySVCEncoder(ISVCEncoder* pEncoder) { CWelsH264SVCEncoder *pSVCEncoder = (CWelsH264SVCEncoder*)pEncoder; if( pSVCEncoder ){ delete pSVCEncoder; pSVCEncoder = NULL; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////