openh264/codec/encoder/plus/src/welsEncoderExt.cpp
2013-12-12 14:21:12 -08:00

1227 lines
42 KiB
C++

/*!
* \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),
#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
Uninitialize();
}
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);
Uninitialize();
}
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");
Uninitialize();
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);
Uninitialize();
}
SWelsSvcCodingParam* pCfg = static_cast<SWelsSvcCodingParam*> (argv);
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->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);
Uninitialize();
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);
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->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");
Uninitialize();
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);
Uninitialize();
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");
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;
if (RawData2SrcPic ((uint8_t*)pSrc) == 0) {
uiFrameType = EncodeFrame (const_cast<const SSourcePicture**> (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<str_t*> (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;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////