/*! * \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 <assert.h>#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 <time.h>#if defined(_WIN32) /*&& defined(_DEBUG)*/ #include <windows.h>#include <stdio.h>#include <stdarg.h>#include <sys/types.h>#include <sys/timeb.h>#else#include <sys/time.h>#endif namespace WelsSVCEnc { /* * CWelsH264SVCEncoder class implementation */CWelsH264SVCEncoder::CWelsH264SVCEncoder() : m_pEncContext (NULL), m_pWelsTrace (NULL), 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 char strStreamFileName[1024] = { 0 }; //for .264 int32_t iBufferUsed = 0; int32_t iBufferLeft = 1023; int32_t iCurUsed; char strLenFileName[1024] = { 0 }; //for .len int32_t iBufferUsedSize = 0; int32_t iBufferLeftSize = 1023; int32_t iCurUsedSize;#endif//OUTPUT_BIT_STREAM #ifdef OUTPUT_BIT_STREAM SWelsTime tTime; WelsGetTimeOfDay(&tTime); iCurUsed = WelsSnprintf (strStreamFileName, iBufferLeft, "enc_bs_0x%p_", (void*)this); iCurUsedSize = WelsSnprintf (strLenFileName, iBufferLeftSize, "enc_size_0x%p_", (void*)this); if (iCurUsed > 0) { iBufferUsed += iCurUsed; iBufferLeft -= iCurUsed; } if (iBufferLeft > 0) { iCurUsed = WelsStrftime (&strStreamFileName[iBufferUsed], iBufferLeft, "%y%m%d%H%M%S", &tTime); iBufferUsed += iCurUsed; iBufferLeft -= iCurUsed; } if (iCurUsedSize > 0) { iBufferUsedSize += iCurUsedSize; iBufferLeftSize -= iCurUsedSize; } if (iBufferLeftSize > 0) { iCurUsedSize = WelsStrftime (&strLenFileName[iBufferUsedSize], iBufferLeftSize, "%y%m%d%H%M%S", &tTime); iBufferUsedSize += iCurUsedSize; iBufferLeftSize -= iCurUsedSize; } if (iBufferLeft > 0) { iCurUsed = WelsSnprintf (&strStreamFileName[iBufferUsed], iBufferLeft, ".%03.3u.264", WelsGetMillisecond(&tTime)); if (iCurUsed > 0) { iBufferUsed += iCurUsed; iBufferLeft -= iCurUsed; } } if (iBufferLeftSize > 0) { iCurUsedSize = WelsSnprintf (&strLenFileName[iBufferUsedSize], iBufferLeftSize, ".%03.3u.len", WelsGetMillisecond(&tTime)); if (iCurUsedSize > 0) { iBufferUsedSize += iCurUsedSize; iBufferLeftSize -= iCurUsedSize; } } m_pFileBs = WelsFopen (strStreamFileName, "wb"); m_pFileBsSize = WelsFopen (strLenFileName, "wb"); m_bSwitch = false; m_iSwitchTimes = 0;#endif//OUTPUT_BIT_STREAM InitEncoder(); XMMREG_PROTECT_INIT(CWelsH264SVCEncoder);} CWelsH264SVCEncoder::~CWelsH264SVCEncoder() { WelsLog (NULL, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()\n"); if (m_pWelsTrace != NULL) { delete m_pWelsTrace; m_pWelsTrace = NULL; }#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) { WelsFclose (m_pFileBs); m_pFileBs = NULL; } if (m_pFileBsSize) { WelsFclose (m_pFileBsSize); m_pFileBsSize = NULL; } m_bSwitch = false; m_iSwitchTimes = 0;#endif//OUTPUT_BIT_STREAM Uninitialize(); XMMREG_PROTECT_UNINIT(CWelsH264SVCEncoder);} void CWelsH264SVCEncoder::InitEncoder (void) { #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} /* Interfaces override from ISVCEncoder */ /* * SVC Encoder Initialization */int CWelsH264SVCEncoder::Initialize (const SEncParamBase* argv, const INIT_TYPE iInitType) { if ((INIT_TYPE_PARAMETER_BASED != iInitType && INIT_TYPE_PARAMETER_EXT != iInitType)|| NULL == argv) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInitType= %d, argv= 0x%p\n", iInitType, (void*)argv); return cmInitParaError; } SWelsSvcCodingParam sConfig (true); if(iInitType == INIT_TYPE_PARAMETER_BASED) { // Convert SEncParamBase into WelsSVCParamConfig here.. if (sConfig.ParamBaseTranscode (*argv, true)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n"); Uninitialize(); return cmInitParaError; } } else if(iInitType == INIT_TYPE_PARAMETER_EXT) { // Convert SEncParamExt into WelsSVCParamConfig here.. if (sConfig.ParamTranscode (*(const SEncParamExt*)argv, true)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n"); Uninitialize(); return cmInitParaError; } } return Initialize2 (&sConfig);} int CWelsH264SVCEncoder::Initialize2 (SWelsSvcCodingParam* pCfg) { if (NULL == pCfg) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.\n", pCfg); return cmInitParaError; } if (m_bInitialFlag) { WelsLog (m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n", m_bInitialFlag); Uninitialize(); } #ifdef REC_FRAME_COUNT SWelsSvcCodingParam &sEncodingParam = *pCfg; 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->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableFrameSkip= %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.fMaxFrameRate, sEncodingParam.iInputCsp, sEncodingParam.uiIntraPeriod, sEncodingParam.bEnableSpsPpsIdAddition, sEncodingParam.bPrefixNalAddingCtrl, sEncodingParam.bEnableDenoise, sEncodingParam.bEnableBackgroundDetection, sEncodingParam.bEnableAdaptiveQuant, sEncodingParam.bEnableFrameSkip, 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 const int32_t iColorspace = pCfg->iInputCsp; if (0 == iColorspace) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n", iColorspace); Uninitialize(); return cmInitParaError; } // Check valid parameters const int32_t iNumOfLayers = pCfg->iSpatialLayerNum; if (iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d].\n", iNumOfLayers, MAX_DEPENDENCY_LAYER); Uninitialize(); return cmInitParaError; } if (pCfg->iTemporalLayerNum < 1) pCfg->iTemporalLayerNum = 1; if (pCfg->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d].\n", pCfg->iTemporalLayerNum, MAX_TEMPORAL_LEVEL); Uninitialize(); 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); Uninitialize(); 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); Uninitialize(); 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); Uninitialize(); 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); Uninitialize(); 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->iLtrMarkPeriod == 0) { pCfg->iLtrMarkPeriod = 30; } const int32_t kiDecStages = WELS_LOG2 (pCfg->uiGopSize); pCfg->iInputCsp = iColorspace; pCfg->iTemporalLayerNum = (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->iSpatialLayerNum * 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"); Uninitialize(); return cmMallocMemeError; } // decide property list size between INIT_TYPE_PARAMETER_BASED/INIT_TYPE_CONFIG_BASED m_iMaxPicWidth = pCfg->iPicWidth; m_iMaxPicHeight = pCfg->iPicHeight; 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); Uninitialize(); m_iSrcListSize = 0; return cmMallocMemeError; } InitPic (m_pSrcPicList[i], iColorspace, m_iMaxPicWidth, m_iMaxPicHeight); } if (WelsInitEncoderExt (&m_pEncContext, pCfg)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.\n"); Uninitialize(); return cmInitParaError; } m_iCspInternal = iColorspace; m_bInitialFlag = true; return cmResultSuccess;} /* * SVC Encoder Uninitialization */int32_t CWelsH264SVCEncoder::Uninitialize() { if (!m_bInitialFlag) { return 0; } WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize()..\n"); #ifdef REC_FRAME_COUNT WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize, 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<uint8_t*> (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;Lines 1–500 of 1076. Load more
/*! * \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 <assert.h> #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 <time.h> #if defined(_WIN32) /*&& defined(_DEBUG)*/ #include <windows.h> #include <stdio.h> #include <stdarg.h> #include <sys/types.h> #include <sys/timeb.h> #else #include <sys/time.h> #endif namespace WelsSVCEnc { /* * CWelsH264SVCEncoder class implementation */ CWelsH264SVCEncoder::CWelsH264SVCEncoder() : m_pEncContext (NULL), m_pWelsTrace (NULL), 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 char strStreamFileName[1024] = { 0 }; //for .264 int32_t iBufferUsed = 0; int32_t iBufferLeft = 1023; int32_t iCurUsed; char strLenFileName[1024] = { 0 }; //for .len int32_t iBufferUsedSize = 0; int32_t iBufferLeftSize = 1023; int32_t iCurUsedSize; #endif//OUTPUT_BIT_STREAM #ifdef OUTPUT_BIT_STREAM SWelsTime tTime; WelsGetTimeOfDay(&tTime); iCurUsed = WelsSnprintf (strStreamFileName, iBufferLeft, "enc_bs_0x%p_", (void*)this); iCurUsedSize = WelsSnprintf (strLenFileName, iBufferLeftSize, "enc_size_0x%p_", (void*)this); if (iCurUsed > 0) { iBufferUsed += iCurUsed; iBufferLeft -= iCurUsed; } if (iBufferLeft > 0) { iCurUsed = WelsStrftime (&strStreamFileName[iBufferUsed], iBufferLeft, "%y%m%d%H%M%S", &tTime); iBufferUsed += iCurUsed; iBufferLeft -= iCurUsed; } if (iCurUsedSize > 0) { iBufferUsedSize += iCurUsedSize; iBufferLeftSize -= iCurUsedSize; } if (iBufferLeftSize > 0) { iCurUsedSize = WelsStrftime (&strLenFileName[iBufferUsedSize], iBufferLeftSize, "%y%m%d%H%M%S", &tTime); iBufferUsedSize += iCurUsedSize; iBufferLeftSize -= iCurUsedSize; } if (iBufferLeft > 0) { iCurUsed = WelsSnprintf (&strStreamFileName[iBufferUsed], iBufferLeft, ".%03.3u.264", WelsGetMillisecond(&tTime)); if (iCurUsed > 0) { iBufferUsed += iCurUsed; iBufferLeft -= iCurUsed; } } if (iBufferLeftSize > 0) { iCurUsedSize = WelsSnprintf (&strLenFileName[iBufferUsedSize], iBufferLeftSize, ".%03.3u.len", WelsGetMillisecond(&tTime)); if (iCurUsedSize > 0) { iBufferUsedSize += iCurUsedSize; iBufferLeftSize -= iCurUsedSize; } } m_pFileBs = WelsFopen (strStreamFileName, "wb"); m_pFileBsSize = WelsFopen (strLenFileName, "wb"); m_bSwitch = false; m_iSwitchTimes = 0; #endif//OUTPUT_BIT_STREAM InitEncoder(); XMMREG_PROTECT_INIT(CWelsH264SVCEncoder); } CWelsH264SVCEncoder::~CWelsH264SVCEncoder() { WelsLog (NULL, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()\n"); if (m_pWelsTrace != NULL) { delete m_pWelsTrace; m_pWelsTrace = NULL; } #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) { WelsFclose (m_pFileBs); m_pFileBs = NULL; } if (m_pFileBsSize) { WelsFclose (m_pFileBsSize); m_pFileBsSize = NULL; } m_bSwitch = false; m_iSwitchTimes = 0; #endif//OUTPUT_BIT_STREAM Uninitialize(); XMMREG_PROTECT_UNINIT(CWelsH264SVCEncoder); } void CWelsH264SVCEncoder::InitEncoder (void) { #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 } /* Interfaces override from ISVCEncoder */ /* * SVC Encoder Initialization */ int CWelsH264SVCEncoder::Initialize (const SEncParamBase* argv, const INIT_TYPE iInitType) { if ((INIT_TYPE_PARAMETER_BASED != iInitType && INIT_TYPE_PARAMETER_EXT != iInitType)|| NULL == argv) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInitType= %d, argv= 0x%p\n", iInitType, (void*)argv); return cmInitParaError; } SWelsSvcCodingParam sConfig (true); if(iInitType == INIT_TYPE_PARAMETER_BASED) { // Convert SEncParamBase into WelsSVCParamConfig here.. if (sConfig.ParamBaseTranscode (*argv, true)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n"); Uninitialize(); return cmInitParaError; } } else if(iInitType == INIT_TYPE_PARAMETER_EXT) { // Convert SEncParamExt into WelsSVCParamConfig here.. if (sConfig.ParamTranscode (*(const SEncParamExt*)argv, true)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n"); Uninitialize(); return cmInitParaError; } } return Initialize2 (&sConfig); } int CWelsH264SVCEncoder::Initialize2 (SWelsSvcCodingParam* pCfg) { if (NULL == pCfg) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.\n", pCfg); return cmInitParaError; } if (m_bInitialFlag) { WelsLog (m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n", m_bInitialFlag); Uninitialize(); } #ifdef REC_FRAME_COUNT SWelsSvcCodingParam &sEncodingParam = *pCfg; 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->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableFrameSkip= %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.fMaxFrameRate, sEncodingParam.iInputCsp, sEncodingParam.uiIntraPeriod, sEncodingParam.bEnableSpsPpsIdAddition, sEncodingParam.bPrefixNalAddingCtrl, sEncodingParam.bEnableDenoise, sEncodingParam.bEnableBackgroundDetection, sEncodingParam.bEnableAdaptiveQuant, sEncodingParam.bEnableFrameSkip, 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 const int32_t iColorspace = pCfg->iInputCsp; if (0 == iColorspace) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n", iColorspace); Uninitialize(); return cmInitParaError; } // Check valid parameters const int32_t iNumOfLayers = pCfg->iSpatialLayerNum; if (iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d].\n", iNumOfLayers, MAX_DEPENDENCY_LAYER); Uninitialize(); return cmInitParaError; } if (pCfg->iTemporalLayerNum < 1) pCfg->iTemporalLayerNum = 1; if (pCfg->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d].\n", pCfg->iTemporalLayerNum, MAX_TEMPORAL_LEVEL); Uninitialize(); 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); Uninitialize(); 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); Uninitialize(); 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); Uninitialize(); 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); Uninitialize(); 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->iLtrMarkPeriod == 0) { pCfg->iLtrMarkPeriod = 30; } const int32_t kiDecStages = WELS_LOG2 (pCfg->uiGopSize); pCfg->iInputCsp = iColorspace; pCfg->iTemporalLayerNum = (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->iSpatialLayerNum * 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"); Uninitialize(); return cmMallocMemeError; } // decide property list size between INIT_TYPE_PARAMETER_BASED/INIT_TYPE_CONFIG_BASED m_iMaxPicWidth = pCfg->iPicWidth; m_iMaxPicHeight = pCfg->iPicHeight; 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); Uninitialize(); m_iSrcListSize = 0; return cmMallocMemeError; } InitPic (m_pSrcPicList[i], iColorspace, m_iMaxPicWidth, m_iMaxPicHeight); } if (WelsInitEncoderExt (&m_pEncContext, pCfg)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.\n"); Uninitialize(); return cmInitParaError; } m_iCspInternal = iColorspace; m_bInitialFlag = true; return cmResultSuccess; } /* * SVC Encoder Uninitialization */ int32_t CWelsH264SVCEncoder::Uninitialize() { if (!m_bInitialFlag) { return 0; } WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize()..\n"); #ifdef REC_FRAME_COUNT WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize, 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<uint8_t*> (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;