2013-12-12 14:21:12 -08:00
/*!
* \ 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>
2013-12-15 15:18:19 +08:00
# if defined(_WIN32) /*&& defined(_DEBUG)*/
2013-12-12 14:21:12 -08:00
# 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 ) ,
2014-02-08 23:39:27 +02:00
m_bInitialFlag ( false ) {
2013-12-12 14:21:12 -08:00
# ifdef REC_FRAME_COUNT
int32_t m_uiCountFrameNum = 0 ;
# endif //REC_FRAME_COUNT
# ifdef OUTPUT_BIT_STREAM
2014-02-08 23:28:42 +02:00
char strStreamFileName [ 1024 ] = { 0 } ; //for .264
2013-12-12 14:21:12 -08:00
int32_t iBufferUsed = 0 ;
int32_t iBufferLeft = 1023 ;
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
int32_t iCurUsed ;
2013-12-12 14:21:12 -08:00
2014-02-08 23:28:42 +02:00
char strLenFileName [ 1024 ] = { 0 } ; //for .len
2013-12-12 14:21:12 -08:00
int32_t iBufferUsedSize = 0 ;
int32_t iBufferLeftSize = 1023 ;
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
int32_t iCurUsedSize ;
2013-12-12 14:21:12 -08:00
# endif //OUTPUT_BIT_STREAM
# ifdef OUTPUT_BIT_STREAM
2014-01-26 15:04:14 +02:00
SWelsTime tTime ;
2013-12-12 14:21:12 -08:00
2014-01-26 15:04:14 +02:00
WelsGetTimeOfDay ( & tTime ) ;
2013-12-12 14:21:12 -08:00
2014-01-26 14:43:30 +02:00
iCurUsed = WelsSnprintf ( strStreamFileName , iBufferLeft , " enc_bs_0x%p_ " , ( void * ) this ) ;
iCurUsedSize = WelsSnprintf ( strLenFileName , iBufferLeftSize , " enc_size_0x%p_ " , ( void * ) this ) ;
2013-12-12 14:21:12 -08:00
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
if ( iCurUsed > 0 ) {
iBufferUsed + = iCurUsed ;
iBufferLeft - = iCurUsed ;
}
2014-01-26 00:40:22 +02:00
if ( iBufferLeft > 0 ) {
2014-01-26 15:04:14 +02:00
iCurUsed = WelsStrftime ( & strStreamFileName [ iBufferUsed ] , iBufferLeft , " %y%m%d%H%M%S " , & tTime ) ;
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
iBufferUsed + = iCurUsed ;
iBufferLeft - = iCurUsed ;
2013-12-12 14:21:12 -08:00
}
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
if ( iCurUsedSize > 0 ) {
iBufferUsedSize + = iCurUsedSize ;
iBufferLeftSize - = iCurUsedSize ;
}
2014-01-26 00:40:22 +02:00
if ( iBufferLeftSize > 0 ) {
2014-01-26 15:04:14 +02:00
iCurUsedSize = WelsStrftime ( & strLenFileName [ iBufferUsedSize ] , iBufferLeftSize , " %y%m%d%H%M%S " , & tTime ) ;
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
iBufferUsedSize + = iCurUsedSize ;
iBufferLeftSize - = iCurUsedSize ;
2013-12-12 14:21:12 -08:00
}
2014-01-26 00:40:22 +02:00
if ( iBufferLeft > 0 ) {
2014-01-26 15:04:14 +02:00
iCurUsed = WelsSnprintf ( & strStreamFileName [ iBufferUsed ] , iBufferLeft , " .%03.3u.264 " ,
WelsGetMillisecond ( & tTime ) ) ;
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
if ( iCurUsed > 0 ) {
iBufferUsed + = iCurUsed ;
iBufferLeft - = iCurUsed ;
}
2013-12-12 14:21:12 -08:00
}
2014-01-26 00:40:22 +02:00
if ( iBufferLeftSize > 0 ) {
2014-01-26 15:04:14 +02:00
iCurUsedSize = WelsSnprintf ( & strLenFileName [ iBufferUsedSize ] , iBufferLeftSize , " .%03.3u.len " ,
WelsGetMillisecond ( & tTime ) ) ;
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 11:35:19 +02:00
if ( iCurUsedSize > 0 ) {
iBufferUsedSize + = iCurUsedSize ;
iBufferLeftSize - = iCurUsedSize ;
}
2013-12-12 14:21:12 -08:00
}
2014-01-26 13:56:43 +02:00
m_pFileBs = WelsFopen ( strStreamFileName , " wb " ) ;
m_pFileBsSize = WelsFopen ( strLenFileName , " wb " ) ;
2013-12-12 14:21:12 -08:00
2014-02-08 23:39:27 +02:00
m_bSwitch = false ;
2013-12-12 14:21:12 -08:00
m_iSwitchTimes = 0 ;
# endif //OUTPUT_BIT_STREAM
InitEncoder ( ) ;
2014-01-21 11:16:48 +08:00
XMMREG_PROTECT_INIT ( CWelsH264SVCEncoder ) ;
2013-12-12 14:21:12 -08:00
}
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 ) {
2014-01-26 16:04:52 +02:00
WelsFclose ( m_pFileBs ) ;
2013-12-12 14:21:12 -08:00
m_pFileBs = NULL ;
}
if ( m_pFileBsSize ) {
2014-01-26 16:04:52 +02:00
WelsFclose ( m_pFileBsSize ) ;
2013-12-12 14:21:12 -08:00
m_pFileBsSize = NULL ;
}
2014-02-08 23:39:27 +02:00
m_bSwitch = false ;
2013-12-12 14:21:12 -08:00
m_iSwitchTimes = 0 ;
# endif //OUTPUT_BIT_STREAM
Uninitialize ( ) ;
2014-01-21 11:16:48 +08:00
XMMREG_PROTECT_UNINIT ( CWelsH264SVCEncoder ) ;
2013-12-12 14:21:12 -08:00
}
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 ) {
2014-03-10 15:22:40 +08:00
m_pWelsTrace - > SetTraceLevel ( WELS_LOG_ERROR ) ;
2013-12-12 14:21:12 -08:00
WelsSetLogCallback ( welsCodecTrace : : CODEC_TRACE ) ;
}
}
// initialization
2014-03-10 15:22:40 +08:00
WelsSetLogLevel ( WELS_LOG_ERROR ) ; // no output, WELS_LOG_QUIET
2013-12-12 14:21:12 -08:00
}
/* Interfaces override from ISVCEncoder */
2014-02-26 22:08:41 +02:00
int CWelsH264SVCEncoder : : GetDefaultParams ( SEncParamExt * argv ) {
SWelsSvcCodingParam : : FillDefault ( * argv , true ) ;
return cmResultSuccess ;
}
2013-12-12 14:21:12 -08:00
/*
* SVC Encoder Initialization
*/
2014-02-18 12:29:43 +02:00
int CWelsH264SVCEncoder : : Initialize ( const SEncParamBase * argv ) {
2014-02-18 09:32:05 +08:00
2014-02-18 12:29:43 +02:00
if ( NULL = = argv ) {
WelsLog ( m_pEncContext , WELS_LOG_ERROR , " CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p \n " ,
argv ) ;
2013-12-12 14:21:12 -08:00
return cmInitParaError ;
}
SWelsSvcCodingParam sConfig ( true ) ;
2014-02-18 12:29:43 +02:00
// 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 ;
}
return Initialize2 ( & sConfig ) ;
}
int CWelsH264SVCEncoder : : InitializeExt ( const SEncParamExt * argv ) {
if ( NULL = = argv ) {
WelsLog ( m_pEncContext , WELS_LOG_ERROR , " CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p \n " ,
argv ) ;
return cmInitParaError ;
2014-02-18 09:32:05 +08:00
}
2014-02-18 12:29:43 +02:00
SWelsSvcCodingParam sConfig ( true ) ;
// Convert SEncParamExt into WelsSVCParamConfig here..
if ( sConfig . ParamTranscode ( * argv ) ) {
WelsLog ( m_pEncContext , WELS_LOG_ERROR , " CWelsH264SVCEncoder::Initialize(), parameter_translation failed. \n " ) ;
Uninitialize ( ) ;
return cmInitParaError ;
2014-02-18 09:32:05 +08:00
}
2014-02-18 11:31:55 +02:00
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 ( ) ;
}
2013-12-12 14:21:12 -08:00
# ifdef REC_FRAME_COUNT
2014-02-18 11:31:55 +02:00
SWelsSvcCodingParam & sEncodingParam = * pCfg ;
2013-12-12 14:21:12 -08:00
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 ,
2014-02-18 09:32:05 +08:00
" 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 " ,
2013-12-12 14:21:12 -08:00
sEncodingParam . iPicWidth ,
sEncodingParam . iPicHeight ,
sEncodingParam . iTargetBitrate ,
sEncodingParam . iRCMode ,
sEncodingParam . iTemporalLayerNum ,
sEncodingParam . iSpatialLayerNum ,
2014-02-18 11:30:26 +02:00
sEncodingParam . fMaxFrameRate ,
2013-12-12 14:21:12 -08:00
sEncodingParam . iInputCsp ,
2014-02-18 11:30:26 +02:00
sEncodingParam . uiIntraPeriod ,
2013-12-12 14:21:12 -08:00
sEncodingParam . bEnableSpsPpsIdAddition ,
sEncodingParam . bPrefixNalAddingCtrl ,
sEncodingParam . bEnableDenoise ,
sEncodingParam . bEnableBackgroundDetection ,
sEncodingParam . bEnableAdaptiveQuant ,
2014-01-17 12:29:03 +02:00
sEncodingParam . bEnableFrameSkip ,
2013-12-12 14:21:12 -08:00
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 ,
2014-02-24 11:06:09 +08:00
" coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.uiSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d; \n " ,
2013-12-12 14:21:12 -08:00
i , spatial_cfg - > iVideoWidth ,
spatial_cfg - > iVideoHeight ,
spatial_cfg - > fFrameRate ,
spatial_cfg - > iSpatialBitrate ,
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
2014-02-18 09:32:05 +08:00
const int32_t iNumOfLayers = pCfg - > iSpatialLayerNum ;
2013-12-12 14:21:12 -08:00
if ( iNumOfLayers < 1 | | iNumOfLayers > MAX_DEPENDENCY_LAYER ) {
WelsLog ( m_pEncContext , WELS_LOG_ERROR ,
2014-02-18 09:32:05 +08:00
" CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d]. \n " , iNumOfLayers ,
2013-12-12 14:21:12 -08:00
MAX_DEPENDENCY_LAYER ) ;
Uninitialize ( ) ;
return cmInitParaError ;
}
2014-02-18 09:32:05 +08:00
if ( pCfg - > iTemporalLayerNum < 1 )
pCfg - > iTemporalLayerNum = 1 ;
if ( pCfg - > iTemporalLayerNum > MAX_TEMPORAL_LEVEL ) {
2013-12-12 14:21:12 -08:00
WelsLog ( m_pEncContext , WELS_LOG_ERROR ,
2014-02-18 09:32:05 +08:00
" CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d]. \n " ,
pCfg - > iTemporalLayerNum , MAX_TEMPORAL_LEVEL ) ;
2013-12-12 14:21:12 -08:00
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 ) ;
2014-02-18 09:32:05 +08:00
if ( pCfg - > iLtrMarkPeriod = = 0 ) {
pCfg - > iLtrMarkPeriod = 30 ;
2013-12-12 14:21:12 -08:00
}
const int32_t kiDecStages = WELS_LOG2 ( pCfg - > uiGopSize ) ;
pCfg - > iInputCsp = iColorspace ;
2014-02-18 09:32:05 +08:00
pCfg - > iTemporalLayerNum = ( int8_t ) ( 1 + kiDecStages ) ;
2013-12-12 14:21:12 -08:00
pCfg - > iLoopFilterAlphaC0Offset = WELS_CLIP3 ( pCfg - > iLoopFilterAlphaC0Offset , - 6 , 6 ) ;
pCfg - > iLoopFilterBetaOffset = WELS_CLIP3 ( pCfg - > iLoopFilterBetaOffset , - 6 , 6 ) ;
2014-02-18 09:32:05 +08:00
// m_pSrcPicList = (SSourcePicture **)WelsMalloc( pCfg->iSpatialLayerNum * sizeof(SSourcePicture *), "m_pSrcPicList" );
2013-12-12 14:21:12 -08:00
// 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
2014-02-18 09:32:05 +08:00
m_iMaxPicWidth = pCfg - > iPicWidth ;
m_iMaxPicHeight = pCfg - > iPicHeight ;
2013-12-12 14:21:12 -08:00
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 ;
}
2014-02-28 14:31:17 +08:00
if ( InitPic ( m_pSrcPicList [ i ] , iColorspace , m_iMaxPicWidth , m_iMaxPicHeight ) )
{
WelsLog ( m_pEncContext , WELS_LOG_ERROR ,
" CWelsH264SVCEncoder::Initialize(), InitPic Failed iColorspace= 0x%x \n " , iColorspace ) ;
Uninitialize ( ) ;
return cmInitParaError ;
}
}
2013-12-12 14:21:12 -08:00
if ( WelsInitEncoderExt ( & m_pEncContext , pCfg ) ) {
WelsLog ( m_pEncContext , WELS_LOG_ERROR , " CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed. \n " ) ;
Uninitialize ( ) ;
return cmInitParaError ;
}
m_iCspInternal = iColorspace ;
2014-02-08 23:39:27 +02:00
m_bInitialFlag = true ;
2013-12-12 14:21:12 -08:00
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 ;
}
2014-02-08 23:39:27 +02:00
m_bInitialFlag = false ;
2013-12-12 14:21:12 -08:00
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
*/
2014-02-20 10:33:07 +08:00
int CWelsH264SVCEncoder : : EncodeFrame ( const SSourcePicture * kpSrcPic , SFrameBSInfo * pBsInfo ) {
if ( ! ( kpSrcPic & & m_pEncContext & & m_bInitialFlag ) ) {
2013-12-12 14:21:12 -08:00
return videoFrameTypeInvalid ;
}
int32_t uiFrameType = videoFrameTypeInvalid ;
2014-02-28 13:06:49 +08:00
uiFrameType = EncodeFrameInternal ( kpSrcPic , pBsInfo ) ;
2013-12-12 14:21:12 -08:00
# 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 ) ;
2014-01-05 14:35:37 +02:00
# endif //REC_FRAME_COUNT
2013-12-12 14:21:12 -08:00
# ifdef DUMP_SRC_PICTURE
DumpSrcPicture ( pSrc ) ;
2014-01-05 14:35:37 +02:00
# endif // DUMP_SRC_PICTURE
2013-12-12 14:21:12 -08:00
return uiFrameType ;
}
2014-02-28 13:06:49 +08:00
int CWelsH264SVCEncoder : : EncodeFrameInternal ( const SSourcePicture * pSrcPic , SFrameBSInfo * pBsInfo ) {
if ( ! ( pSrcPic & & m_pEncContext & & m_bInitialFlag ) ) {
2013-12-12 14:21:12 -08:00
return videoFrameTypeInvalid ;
}
int32_t iFrameTypeReturned = 0 ;
int32_t iFrameType = videoFrameTypeInvalid ;
2014-02-20 14:50:04 +08:00
XMMREG_PROTECT_STORE ( CWelsH264SVCEncoder ) ;
2014-02-28 15:13:38 +08:00
const int32_t kiEncoderReturn = WelsEncoderEncodeExt ( m_pEncContext , pBsInfo , pSrcPic ) ;
2014-02-20 14:50:04 +08:00
XMMREG_PROTECT_LOAD ( CWelsH264SVCEncoder ) ;
2013-12-12 14:21:12 -08:00
2014-02-20 14:50:04 +08:00
switch ( kiEncoderReturn ) {
case ENC_RETURN_MEMALLOCERR :
WelsUninitEncoderExt ( & m_pEncContext ) ;
return videoFrameTypeInvalid ;
case ENC_RETURN_SUCCESS :
case ENC_RETURN_CORRECTED :
break ; //continue processing
case ENC_RETURN_UNSUPPORTED_PARA :
case ENC_RETURN_UNEXPECTED :
return videoFrameTypeInvalid ;
default :
WelsLog ( m_pEncContext , WELS_LOG_ERROR , " unexpected return(%d) from WelsEncoderEncodeExt()! \n " , kiEncoderReturn ) ;
2013-12-12 14:21:12 -08:00
return videoFrameTypeInvalid ;
}
2014-02-20 14:50:04 +08:00
iFrameTypeReturned = pBsInfo - > eOutputFrameType ;
2013-12-12 14:21:12 -08:00
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 ) {
2014-01-26 16:04:52 +02:00
WelsFclose ( m_pFileBs ) ;
2013-12-12 14:21:12 -08:00
m_pFileBs = NULL ;
}
if ( m_pFileBsSize ) {
2014-01-26 16:04:52 +02:00
WelsFclose ( m_pFileBsSize ) ;
2013-12-12 14:21:12 -08:00
m_pFileBsSize = NULL ;
}
2014-02-08 23:28:42 +02:00
char strStreamFileName [ 128 ] = { 0 } ;
2014-01-26 14:43:30 +02:00
int32_t iLen = WelsSnprintf ( strStreamFileName , 128 , " adj%d_w%d.264 " , m_iSwitchTimes ,
2014-02-18 09:32:05 +08:00
m_pEncContext - > pSvcParam - > iPicWidth ) ;
2014-01-26 13:56:43 +02:00
m_pFileBs = WelsFopen ( strStreamFileName , " wb " ) ;
2014-01-26 14:43:30 +02:00
WelsSnprintf ( strStreamFileName , 128 , " adj%d_w%d_size.iLen " , m_iSwitchTimes ,
2014-02-18 09:32:05 +08:00
m_pEncContext - > pSvcParam - > iPicWidth ) ;
2014-01-26 13:56:43 +02:00
m_pFileBsSize = WelsFopen ( strStreamFileName , " wb " ) ;
2013-12-12 14:21:12 -08:00
2014-02-08 23:39:27 +02:00
m_bSwitch = false ;
2013-12-12 14:21:12 -08:00
}
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 )
2014-01-26 16:04:52 +02:00
WelsFwrite ( pLayer - > pBsBuf , 1 , iCurLayerBits , m_pFileBs ) ;
2013-12-12 14:21:12 -08:00
}
if ( m_pFileBsSize ! = NULL )
2014-01-26 16:04:52 +02:00
WelsFwrite ( & total_bits , sizeof ( int32_t ) , 1 , m_pFileBsSize ) ;
2013-12-12 14:21:12 -08:00
}
# endif //OUTPUT_BIT_STREAM
# ifdef DUMP_SRC_PICTURE
DumpSrcPicture ( pSrcPicList [ 0 ] - > pData [ 0 ] ) ;
2014-01-05 14:35:37 +02:00
# endif // DUMP_SRC_PICTURE
2013-12-12 14:21:12 -08:00
return iFrameType ;
}
2014-01-10 20:46:05 +02:00
int CWelsH264SVCEncoder : : EncodeParameterSets ( SFrameBSInfo * pBsInfo ) {
return WelsEncoderEncodeParameterSets ( m_pEncContext , pBsInfo ) ;
}
2013-12-12 14:21:12 -08:00
/*
* return : 0 - success ; otherwise - failed ;
*/
2014-02-20 10:33:07 +08:00
int CWelsH264SVCEncoder : : PauseFrame ( const SSourcePicture * kpSrcPic , SFrameBSInfo * pBsInfo ) {
2013-12-12 14:21:12 -08:00
int32_t iReturn = 1 ;
ForceIntraFrame ( true ) ;
2014-02-28 13:06:49 +08:00
if ( EncodeFrameInternal ( kpSrcPic , pBsInfo ) ! = videoFrameTypeInvalid ) {
2014-02-20 10:33:07 +08:00
iReturn = 0 ;
2013-12-12 14:21:12 -08:00
}
2014-02-28 13:06:49 +08:00
2013-12-12 14:21:12 -08:00
// 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 ;
}
2014-02-08 23:39:27 +02:00
if ( NULL = = m_pEncContext | | false = = m_bInitialFlag ) {
2013-12-12 14:21:12 -08:00
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 ;
}
2014-02-28 14:31:17 +08:00
if ( InitPic ( m_pSrcPicList [ iPicIdx ] , iColorspace , m_iMaxPicWidth , m_iMaxPicHeight ) )
{
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
" CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_DATAFORMAT, iColorspace= 0x%x \n " ,
iColorspace ) ;
return cmInitParaError ;
}
2013-12-12 14:21:12 -08:00
}
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 ;
2014-02-18 09:32:05 +08:00
case ENCODER_OPTION_SVC_ENCODE_PARAM_EXT : { // SVC Encoding Parameter
SEncParamExt sEncodingParam ;
2013-12-12 14:21:12 -08:00
SWelsSvcCodingParam sConfig ( true ) ;
int32_t iInputColorspace = 0 ;
int32_t iTargetWidth = 0 ;
int32_t iTargetHeight = 0 ;
2014-03-03 10:46:32 +08:00
memcpy ( & sEncodingParam , pOption , sizeof ( SEncParamExt ) ) ; // confirmed_safe_unsafe_usage
2014-02-18 09:32:05 +08:00
WelsLog ( m_pEncContext , WELS_LOG_INFO , " ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, sEncodingParam.iInputCsp= 0x%x \n " ,
2013-12-12 14:21:12 -08:00
sEncodingParam . iInputCsp ) ;
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
2014-02-24 10:40:17 +08:00
" 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->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d; \n " ,
2013-12-12 14:21:12 -08:00
sEncodingParam . iPicWidth ,
sEncodingParam . iPicHeight ,
sEncodingParam . iTargetBitrate ,
sEncodingParam . iRCMode ,
sEncodingParam . iPaddingFlag ,
sEncodingParam . iTemporalLayerNum ,
sEncodingParam . iSpatialLayerNum ,
2014-02-18 09:32:05 +08:00
sEncodingParam . fMaxFrameRate ,
2013-12-12 14:21:12 -08:00
sEncodingParam . iInputCsp ,
2014-02-18 09:32:05 +08:00
sEncodingParam . uiIntraPeriod ,
2013-12-12 14:21:12 -08:00
sEncodingParam . bEnableSpsPpsIdAddition ,
sEncodingParam . bPrefixNalAddingCtrl ,
sEncodingParam . bEnableDenoise ,
sEncodingParam . bEnableBackgroundDetection ,
sEncodingParam . bEnableAdaptiveQuant ,
2014-01-17 12:29:03 +02:00
sEncodingParam . bEnableFrameSkip ,
2013-12-12 14:21:12 -08:00
sEncodingParam . bEnableLongTermReference ,
sEncodingParam . iLtrMarkPeriod ) ;
int32_t i = 0 ;
while ( i < sEncodingParam . iSpatialLayerNum ) {
SSpatialLayerConfig * pSpatialCfg = & sEncodingParam . sSpatialLayers [ i ] ;
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
2014-02-24 11:06:09 +08:00
" coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.iSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d; \n " ,
2013-12-12 14:21:12 -08:00
i , pSpatialCfg - > iVideoWidth ,
pSpatialCfg - > iVideoHeight ,
pSpatialCfg - > fFrameRate ,
pSpatialCfg - > iSpatialBitrate ,
pSpatialCfg - > sSliceCfg . uiSliceMode ,
pSpatialCfg - > sSliceCfg . sSliceArgument . uiSliceNum ,
pSpatialCfg - > sSliceCfg . sSliceArgument . uiSliceSizeConstraint
) ;
+ + i ;
}
# ifdef OUTPUT_BIT_STREAM
if ( sEncodingParam . sSpatialLayers [ sEncodingParam . iSpatialLayerNum - 1 ] . iVideoWidth ! =
2014-02-18 09:32:05 +08:00
m_pEncContext - > pSvcParam - > sDependencyLayers [ m_pEncContext - > pSvcParam - > iSpatialLayerNum - 1 ] . iFrameWidth ) {
2013-12-12 14:21:12 -08:00
+ + m_iSwitchTimes ;
2014-02-08 23:39:27 +02:00
m_bSwitch = true ;
2013-12-12 14:21:12 -08:00
}
# endif //OUTPUT_BIT_STREAM
if ( sEncodingParam . iSpatialLayerNum < 1
| | sEncodingParam . iSpatialLayerNum > MAX_SPATIAL_LAYER_NUM ) { // verify number of spatial layer
return cmInitParaError ;
}
iInputColorspace = sEncodingParam . iInputCsp ;
2014-02-18 12:03:23 +02:00
if ( sConfig . ParamTranscode ( sEncodingParam ) ) {
2013-12-12 14:21:12 -08:00
return cmInitParaError ;
}
2014-02-18 09:32:05 +08:00
if ( sConfig . iSpatialLayerNum < 1 ) {
2013-12-12 14:21:12 -08:00
return cmInitParaError ;
}
2014-02-18 09:32:05 +08:00
iTargetWidth = sConfig . iPicWidth ;
iTargetHeight = sConfig . iPicHeight ;
2013-12-12 14:21:12 -08:00
if ( m_pSrcPicList [ 0 ] = = NULL ) {
return cmInitParaError ;
}
if ( m_iCspInternal ! = iInputColorspace | | m_iMaxPicWidth ! = iTargetWidth
| | m_iMaxPicHeight ! = iTargetHeight ) { // for color space due to changed
2014-02-28 14:31:17 +08:00
if ( InitPic ( m_pSrcPicList [ 0 ] , iInputColorspace , iTargetWidth , iTargetHeight ) )
{
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
" CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iInputColorspace= 0x%x \n " ,
iInputColorspace ) ;
return cmInitParaError ;
}
2013-12-12 14:21:12 -08:00
m_iMaxPicWidth = iTargetWidth ;
m_iMaxPicHeight = iTargetHeight ;
m_iCspInternal = iInputColorspace ;
}
# ifdef REC_FRAME_COUNT
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
2014-02-18 09:32:05 +08:00
" CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x \n " ,
2013-12-12 14:21:12 -08:00
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 ,
2014-01-28 12:28:41 +02:00
" CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_FRAME_RATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %f \n " ,
2013-12-12 14:21:12 -08:00
m_uiCountFrameNum , m_iCspInternal , iValue ) ;
# endif //REC_FRAME_COUNT
2014-01-09 09:20:35 +08:00
if ( iValue < = 0 ) {
return cmInitParaError ;
}
//adjust to valid range
2014-02-20 14:50:04 +08:00
m_pEncContext - > pSvcParam - > fMaxFrameRate = WELS_CLIP3 ( iValue , MIN_FRAME_RATE , MAX_FRAME_RATE ) ;
2014-01-09 09:20:35 +08:00
WelsEncoderApplyFrameRate ( m_pEncContext - > pSvcParam ) ;
2013-12-12 14:21:12 -08:00
}
break ;
2013-12-23 11:01:35 +08:00
case ENCODER_OPTION_BITRATE : { // Target bit-rate
2013-12-12 14:21:12 -08:00
int32_t iValue = * ( ( int32_t * ) pOption ) ;
# ifdef REC_FRAME_COUNT
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
2014-01-09 09:20:35 +08:00
" CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d \n " ,
m_uiCountFrameNum , m_iCspInternal , iValue ) ;
2013-12-12 14:21:12 -08:00
# endif //REC_FRAME_COUNT
2014-01-09 09:20:35 +08:00
if ( iValue < = 0 ) {
return cmInitParaError ;
}
//adjust to valid range
m_pEncContext - > pSvcParam - > iTargetBitrate = WELS_CLIP3 ( iValue , MIN_BIT_RATE , MAX_BIT_RATE ) ;
WelsEncoderApplyBitRate ( m_pEncContext - > pSvcParam ) ;
2013-12-12 14:21:12 -08:00
}
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 ) ) ;
2014-02-18 09:32:05 +08:00
m_pEncContext - > pSvcParam - > iLtrMarkPeriod = iValue ;
2013-12-12 14:21:12 -08:00
}
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 : {
2014-02-08 23:24:33 +02:00
bool iValue = * ( ( bool * ) pOption ) ;
2013-12-12 14:21:12 -08:00
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 : {
2014-02-08 23:24:33 +02:00
bool iValue = * ( ( bool * ) pOption ) ;
2013-12-12 14:21:12 -08:00
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 : {
2014-02-08 23:24:33 +02:00
bool iValue = * ( ( bool * ) pOption ) ;
2013-12-12 14:21:12 -08:00
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 ) {
2014-02-08 23:28:42 +02:00
char * path = static_cast < char * > ( pOption ) ;
2013-12-12 14:21:12 -08:00
m_pEncContext - > pSvcParam - > pCurPath = path ;
}
}
break ;
2014-03-07 10:23:25 +08:00
case ENCODER_OPTION_DUMP_FILE : {
# ifdef ENABLE_FRAME_DUMP
2014-03-07 16:29:12 +08:00
if ( m_pEncContext - > pSvcParam ! = NULL ) {
SDumpLayer * pDump = ( static_cast < SDumpLayer * > ( pOption ) ) ;
WelsStrncpy ( m_pEncContext - > pSvcParam - > sDependencyLayers [ pDump - > iLayer ] . sRecFileName , pDump - > pFileName , sizeof ( m_pEncContext - > pSvcParam - > sDependencyLayers [ pDump - > iLayer ] . sRecFileName ) )
}
2014-03-07 10:23:25 +08:00
# endif
2014-03-07 16:29:12 +08:00
}
2014-03-07 10:23:25 +08:00
break ;
2014-03-10 15:22:40 +08:00
case ENCODER_OPTION_TRACE_LEVEL : {
if ( m_pWelsTrace ) {
uint32_t level = * ( ( uint32_t * ) pOption ) ;
m_pWelsTrace - > SetTraceLevel ( level ) ;
}
}
break ;
2013-12-12 14:21:12 -08:00
default :
return cmInitParaError ;
}
return 0 ;
}
int CWelsH264SVCEncoder : : GetOption ( ENCODER_OPTION eOptionId , void * pOption ) {
if ( NULL = = pOption ) {
return cmInitParaError ;
}
2014-02-08 23:39:27 +02:00
if ( NULL = = m_pEncContext | | false = = m_bInitialFlag ) {
2013-12-12 14:21:12 -08:00
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 ;
2014-02-18 09:32:05 +08:00
case ENCODER_OPTION_SVC_ENCODE_PARAM_EXT : { // SVC Encoding Parameter
# ifdef REC_FRAME_COUNT
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
" CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x \n " ,
m_uiCountFrameNum , m_iCspInternal ) ;
# endif //REC_FRAME_COUNT
memcpy ( pOption , m_pEncContext - > pSvcParam , sizeof ( SEncParamExt ) ) ; // confirmed_safe_unsafe_usage
}
break ;
case ENCODER_OPTION_SVC_ENCODE_PARAM_BASE : { // SVC Encoding Parameter
2013-12-12 14:21:12 -08:00
# ifdef REC_FRAME_COUNT
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
2014-02-18 09:32:05 +08:00
" CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_BASE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x \n " ,
2013-12-12 14:21:12 -08:00
m_uiCountFrameNum , m_iCspInternal ) ;
# endif //REC_FRAME_COUNT
2014-02-18 12:08:27 +02:00
m_pEncContext - > pSvcParam - > GetBaseParams ( ( SEncParamBase * ) pOption ) ;
2013-12-12 14:21:12 -08:00
}
break ;
2014-02-18 09:32:05 +08:00
2013-12-12 14:21:12 -08:00
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 ;
2013-12-23 11:01:35 +08:00
case ENCODER_OPTION_BITRATE : { // Target bit-rate
2013-12-12 14:21:12 -08:00
# ifdef REC_FRAME_COUNT
WelsLog ( m_pEncContext , WELS_LOG_INFO ,
2013-12-23 11:01:35 +08:00
" CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x \n " ,
2013-12-12 14:21:12 -08:00
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 ;
2014-02-08 23:28:42 +02:00
char strFileName [ 256 ] = { 0 } ;
2013-12-12 14:21:12 -08:00
const int32_t iDataLength = m_iMaxPicWidth * m_iMaxPicHeight ;
2014-01-28 12:12:42 +02:00
WelsStrncpy ( strFileName , 256 , " pic_in_ " ) ; // confirmed_safe_unsafe_usage
2013-12-12 14:21:12 -08:00
if ( m_iMaxPicWidth = = 640 ) {
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " 360p. " ) ; // confirmed_safe_unsafe_usage
2013-12-12 14:21:12 -08:00
} else if ( m_iMaxPicWidth = = 320 ) {
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " 180p. " ) ; // confirmed_safe_unsafe_usage
2013-12-12 14:21:12 -08:00
} else if ( m_iMaxPicWidth = = 160 ) {
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " 90p. " ) ; // confirmed_safe_unsafe_usage
2013-12-12 14:21:12 -08:00
}
switch ( m_iCspInternal ) {
case videoFormatI420 :
case videoFormatYV12 :
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " yuv " ) ; // confirmed_safe_unsafe_usage
2014-01-26 13:56:43 +02:00
pFile = WelsFopen ( strFileName , " ab+ " ) ;
2013-12-12 14:21:12 -08:00
// 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 :
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " rgb " ) ; // confirmed_safe_unsafe_usage
2014-01-26 13:56:43 +02:00
pFile = WelsFopen ( strFileName , " ab+ " ) ;
2013-12-12 14:21:12 -08:00
if ( NULL ! = pFile ) {
fwrite ( pSrc , sizeof ( uint8_t ) , iDataLength * 3 , pFile ) ;
fflush ( pFile ) ;
fclose ( pFile ) ;
}
case videoFormatBGR :
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " bgr " ) ; // confirmed_safe_unsafe_usage
2014-01-26 13:56:43 +02:00
pFile = WelsFopen ( strFileName , " ab+ " ) ;
2013-12-12 14:21:12 -08:00
// 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 :
2014-01-28 12:24:20 +02:00
WelsStrcat ( strFileName , 256 , " yuy2 " ) ; // confirmed_safe_unsafe_usage
2014-01-26 13:56:43 +02:00
pFile = WelsFopen ( strFileName , " ab+ " ) ;
2013-12-12 14:21:12 -08:00
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 ) {
if ( ( * ppEncoder = new CWelsH264SVCEncoder ( ) ) ! = NULL ) {
return 0 ;
}
return 1 ;
}
void DestroySVCEncoder ( ISVCEncoder * pEncoder ) {
CWelsH264SVCEncoder * pSVCEncoder = ( CWelsH264SVCEncoder * ) pEncoder ;
if ( pSVCEncoder ) {
delete pSVCEncoder ;
pSVCEncoder = NULL ;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////