• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  2013, Cisco Systems
4  *     All rights reserved.
5  *
6  *     Redistribution and use in source and binary forms, with or without
7  *     modification, are permitted provided that the following conditions
8  *     are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *
13  *        * Redistributions in binary form must reproduce the above copyright
14  *          notice, this list of conditions and the following disclaimer in
15  *          the documentation and/or other materials provided with the
16  *          distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *     POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 #include <assert.h>
34 #include "welsEncoderExt.h"
35 #include "welsCodecTrace.h"
36 #include "typedefs.h"
37 #include "wels_const.h"
38 #include "utils.h"
39 #include "macros.h"
40 #include "version.h"
41 #include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
42 #include "ref_list_mgr_svc.h"
43 #include "codec_ver.h"
44 
45 #include <time.h>
46 #include <measure_time.h>
47 #if defined(_WIN32) /*&& defined(_DEBUG)*/
48 
49 #include <windows.h>
50 #include <stdio.h>
51 #include <stdarg.h>
52 #include <sys/types.h>
53 #else
54 #include <sys/time.h>
55 #endif
56 
57 namespace WelsEnc {
58 
59 /*
60  *  CWelsH264SVCEncoder class implementation
61  */
CWelsH264SVCEncoder()62 CWelsH264SVCEncoder::CWelsH264SVCEncoder()
63   : m_pEncContext (NULL),
64     m_pWelsTrace (NULL),
65     m_iMaxPicWidth (0),
66     m_iMaxPicHeight (0),
67     m_iCspInternal (0),
68     m_bInitialFlag (false) {
69 #ifdef REC_FRAME_COUNT
70   int32_t m_uiCountFrameNum = 0;
71 #endif//REC_FRAME_COUNT
72 
73 #ifdef OUTPUT_BIT_STREAM
74   char strStreamFileName[1024] = { 0 };  //for .264
75   int32_t iBufferUsed = 0;
76   int32_t iBufferLeft = 1023;
77   int32_t iCurUsed;
78 
79   char strLenFileName[1024] = { 0 }; //for .len
80   int32_t iBufferUsedSize = 0;
81   int32_t iBufferLeftSize = 1023;
82   int32_t iCurUsedSize;
83 #endif//OUTPUT_BIT_STREAM
84 
85 #ifdef OUTPUT_BIT_STREAM
86   SWelsTime tTime;
87 
88   WelsGetTimeOfDay (&tTime);
89 
90   iCurUsed      = WelsSnprintf (strStreamFileName, iBufferLeft, "enc_bs_0x%p_", (void*)this);
91   iCurUsedSize  = WelsSnprintf (strLenFileName, iBufferLeftSize, "enc_size_0x%p_", (void*)this);
92 
93 
94   iBufferUsed += iCurUsed;
95   iBufferLeft -= iCurUsed;
96   if (iBufferLeft > 0) {
97     iCurUsed = WelsStrftime (&strStreamFileName[iBufferUsed], iBufferLeft, "%y%m%d%H%M%S", &tTime);
98     iBufferUsed += iCurUsed;
99     iBufferLeft -= iCurUsed;
100   }
101 
102   iBufferUsedSize += iCurUsedSize;
103   iBufferLeftSize -= iCurUsedSize;
104   if (iBufferLeftSize > 0) {
105     iCurUsedSize = WelsStrftime (&strLenFileName[iBufferUsedSize], iBufferLeftSize, "%y%m%d%H%M%S", &tTime);
106     iBufferUsedSize += iCurUsedSize;
107     iBufferLeftSize -= iCurUsedSize;
108   }
109 
110   if (iBufferLeft > 0) {
111     iCurUsed = WelsSnprintf (&strStreamFileName[iBufferUsed], iBufferLeft, ".%03.3u.264",
112                              WelsGetMillisecond (&tTime));
113     iBufferUsed += iCurUsed;
114     iBufferLeft -= iCurUsed;
115   }
116 
117   if (iBufferLeftSize > 0) {
118     iCurUsedSize = WelsSnprintf (&strLenFileName[iBufferUsedSize], iBufferLeftSize, ".%03.3u.len",
119                                  WelsGetMillisecond (&tTime));
120     iBufferUsedSize += iCurUsedSize;
121     iBufferLeftSize -= iCurUsedSize;
122   }
123 
124   m_pFileBs     = WelsFopen (strStreamFileName, "wb");
125   m_pFileBsSize = WelsFopen (strLenFileName, "wb");
126 
127   m_bSwitch      = false;
128   m_iSwitchTimes = 0;
129 #endif//OUTPUT_BIT_STREAM
130 
131   InitEncoder();
132 }
133 
~CWelsH264SVCEncoder()134 CWelsH264SVCEncoder::~CWelsH264SVCEncoder() {
135   if (m_pWelsTrace) {
136     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()");
137   }
138 
139 #ifdef REC_FRAME_COUNT
140   m_uiCountFrameNum = 0;
141 #endif//REC_FRAME_COUNT
142 
143 #ifdef OUTPUT_BIT_STREAM
144   if (m_pFileBs) {
145     WelsFclose (m_pFileBs);
146     m_pFileBs = NULL;
147   }
148   if (m_pFileBsSize) {
149     WelsFclose (m_pFileBsSize);
150     m_pFileBsSize = NULL;
151   }
152   m_bSwitch = false;
153   m_iSwitchTimes = 0;
154 #endif//OUTPUT_BIT_STREAM
155 
156   Uninitialize();
157 
158   if (m_pWelsTrace) {
159     delete m_pWelsTrace;
160     m_pWelsTrace = NULL;
161   }
162 }
163 
InitEncoder(void)164 void CWelsH264SVCEncoder::InitEncoder (void) {
165 
166   m_pWelsTrace = new welsCodecTrace();
167   if (m_pWelsTrace == NULL) {
168     return;
169   }
170   m_pWelsTrace->SetCodecInstance (this);
171 }
172 
173 /* Interfaces override from ISVCEncoder */
174 
GetDefaultParams(SEncParamExt * argv)175 int CWelsH264SVCEncoder::GetDefaultParams (SEncParamExt* argv) {
176   SWelsSvcCodingParam::FillDefault (*argv);
177   return cmResultSuccess;
178 }
179 
180 /*
181  *  SVC Encoder Initialization
182  */
Initialize(const SEncParamBase * argv)183 int CWelsH264SVCEncoder::Initialize (const SEncParamBase* argv) {
184   if (m_pWelsTrace == NULL) {
185     return cmMallocMemeError;
186   }
187 
188   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::InitEncoder(), openh264 codec version = %s",
189            VERSION_NUMBER);
190 
191   if (NULL == argv) {
192     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p",
193              argv);
194     return cmInitParaError;
195   }
196 
197   SWelsSvcCodingParam sConfig;
198   // Convert SEncParamBase into WelsSVCParamConfig here..
199   if (sConfig.ParamBaseTranscode (*argv)) {
200     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
201              "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.");
202     TraceParamInfo (&sConfig);
203     Uninitialize();
204     return cmInitParaError;
205   }
206 
207   return InitializeInternal (&sConfig);
208 }
209 
InitializeExt(const SEncParamExt * argv)210 int CWelsH264SVCEncoder::InitializeExt (const SEncParamExt* argv) {
211   if (m_pWelsTrace == NULL) {
212     return cmMallocMemeError;
213   }
214 
215   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::InitEncoder(), openh264 codec version = %s",
216            VERSION_NUMBER);
217 
218   if (NULL == argv) {
219     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::InitializeExt(), invalid argv= 0x%p",
220              argv);
221     return cmInitParaError;
222   }
223 
224   SWelsSvcCodingParam sConfig;
225   // Convert SEncParamExt into WelsSVCParamConfig here..
226   if (sConfig.ParamTranscode (*argv)) {
227     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
228              "CWelsH264SVCEncoder::InitializeExt(), parameter_translation failed.");
229     TraceParamInfo (&sConfig);
230     Uninitialize();
231     return cmInitParaError;
232   }
233 
234   return InitializeInternal (&sConfig);
235 }
236 
InitializeInternal(SWelsSvcCodingParam * pCfg)237 int CWelsH264SVCEncoder::InitializeInternal (SWelsSvcCodingParam* pCfg) {
238   if (NULL == pCfg) {
239     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.",
240              pCfg);
241     return cmInitParaError;
242   }
243 
244   if (m_bInitialFlag) {
245     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
246              "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.",
247              m_bInitialFlag);
248     Uninitialize();
249   }
250   // Check valid parameters
251   const int32_t iNumOfLayers = pCfg->iSpatialLayerNum;
252   if (iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER) {
253     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
254              "CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d].", iNumOfLayers,
255              MAX_DEPENDENCY_LAYER);
256     Uninitialize();
257     return cmInitParaError;
258   }
259   if (pCfg->iTemporalLayerNum < 1)
260     pCfg->iTemporalLayerNum = 1;
261   if (pCfg->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) {
262     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
263              "CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d].",
264              pCfg->iTemporalLayerNum, MAX_TEMPORAL_LEVEL);
265     Uninitialize();
266     return cmInitParaError;
267   }
268 
269   // assert( cfg.uiGopSize >= 1 && ( cfg.uiIntraPeriod && (cfg.uiIntraPeriod % cfg.uiGopSize) == 0) );
270 
271   if (pCfg->uiGopSize < 1 || pCfg->uiGopSize > MAX_GOP_SIZE) {
272     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
273              "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d].", pCfg->uiGopSize,
274              MAX_GOP_SIZE);
275     Uninitialize();
276     return cmInitParaError;
277   }
278 
279   if (!WELS_POWER2_IF (pCfg->uiGopSize)) {
280     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
281              "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d] and yield to power of 2.",
282              pCfg->uiGopSize, MAX_GOP_SIZE);
283     Uninitialize();
284     return cmInitParaError;
285   }
286 
287   if (pCfg->uiIntraPeriod && pCfg->uiIntraPeriod < pCfg->uiGopSize) {
288     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
289              "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d.",
290              pCfg->uiIntraPeriod, pCfg->uiGopSize);
291     Uninitialize();
292     return cmInitParaError;
293   }
294 
295   if ((pCfg->uiIntraPeriod && (pCfg->uiIntraPeriod & (pCfg->uiGopSize - 1)) != 0)) {
296     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
297              "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.",
298              pCfg->uiIntraPeriod, pCfg->uiGopSize);
299     Uninitialize();
300     return cmInitParaError;
301   }
302   if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) {
303     if (pCfg->bEnableLongTermReference) {
304       pCfg->iLTRRefNum = LONG_TERM_REF_NUM_SCREEN;
305       if (pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT)
306         pCfg->iNumRefFrame = WELS_MAX (1, WELS_LOG2 (pCfg->uiGopSize)) + pCfg->iLTRRefNum;
307     } else {
308       pCfg->iLTRRefNum = 0;
309       if (pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT)
310         pCfg->iNumRefFrame = WELS_MAX (1, pCfg->uiGopSize >> 1);
311     }
312   } else {
313     pCfg->iLTRRefNum = pCfg->bEnableLongTermReference ? LONG_TERM_REF_NUM : 0;
314     if (pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT) {
315       pCfg->iNumRefFrame = ((pCfg->uiGopSize >> 1) > 1) ? ((pCfg->uiGopSize >> 1) + pCfg->iLTRRefNum) :
316                            (MIN_REF_PIC_COUNT + pCfg->iLTRRefNum);
317       pCfg->iNumRefFrame = WELS_CLIP3 (pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA);
318     }
319   }
320 
321   if (pCfg->iLtrMarkPeriod == 0) {
322     pCfg->iLtrMarkPeriod = 30;
323   }
324 
325   const int32_t kiDecStages = WELS_LOG2 (pCfg->uiGopSize);
326   pCfg->iTemporalLayerNum        = (int8_t) (1 + kiDecStages);
327   pCfg->iLoopFilterAlphaC0Offset = WELS_CLIP3 (pCfg->iLoopFilterAlphaC0Offset, -6, 6);
328   pCfg->iLoopFilterBetaOffset    = WELS_CLIP3 (pCfg->iLoopFilterBetaOffset, -6, 6);
329 
330   // decide property list size between INIT_TYPE_PARAMETER_BASED/INIT_TYPE_CONFIG_BASED
331   m_iMaxPicWidth  = pCfg->iPicWidth;
332   m_iMaxPicHeight = pCfg->iPicHeight;
333 
334   TraceParamInfo (pCfg);
335   if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx, NULL)) {
336     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.");
337     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_DEBUG,
338              "Problematic Input Base Param: iUsageType=%d, Resolution=%dx%d, FR=%f, TLayerNum=%d, DLayerNum=%d",
339              pCfg->iUsageType, pCfg->iPicWidth, pCfg->iPicHeight, pCfg->fMaxFrameRate, pCfg->iTemporalLayerNum,
340              pCfg->iSpatialLayerNum);
341     Uninitialize();
342     return cmInitParaError;
343   }
344 
345   m_bInitialFlag  = true;
346 
347   return cmResultSuccess;
348 }
349 
350 /*
351  *  SVC Encoder Uninitialization
352  */
Uninitialize()353 int32_t CWelsH264SVCEncoder::Uninitialize() {
354   if (!m_bInitialFlag) {
355     return 0;
356   }
357 
358   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize(), openh264 codec version = %s.",
359            VERSION_NUMBER);
360 
361   if (NULL != m_pEncContext) {
362     WelsUninitEncoderExt (&m_pEncContext);
363     m_pEncContext = NULL;
364   }
365 
366   m_bInitialFlag = false;
367 
368   return 0;
369 }
370 
371 
372 /*
373  *  SVC core encoding
374  */
EncodeFrame(const SSourcePicture * kpSrcPic,SFrameBSInfo * pBsInfo)375 int CWelsH264SVCEncoder::EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo) {
376   if (! (kpSrcPic && m_bInitialFlag && pBsInfo)) {
377     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::EncodeFrame(), cmInitParaError.");
378     return cmInitParaError;
379   }
380   if (kpSrcPic->iColorFormat != videoFormatI420) {
381     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::EncodeFrame(), wrong iColorFormat %d",
382              kpSrcPic->iColorFormat);
383     return cmInitParaError;
384   }
385 
386   const int32_t kiEncoderReturn = EncodeFrameInternal (kpSrcPic, pBsInfo);
387 
388   if (kiEncoderReturn != cmResultSuccess) {
389     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::EncodeFrame(), kiEncoderReturn %d",
390              kiEncoderReturn);
391     return kiEncoderReturn;
392   }
393 
394 #ifdef REC_FRAME_COUNT
395   ++ m_uiCountFrameNum;
396   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
397            "CWelsH264SVCEncoder::EncodeFrame(), m_uiCountFrameNum= %d,", m_uiCountFrameNum);
398 #endif//REC_FRAME_COUNT
399 
400   return kiEncoderReturn;
401 }
402 
403 
EncodeFrameInternal(const SSourcePicture * pSrcPic,SFrameBSInfo * pBsInfo)404 int CWelsH264SVCEncoder ::EncodeFrameInternal (const SSourcePicture*  pSrcPic, SFrameBSInfo* pBsInfo) {
405 
406   if ((pSrcPic->iPicWidth < 16) || ((pSrcPic->iPicHeight < 16))) {
407     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Don't support width(%d) or height(%d) which is less than 16!",
408              pSrcPic->iPicWidth, pSrcPic->iPicHeight);
409     return cmUnsupportedData;
410   }
411 
412   const int64_t kiBeforeFrameUs = WelsTime();
413   const int32_t kiEncoderReturn = WelsEncoderEncodeExt (m_pEncContext, pBsInfo, pSrcPic);
414   const int64_t kiCurrentFrameMs = (WelsTime() - kiBeforeFrameUs) / 1000;
415   if ((kiEncoderReturn == ENC_RETURN_MEMALLOCERR) || (kiEncoderReturn == ENC_RETURN_MEMOVERFLOWFOUND)
416       || (kiEncoderReturn == ENC_RETURN_VLCOVERFLOWFOUND)) {
417     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_DEBUG, "CWelsH264SVCEncoder::EncodeFrame() not succeed, err=%d",
418              kiEncoderReturn);
419     WelsUninitEncoderExt (&m_pEncContext);
420     return cmMallocMemeError;
421   } else if ((kiEncoderReturn != ENC_RETURN_SUCCESS) && (kiEncoderReturn == ENC_RETURN_CORRECTED)) {
422     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "unexpected return(%d) from EncodeFrameInternal()!",
423              kiEncoderReturn);
424     return cmUnknownReason;
425   }
426 
427   UpdateStatistics (pBsInfo, kiCurrentFrameMs);
428 
429   ///////////////////for test
430 #ifdef OUTPUT_BIT_STREAM
431   if (pBsInfo->eFrameType != videoFrameTypeInvalid && pBsInfo->eFrameType != videoFrameTypeSkip) {
432     SLayerBSInfo* pLayer = NULL;
433     int32_t i = 0, j = 0, iCurLayerBits = 0, total_bits = 0;
434 
435     if (m_bSwitch) {
436       if (m_pFileBs) {
437         WelsFclose (m_pFileBs);
438         m_pFileBs = NULL;
439       }
440       if (m_pFileBsSize) {
441         WelsFclose (m_pFileBsSize);
442         m_pFileBsSize = NULL;
443       }
444       char strStreamFileName[128] = {0};
445       WelsSnprintf (strStreamFileName, 128, "adj%d_w%d.264", m_iSwitchTimes,
446                     m_pEncContext->pSvcParam->iPicWidth);
447       m_pFileBs = WelsFopen (strStreamFileName, "wb");
448       WelsSnprintf (strStreamFileName, 128, "adj%d_w%d_size.iLen", m_iSwitchTimes,
449                     m_pEncContext->pSvcParam->iPicWidth);
450       m_pFileBsSize = WelsFopen (strStreamFileName, "wb");
451 
452 
453       m_bSwitch = false;
454     }
455 
456     for (i = 0; i < pBsInfo->iLayerNum; i++) {
457       pLayer = &pBsInfo->sLayerInfo[i];
458 
459       iCurLayerBits = 0;
460       for (j = 0; j < pLayer->iNalCount; j++) {
461         iCurLayerBits += pLayer->pNalLengthInByte[j];
462       }
463       total_bits += iCurLayerBits;
464       if (m_pFileBs != NULL)
465         WelsFwrite (pLayer->pBsBuf, 1, iCurLayerBits, m_pFileBs);
466     }
467 
468     if (m_pFileBsSize != NULL)
469       WelsFwrite (&total_bits, sizeof (int32_t), 1, m_pFileBsSize);
470   }
471 #endif //OUTPUT_BIT_STREAM
472 #ifdef DUMP_SRC_PICTURE
473   DumpSrcPicture (pSrcPic, m_pEncContext->pSvcParam->iUsageType);
474 #endif // DUMP_SRC_PICTURE
475 
476   return cmResultSuccess;
477 
478 }
479 
EncodeParameterSets(SFrameBSInfo * pBsInfo)480 int CWelsH264SVCEncoder::EncodeParameterSets (SFrameBSInfo* pBsInfo) {
481   return WelsEncoderEncodeParameterSets (m_pEncContext, pBsInfo);
482 }
483 
484 /*
485  *  Force key frame
486  */
ForceIntraFrame(bool bIDR,int iLayerId)487 int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR, int iLayerId) {
488   if (bIDR) {
489     if (! (m_pEncContext && m_bInitialFlag)) {
490       return 1;
491     }
492 
493     ForceCodingIDR (m_pEncContext, iLayerId);
494   } else {
495     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
496              "CWelsH264SVCEncoder::ForceIntraFrame(),nothing to do as bIDR set to false");
497   }
498 
499   return 0;
500 }
TraceParamInfo(SEncParamExt * pParam)501 void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) {
502   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
503            "iUsageType = %d,iPicWidth= %d;iPicHeight= %d;iTargetBitrate= %d;iMaxBitrate= %d;iRCMode= %d;iPaddingFlag= %d;iTemporalLayerNum= %d;iSpatialLayerNum= %d;fFrameRate= %.6ff;uiIntraPeriod= %d;"
504            "eSpsPpsIdStrategy = %d;bPrefixNalAddingCtrl = %d;bSimulcastAVC=%d;bEnableDenoise= %d;bEnableBackgroundDetection= %d;bEnableSceneChangeDetect = %d;bEnableAdaptiveQuant= %d;bEnableFrameSkip= %d;bEnableLongTermReference= %d;iLtrMarkPeriod= %d, bIsLosslessLink=%d;"
505            "iComplexityMode = %d;iNumRefFrame = %d;iEntropyCodingModeFlag = %d;uiMaxNalSize = %d;iLTRRefNum = %d;iMultipleThreadIdc = %d;iLoopFilterDisableIdc = %d (offset(alpha/beta): %d,%d;iComplexityMode = %d,iMaxQp = %d;iMinQp = %d)",
506            pParam->iUsageType,
507            pParam->iPicWidth,
508            pParam->iPicHeight,
509            pParam->iTargetBitrate,
510            pParam->iMaxBitrate,
511            pParam->iRCMode,
512            pParam->iPaddingFlag,
513            pParam->iTemporalLayerNum,
514            pParam->iSpatialLayerNum,
515            pParam->fMaxFrameRate,
516            pParam->uiIntraPeriod,
517            pParam->eSpsPpsIdStrategy,
518            pParam->bPrefixNalAddingCtrl,
519            pParam->bSimulcastAVC,
520            pParam->bEnableDenoise,
521            pParam->bEnableBackgroundDetection,
522            pParam->bEnableSceneChangeDetect,
523            pParam->bEnableAdaptiveQuant,
524            pParam->bEnableFrameSkip,
525            pParam->bEnableLongTermReference,
526            pParam->iLtrMarkPeriod,
527            pParam->bIsLosslessLink,
528            pParam->iComplexityMode,
529            pParam->iNumRefFrame,
530            pParam->iEntropyCodingModeFlag,
531            pParam->uiMaxNalSize,
532            pParam->iLTRRefNum,
533            pParam->iMultipleThreadIdc,
534            pParam->iLoopFilterDisableIdc,
535            pParam->iLoopFilterAlphaC0Offset,
536            pParam->iLoopFilterBetaOffset,
537            pParam->iComplexityMode,
538            pParam->iMaxQp,
539            pParam->iMinQp
540           );
541   int32_t i = 0;
542   int32_t iSpatialLayers = (pParam->iSpatialLayerNum < MAX_SPATIAL_LAYER_NUM) ? (pParam->iSpatialLayerNum) :
543                            MAX_SPATIAL_LAYER_NUM;
544   while (i < iSpatialLayers) {
545     SSpatialLayerConfig* pSpatialCfg = &pParam->sSpatialLayers[i];
546     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
547              "sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .iMaxSpatialBitrate= %d; .sSliceArgument.uiSliceMode= %d; .sSliceArgument.iSliceNum= %d; .sSliceArgument.uiSliceSizeConstraint= %d;"
548              "uiProfileIdc = %d;uiLevelIdc = %d;iDLayerQp = %d",
549              i, pSpatialCfg->iVideoWidth,
550              pSpatialCfg->iVideoHeight,
551              pSpatialCfg->fFrameRate,
552              pSpatialCfg->iSpatialBitrate,
553              pSpatialCfg->iMaxSpatialBitrate,
554              pSpatialCfg->sSliceArgument.uiSliceMode,
555              pSpatialCfg->sSliceArgument.uiSliceNum,
556              pSpatialCfg->sSliceArgument.uiSliceSizeConstraint,
557              pSpatialCfg->uiProfileIdc,
558              pSpatialCfg->uiLevelIdc,
559              pSpatialCfg->iDLayerQp
560             );
561     ++ i;
562   }
563 }
564 
LogStatistics(const int64_t kiCurrentFrameTs,int32_t iMaxDid)565 void CWelsH264SVCEncoder::LogStatistics (const int64_t kiCurrentFrameTs, int32_t iMaxDid) {
566   for (int32_t iDid = 0; iDid <= iMaxDid; iDid++) {
567     SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics[iDid]);
568     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
569              "EncoderStatistics: SpatialId = %d,%dx%d, SpeedInMs: %f, fAverageFrameRate=%f, "
570              "LastFrameRate=%f, LatestBitRate=%d, LastFrameQP=%d, uiInputFrameCount=%d, uiSkippedFrameCount=%d, "
571              "uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA, iTotalEncodedBytes=%lu at Ts = %" PRId64,
572              iDid, pStatistics->uiWidth, pStatistics->uiHeight,
573              pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate,
574              pStatistics->fLatestFrameRate, pStatistics->uiBitRate, pStatistics->uiAverageFrameQP,
575              pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount,
576              pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum,
577              pStatistics->iTotalEncodedBytes, kiCurrentFrameTs);
578   }
579 }
580 
UpdateStatistics(SFrameBSInfo * pBsInfo,const int64_t kiCurrentFrameMs)581 void CWelsH264SVCEncoder::UpdateStatistics (SFrameBSInfo* pBsInfo,
582     const int64_t kiCurrentFrameMs) {
583 
584   const int64_t kiCurrentFrameTs = m_pEncContext->uiLastTimestamp = pBsInfo->uiTimeStamp;
585   const int64_t kiTimeDiff = kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs;
586 
587   int32_t iMaxDid = m_pEncContext->pSvcParam->iSpatialLayerNum - 1;
588   SLayerBSInfo*  pLayerInfo = &pBsInfo->sLayerInfo[0];
589   uint32_t iMaxInputFrame = 0;
590   float iMaxFrameRate = 0;
591   for (int32_t iDid = 0; iDid <= iMaxDid; iDid++) {
592     EVideoFrameType eFrameType = videoFrameTypeSkip;
593     int32_t kiCurrentFrameSize = 0;
594     for (int32_t iLayerNum = 0; iLayerNum < pBsInfo->iLayerNum; iLayerNum++) {
595       pLayerInfo = &pBsInfo->sLayerInfo[iLayerNum];
596       if ((pLayerInfo->uiLayerType == VIDEO_CODING_LAYER) && (pLayerInfo->uiSpatialId == iDid)) {
597         eFrameType = pLayerInfo->eFrameType;
598         for (int32_t iNalIdx = 0; iNalIdx < pLayerInfo->iNalCount; iNalIdx++) {
599           kiCurrentFrameSize += pLayerInfo->pNalLengthInByte[iNalIdx];
600         }
601       }
602     }
603     SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics[iDid]);
604     SSpatialLayerInternal* pSpatialLayerInternalParam = & (m_pEncContext->pSvcParam->sDependencyLayers[iDid]);
605 
606     if ((0 != pStatistics->uiWidth && 0 != pStatistics->uiHeight)
607         && (pStatistics->uiWidth != (unsigned int) pSpatialLayerInternalParam->iActualWidth
608             || pStatistics->uiHeight != (unsigned int) pSpatialLayerInternalParam->iActualHeight)) {
609       pStatistics->uiResolutionChangeTimes ++;
610     }
611     pStatistics->uiWidth = pSpatialLayerInternalParam->iActualWidth;
612     pStatistics->uiHeight = pSpatialLayerInternalParam->iActualHeight;
613 
614     const bool kbCurrentFrameSkipped = (videoFrameTypeSkip == eFrameType);
615     pStatistics->uiInputFrameCount ++;
616     pStatistics->uiSkippedFrameCount += (kbCurrentFrameSkipped ? 1 : 0);
617     iMaxInputFrame = WELS_MAX (pStatistics->uiInputFrameCount, iMaxInputFrame);
618     int32_t iProcessedFrameCount = pStatistics->uiInputFrameCount - pStatistics->uiSkippedFrameCount;
619     if (!kbCurrentFrameSkipped && iProcessedFrameCount != 0) {
620       pStatistics->fAverageFrameSpeedInMs += (kiCurrentFrameMs - pStatistics->fAverageFrameSpeedInMs) / iProcessedFrameCount;
621     }
622     // rate control related
623     if (0 != m_pEncContext->uiStartTimestamp) {
624       if (kiCurrentFrameTs > m_pEncContext->uiStartTimestamp + 800) {
625         pStatistics->fAverageFrameRate = (static_cast<float> (pStatistics->uiInputFrameCount) * 1000 /
626                                           (kiCurrentFrameTs - m_pEncContext->uiStartTimestamp));
627       }
628     } else {
629       m_pEncContext->uiStartTimestamp = kiCurrentFrameTs;
630     }
631     iMaxFrameRate = WELS_MAX (iMaxFrameRate, pStatistics->fAverageFrameRate);
632     //pStatistics->fLatestFrameRate = m_pEncContext->pWelsSvcRc->fLatestFrameRate; //TODO: finish the calculation in RC
633     //pStatistics->uiBitRate = m_pEncContext->pWelsSvcRc->iActualBitRate; //TODO: finish the calculation in RC
634     pStatistics->uiAverageFrameQP = m_pEncContext->pWelsSvcRc[iDid].iAverageFrameQp;
635 
636     if (videoFrameTypeIDR == eFrameType || videoFrameTypeI == eFrameType) {
637       pStatistics->uiIDRSentNum ++;
638     }
639     if (m_pEncContext->pLtr->bLTRMarkingFlag) {
640       pStatistics->uiLTRSentNum ++;
641     }
642 
643     pStatistics->iTotalEncodedBytes += kiCurrentFrameSize;
644 
645     const int32_t kiDeltaFrames = static_cast<int32_t> (pStatistics->uiInputFrameCount -
646                                   pStatistics->iLastStatisticsFrameCount);
647     if (kiDeltaFrames > (m_pEncContext->pSvcParam->fMaxFrameRate * 2)) {
648       if (kiTimeDiff >= m_pEncContext->iStatisticsLogInterval) {
649         float fTimeDiffSec = kiTimeDiff / 1000.0f;
650         pStatistics->fLatestFrameRate = static_cast<float> ((pStatistics->uiInputFrameCount -
651                                         pStatistics->iLastStatisticsFrameCount) / fTimeDiffSec);
652         pStatistics->uiBitRate = static_cast<unsigned int> ((pStatistics->iTotalEncodedBytes) * 8  / fTimeDiffSec);
653 
654         if (WELS_ABS (pStatistics->fLatestFrameRate - m_pEncContext->pSvcParam->fMaxFrameRate) > 30) {
655           WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
656                    "Actual input fLatestFrameRate = %f is quite different from framerate in setting %f, please check setting or timestamp unit (ms), cur_Ts = %"
657                    PRId64 " start_Ts = %" PRId64,
658                    pStatistics->fLatestFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate, kiCurrentFrameTs,
659                    static_cast<int64_t> (m_pEncContext->iLastStatisticsLogTs));
660         }
661 
662         if (m_pEncContext->pSvcParam->iRCMode == RC_QUALITY_MODE || m_pEncContext->pSvcParam->iRCMode == RC_BITRATE_MODE) {
663           if ((pStatistics->fLatestFrameRate > 0)
664               && WELS_ABS (m_pEncContext->pSvcParam->fMaxFrameRate - pStatistics->fLatestFrameRate) > 5) {
665             WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
666                      "Actual input framerate %f is different from framerate in setting %f, suggest to use other rate control modes",
667                      pStatistics->fLatestFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate);
668           }
669         }
670         // update variables
671         pStatistics->iLastStatisticsBytes = pStatistics->iTotalEncodedBytes;
672         pStatistics->iLastStatisticsFrameCount = pStatistics->uiInputFrameCount;
673         m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs;
674         LogStatistics (kiCurrentFrameTs, iMaxDid);
675         pStatistics->iTotalEncodedBytes = 0;
676         //TODO: the following statistics will be calculated and added later
677         //pStatistics->uiLTRSentNum
678 
679       }
680     }
681   }
682 
683 }
684 
685 /************************************************************************
686 * InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,..
687 ************************************************************************/
SetOption(ENCODER_OPTION eOptionId,void * pOption)688 int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
689   if (NULL == pOption) {
690     return cmInitParaError;
691   }
692 
693   if ((NULL == m_pEncContext || false == m_bInitialFlag) && eOptionId != ENCODER_OPTION_TRACE_LEVEL
694       && eOptionId != ENCODER_OPTION_TRACE_CALLBACK && eOptionId != ENCODER_OPTION_TRACE_CALLBACK_CONTEXT) {
695     return cmInitExpected;
696   }
697 
698   switch (eOptionId) {
699   case ENCODER_OPTION_INTER_SPATIAL_PRED: { // Inter spatial layer prediction flag
700     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
701              "ENCODER_OPTION_INTER_SPATIAL_PRED, this feature not supported at present.");
702   }
703   break;
704   case ENCODER_OPTION_DATAFORMAT: { // Input color space
705     int32_t iValue = * ((int32_t*)pOption);
706     int32_t iColorspace = iValue;
707     if (iColorspace == 0) {
708       return cmInitParaError;
709     }
710 
711     m_iCspInternal = iColorspace;
712     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
713              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_DATAFORMAT, m_iCspInternal = 0x%x", m_iCspInternal);
714   }
715   break;
716   case ENCODER_OPTION_IDR_INTERVAL: { // IDR Interval
717     int32_t iValue = * ((int32_t*)pOption);
718     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
719              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_IDR_INTERVAL iValue = %d", iValue);
720     if (iValue <= -1) {
721       iValue = 0;
722     }
723     if (iValue == (int32_t)m_pEncContext->pSvcParam->uiIntraPeriod) {
724       return cmResultSuccess;
725     }
726     m_pEncContext->pSvcParam->uiIntraPeriod = (uint32_t)iValue;
727     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
728              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_IDR_INTERVAL uiIntraPeriod updated to %d",
729              m_pEncContext->pSvcParam->uiIntraPeriod);
730   }
731   break;
732   case ENCODER_OPTION_SVC_ENCODE_PARAM_BASE: { // SVC Encoding Parameter
733     SEncParamBase sEncodingParam;
734     SWelsSvcCodingParam sConfig;
735     int32_t iTargetWidth = 0;
736     int32_t iTargetHeight = 0;
737 
738     memcpy (&sEncodingParam, pOption, sizeof (SEncParamBase)); // confirmed_safe_unsafe_usage
739 #ifdef OUTPUT_BIT_STREAM
740     if ((sEncodingParam.iPicWidth  != m_pEncContext->pSvcParam->sDependencyLayers[m_pEncContext->pSvcParam->iSpatialLayerNum
741          - 1].iActualWidth) ||
742         (sEncodingParam.iPicHeight != m_pEncContext->pSvcParam->sDependencyLayers[m_pEncContext->pSvcParam->iSpatialLayerNum -
743                                                        1].iActualHeight)) {
744       ++m_iSwitchTimes;
745       m_bSwitch = true;
746     }
747 #endif//OUTPUT_BIT_STREAM
748     if (sConfig.ParamBaseTranscode (sEncodingParam)) {
749       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
750                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_BASE, ParamTranscode failed!");
751       return cmInitParaError;
752     }
753     /* New configuration available here */
754     iTargetWidth        = sConfig.iPicWidth;
755     iTargetHeight       = sConfig.iPicHeight;
756     if (m_iMaxPicWidth != iTargetWidth
757         || m_iMaxPicHeight != iTargetHeight) {
758       m_iMaxPicWidth    = iTargetWidth;
759       m_iMaxPicHeight   = iTargetHeight;
760     }
761     if (sConfig.DetermineTemporalSettings()) {
762       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
763                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_BASE, DetermineTemporalSettings failed!");
764       return cmInitParaError;
765     }
766     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
767              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_BASE iUsageType = %d,iPicWidth= %d;iPicHeight= %d;iTargetBitrate= %d;fMaxFrameRate=  %.6ff;iRCMode= %d",
768              sEncodingParam.iUsageType,
769              sEncodingParam.iPicWidth,
770              sEncodingParam.iPicHeight,
771              sEncodingParam.iTargetBitrate,
772              sEncodingParam.fMaxFrameRate,
773              sEncodingParam.iRCMode);
774     if (WelsEncoderParamAdjust (&m_pEncContext, &sConfig)) {
775       return cmInitParaError;
776     }
777 
778     //LogStatistics
779     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
780              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_BASE, LogStatisticsBeforeNewEncoding");
781     LogStatistics (m_pEncContext->iLastStatisticsLogTs, 0);
782   }
783   break;
784 
785   case ENCODER_OPTION_SVC_ENCODE_PARAM_EXT: { // SVC Encoding Parameter
786     SEncParamExt sEncodingParam;
787     SWelsSvcCodingParam sConfig;
788     int32_t iTargetWidth = 0;
789     int32_t iTargetHeight = 0;
790 
791     memcpy (&sEncodingParam, pOption, sizeof (SEncParamExt)); // confirmed_safe_unsafe_usage
792     TraceParamInfo (&sEncodingParam);
793 #ifdef OUTPUT_BIT_STREAM
794     if ((sEncodingParam.sSpatialLayers[sEncodingParam.iSpatialLayerNum - 1].iVideoWidth !=
795          m_pEncContext->pSvcParam->sDependencyLayers[m_pEncContext->pSvcParam->iSpatialLayerNum - 1].iActualWidth) ||
796         (sEncodingParam.sSpatialLayers[sEncodingParam.iSpatialLayerNum - 1].iVideoHeight !=
797          m_pEncContext->pSvcParam->sDependencyLayers[m_pEncContext->pSvcParam->iSpatialLayerNum - 1].iActualHeight)) {
798       ++ m_iSwitchTimes;
799       m_bSwitch = true;
800     }
801 #endif//OUTPUT_BIT_STREAM
802     if (sEncodingParam.iSpatialLayerNum < 1
803         || sEncodingParam.iSpatialLayerNum > MAX_SPATIAL_LAYER_NUM) { // verify number of spatial layer
804       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
805                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iSpatialLayerNum(%d) failed!",
806                sEncodingParam.iSpatialLayerNum);
807       return cmInitParaError;
808     }
809 
810     if (sConfig.ParamTranscode (sEncodingParam)) {
811       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
812                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ParamTranscode failed!");
813       return cmInitParaError;
814     }
815     if (sConfig.iSpatialLayerNum < 1) {
816       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
817                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iSpatialLayerNum(%d) failed!",
818                sConfig.iSpatialLayerNum);
819       return cmInitParaError;
820     }
821     if (sConfig.DetermineTemporalSettings()) {
822       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
823                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, DetermineTemporalSettings failed!");
824       return cmInitParaError;
825     }
826 
827     /* New configuration available here */
828     iTargetWidth        = sConfig.iPicWidth;
829     iTargetHeight       = sConfig.iPicHeight;
830     if (m_iMaxPicWidth != iTargetWidth
831         || m_iMaxPicHeight != iTargetHeight) {
832       m_iMaxPicWidth    = iTargetWidth;
833       m_iMaxPicHeight   = iTargetHeight;
834     }
835     /* Check every field whether there is new request for memory block changed or else, Oct. 24, 2008 */
836     if (WelsEncoderParamAdjust (&m_pEncContext, &sConfig)) {
837       return cmInitParaError;
838     }
839 
840     //LogStatistics
841     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
842              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, LogStatisticsBeforeNewEncoding");
843     LogStatistics (m_pEncContext->iLastStatisticsLogTs, sEncodingParam.iSpatialLayerNum - 1);
844   }
845   break;
846   case ENCODER_OPTION_FRAME_RATE: { // Maximal input frame rate
847     float iValue = * ((float*)pOption);
848     if (iValue <= 0) {
849       return cmInitParaError;
850     }
851     //adjust to valid range
852     m_pEncContext->pSvcParam->fMaxFrameRate = WELS_CLIP3 (iValue, MIN_FRAME_RATE, MAX_FRAME_RATE);
853     WelsEncoderApplyFrameRate (m_pEncContext->pSvcParam);
854     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
855              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_FRAME_RATE,m_pEncContext->pSvcParam->fMaxFrameRate= %f",
856              m_pEncContext->pSvcParam->fMaxFrameRate);
857   }
858   break;
859   case ENCODER_OPTION_BITRATE: { // Target bit-rate
860     SBitrateInfo* pInfo = (static_cast<SBitrateInfo*> (pOption));
861     int32_t iBitrate = pInfo->iBitrate;
862     if (iBitrate <= 0) {
863       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
864                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,iBitrate = %d",
865                iBitrate);
866       return cmInitParaError;
867     }
868     iBitrate = WELS_CLIP3 (iBitrate, MIN_BIT_RATE, MAX_BIT_RATE);
869     switch (pInfo->iLayer) {
870     case SPATIAL_LAYER_ALL:
871       m_pEncContext->pSvcParam->iTargetBitrate = iBitrate;
872       break;
873     case SPATIAL_LAYER_0:
874       m_pEncContext->pSvcParam->sSpatialLayers[0].iSpatialBitrate = iBitrate;
875       break;
876     case SPATIAL_LAYER_1:
877       m_pEncContext->pSvcParam->sSpatialLayers[1].iSpatialBitrate = iBitrate;
878       break;
879     case SPATIAL_LAYER_2:
880       m_pEncContext->pSvcParam->sSpatialLayers[2].iSpatialBitrate = iBitrate;
881       break;
882     case SPATIAL_LAYER_3:
883       m_pEncContext->pSvcParam->sSpatialLayers[3].iSpatialBitrate = iBitrate;
884       break;
885     default:
886       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
887                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,iLayer = %d",
888                pInfo->iLayer);
889       return cmInitParaError;
890       break;
891     }
892     //adjust to valid range
893     if (WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer)) {
894       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
895                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
896       return cmInitParaError;
897     } else {
898       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
899                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
900 
901     }
902 
903   }
904   break;
905   case ENCODER_OPTION_MAX_BITRATE: { // Target bit-rate
906     SBitrateInfo* pInfo = (static_cast<SBitrateInfo*> (pOption));
907     int32_t iBitrate = pInfo->iBitrate;
908     if (iBitrate <= 0) {
909       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
910                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_MAX_BITRATE,iBitrate = %d",
911                iBitrate);
912       return cmInitParaError;
913     }
914     iBitrate = WELS_CLIP3 (iBitrate, MIN_BIT_RATE, MAX_BIT_RATE);
915     switch (pInfo->iLayer) {
916     case SPATIAL_LAYER_ALL:
917       m_pEncContext->pSvcParam->iMaxBitrate = iBitrate;
918       break;
919     case SPATIAL_LAYER_0:
920       m_pEncContext->pSvcParam->sSpatialLayers[0].iMaxSpatialBitrate = iBitrate;
921       break;
922     case SPATIAL_LAYER_1:
923       m_pEncContext->pSvcParam->sSpatialLayers[1].iMaxSpatialBitrate = iBitrate;
924       break;
925     case SPATIAL_LAYER_2:
926       m_pEncContext->pSvcParam->sSpatialLayers[2].iMaxSpatialBitrate = iBitrate;
927       break;
928     case SPATIAL_LAYER_3:
929       m_pEncContext->pSvcParam->sSpatialLayers[3].iMaxSpatialBitrate = iBitrate;
930       break;
931     default:
932       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
933                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_MAX_BITRATE,iLayer = %d",
934                pInfo->iLayer);
935       return cmInitParaError;
936       break;
937     }
938     //adjust to valid range
939     if (WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer)) {
940       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
941                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer, iBitrate);
942       return cmInitParaError;
943     } else {
944       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
945                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer, iBitrate);
946 
947     }
948   }
949   break;
950   case ENCODER_OPTION_RC_MODE: { // 0:quality mode;1:bit-rate mode;2:bitrate limited mode
951     int32_t iValue = * ((int32_t*)pOption);
952     m_pEncContext->pSvcParam->iRCMode = (RC_MODES) iValue;
953     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
954              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_RC_MODE iRCMode= %d (Note: not suggest changing RC-mode in middle of encoding)",
955              iValue);
956     WelsRcInitFuncPointers (m_pEncContext, m_pEncContext->pSvcParam->iRCMode);
957   }
958   break;
959   case ENCODER_OPTION_RC_FRAME_SKIP: { // 0:FRAME-SKIP disabled;1:FRAME-SKIP enabled
960     bool bValue = * ((bool*)pOption);
961     if (m_pEncContext->pSvcParam->iRCMode != RC_OFF_MODE) {
962       m_pEncContext->pSvcParam->bEnableFrameSkip = bValue;
963       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
964                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_RC_FRAME_SKIP, frame-skip setting(%d)",
965                bValue);
966     } else {
967       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
968                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_RC_FRAME_SKIP, rc off, frame-skip setting(%d) un-useful",
969                bValue);
970     }
971   }
972   break;
973   case ENCODER_PADDING_PADDING: { // 0:disable padding;1:padding
974     int32_t iValue = * ((int32_t*)pOption);
975     m_pEncContext->pSvcParam->iPaddingFlag = iValue;
976     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
977              "CWelsH264SVCEncoder::SetOption():ENCODER_PADDING_PADDING iPaddingFlag= %d ",
978              iValue);
979   }
980   break;
981   case ENCODER_LTR_RECOVERY_REQUEST: {
982     SLTRRecoverRequest* pLTR_Recover_Request = (SLTRRecoverRequest*) (pOption);
983     FilterLTRRecoveryRequest (m_pEncContext, pLTR_Recover_Request);
984   }
985   break;
986   case ENCODER_LTR_MARKING_FEEDBACK: {
987     SLTRMarkingFeedback* fb = (SLTRMarkingFeedback*) (pOption);
988     FilterLTRMarkingFeedback (m_pEncContext, fb);
989   }
990   break;
991   case ENCODER_LTR_MARKING_PERIOD: {
992     uint32_t iValue = * ((uint32_t*) (pOption));
993     m_pEncContext->pSvcParam->iLtrMarkPeriod = iValue;
994     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
995              "CWelsH264SVCEncoder::SetOption():ENCODER_LTR_MARKING_PERIOD iLtrMarkPeriod= %d ",
996              iValue);
997   }
998   break;
999   case ENCODER_OPTION_LTR: {
1000     SLTRConfig* pLTRValue = ((SLTRConfig*) (pOption));
1001     if (WelsEncoderApplyLTR (&m_pWelsTrace->m_sLogCtx, &m_pEncContext, pLTRValue)) {
1002       return cmInitParaError;
1003     }
1004     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1005              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_LTR,expected bEnableLongTermReference = %d,expeced iLTRRefNum = %d,actual bEnableLongTermReference = %d,actual iLTRRefNum = %d",
1006              pLTRValue->bEnableLongTermReference, pLTRValue->iLTRRefNum, m_pEncContext->pSvcParam->bEnableLongTermReference,
1007              m_pEncContext->pSvcParam->iLTRRefNum);
1008   }
1009   break;
1010   case ENCODER_OPTION_ENABLE_SSEI: {
1011     bool iValue = * ((bool*)pOption);
1012     m_pEncContext->pSvcParam->bEnableSSEI = iValue;
1013     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1014              " CWelsH264SVCEncoder::SetOption enable SSEI = %d -- this is not supported yet",
1015              m_pEncContext->pSvcParam->bEnableSSEI);
1016   }
1017   break;
1018   case ENCODER_OPTION_ENABLE_PREFIX_NAL_ADDING: {
1019     bool iValue = * ((bool*)pOption);
1020     m_pEncContext->pSvcParam->bPrefixNalAddingCtrl = iValue;
1021     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption bPrefixNalAddingCtrl = %d ",
1022              m_pEncContext->pSvcParam->bPrefixNalAddingCtrl);
1023   }
1024   break;
1025   case ENCODER_OPTION_SPS_PPS_ID_STRATEGY: {
1026     int32_t iValue = * (static_cast<int32_t*> (pOption));
1027     EParameterSetStrategy eNewStrategy = CONSTANT_ID;
1028     switch (iValue) {
1029     case 0:
1030       eNewStrategy = CONSTANT_ID;
1031       break;
1032     case 0x01:
1033       eNewStrategy = INCREASING_ID;
1034       break;
1035     case 0x02:
1036       eNewStrategy = SPS_LISTING;
1037       break;
1038     case 0x03:
1039       eNewStrategy = SPS_LISTING_AND_PPS_INCREASING;
1040       break;
1041     case 0x06:
1042       eNewStrategy = SPS_PPS_LISTING;
1043       break;
1044     default:
1045       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
1046                " CWelsH264SVCEncoder::SetOption eSpsPpsIdStrategy(%d) not in valid range, unchanged! existing=%d",
1047                iValue, m_pEncContext->pSvcParam->eSpsPpsIdStrategy);
1048       break;
1049     }
1050 
1051     if (((eNewStrategy & SPS_LISTING) || (m_pEncContext->pSvcParam->eSpsPpsIdStrategy & SPS_LISTING))
1052         && m_pEncContext->pSvcParam->eSpsPpsIdStrategy != eNewStrategy) {
1053       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
1054                " CWelsH264SVCEncoder::SetOption eSpsPpsIdStrategy changing in the middle of call is NOT allowed for eSpsPpsIdStrategy>INCREASING_ID: existing setting is %d and the new one is %d",
1055                m_pEncContext->pSvcParam->eSpsPpsIdStrategy, iValue);
1056       return cmInitParaError;
1057     }
1058     SWelsSvcCodingParam sConfig;
1059     memcpy (&sConfig, m_pEncContext->pSvcParam, sizeof (SWelsSvcCodingParam));
1060     sConfig.eSpsPpsIdStrategy = eNewStrategy;
1061     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption eSpsPpsIdStrategy = %d ",
1062              sConfig.eSpsPpsIdStrategy);
1063 
1064     if (WelsEncoderParamAdjust (&m_pEncContext, &sConfig)) {
1065       return cmInitParaError;
1066     }
1067   }
1068   break;
1069   case ENCODER_OPTION_CURRENT_PATH: {
1070     if (m_pEncContext->pSvcParam != NULL) {
1071       char* path = static_cast<char*> (pOption);
1072       m_pEncContext->pSvcParam->pCurPath = path;
1073     }
1074   }
1075   break;
1076   case ENCODER_OPTION_DUMP_FILE: {
1077 #ifdef ENABLE_FRAME_DUMP
1078     if (m_pEncContext->pSvcParam != NULL) {
1079       SDumpLayer* pDump = (static_cast<SDumpLayer*> (pOption));
1080       WelsStrncpy (m_pEncContext->pSvcParam->sDependencyLayers[pDump->iLayer].sRecFileName,
1081                    sizeof (m_pEncContext->pSvcParam->sDependencyLayers[pDump->iLayer].sRecFileName), pDump->pFileName);
1082     }
1083 #endif
1084   }
1085   break;
1086   case ENCODER_OPTION_TRACE_LEVEL: {
1087     if (m_pWelsTrace) {
1088       uint32_t level = * ((uint32_t*)pOption);
1089       m_pWelsTrace->SetTraceLevel (level);
1090     }
1091   }
1092   break;
1093   case ENCODER_OPTION_TRACE_CALLBACK: {
1094     if (m_pWelsTrace) {
1095       WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
1096       m_pWelsTrace->SetTraceCallback (callback);
1097       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1098                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_TRACE_CALLBACK callback = %p.",
1099                callback);
1100     }
1101   }
1102   break;
1103   case ENCODER_OPTION_TRACE_CALLBACK_CONTEXT: {
1104     if (m_pWelsTrace) {
1105       void* ctx = * ((void**)pOption);
1106       m_pWelsTrace->SetTraceCallbackContext (ctx);
1107     }
1108   }
1109   break;
1110   case ENCODER_OPTION_PROFILE: {
1111     SProfileInfo* pProfileInfo = (static_cast<SProfileInfo*> (pOption));
1112     if ((pProfileInfo->iLayer < SPATIAL_LAYER_0) || (pProfileInfo->iLayer > SPATIAL_LAYER_3)) {
1113       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
1114                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_PROFILE,iLayer = %d(rang0-3)", pProfileInfo->iLayer);
1115       return cmInitParaError;
1116     }
1117     CheckProfileSetting (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pProfileInfo->iLayer,
1118                          pProfileInfo->uiProfileIdc);
1119     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1120              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_PROFILE,layerId = %d,expected profile = %d,actual profile = %d",
1121              pProfileInfo->iLayer, pProfileInfo->uiProfileIdc,
1122              m_pEncContext->pSvcParam->sSpatialLayers[pProfileInfo->iLayer].uiProfileIdc);
1123   }
1124   break;
1125   case ENCODER_OPTION_LEVEL: {
1126     SLevelInfo* pLevelInfo = (static_cast<SLevelInfo*> (pOption));
1127     if ((pLevelInfo->iLayer < SPATIAL_LAYER_0) || (pLevelInfo->iLayer > SPATIAL_LAYER_3)) {
1128       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
1129                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_PROFILE,iLayer = %d(rang0-3)", pLevelInfo->iLayer);
1130       return cmInitParaError;
1131     }
1132     CheckLevelSetting (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pLevelInfo->iLayer, pLevelInfo->uiLevelIdc);
1133     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1134              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_LEVEL,layerId = %d,expected level = %d,actual level = %d",
1135              pLevelInfo->iLayer, pLevelInfo->uiLevelIdc, m_pEncContext->pSvcParam->sSpatialLayers[pLevelInfo->iLayer].uiLevelIdc);
1136   }
1137   break;
1138   case ENCODER_OPTION_NUMBER_REF: {
1139     int32_t iValue = * ((int32_t*)pOption);
1140     CheckReferenceNumSetting (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, iValue);
1141     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1142              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_NUMBER_REF,expected refNum = %d,actual refnum = %d", iValue,
1143              m_pEncContext->pSvcParam->iNumRefFrame);
1144   }
1145   break;
1146   case ENCODER_OPTION_DELIVERY_STATUS: {
1147     SDeliveryStatus* pValue = (static_cast<SDeliveryStatus*> (pOption));
1148     m_pEncContext->bDeliveryFlag = pValue->bDeliveryFlag;
1149     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_DEBUG,
1150              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_DELIVERY_STATUS,bDeliveryFlag = %d", pValue->bDeliveryFlag);
1151   }
1152   break;
1153   case ENCODER_OPTION_COMPLEXITY: {
1154     int32_t iValue = * (static_cast<int32_t*> (pOption));
1155     m_pEncContext->pSvcParam->iComplexityMode = (ECOMPLEXITY_MODE)iValue;
1156     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1157              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_COMPLEXITY,iComplexityMode = %d", iValue);
1158   }
1159   break;
1160   case ENCODER_OPTION_GET_STATISTICS: {
1161     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
1162              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_GET_STATISTICS: this option is get-only!");
1163   }
1164   break;
1165   case ENCODER_OPTION_STATISTICS_LOG_INTERVAL: {
1166     int32_t iValue = * (static_cast<int32_t*> (pOption));
1167     m_pEncContext->iStatisticsLogInterval = iValue;
1168     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1169              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_STATISTICS_LOG_INTERVAL,iStatisticsLogInterval = %d", iValue);
1170   }
1171   break;
1172   case ENCODER_OPTION_IS_LOSSLESS_LINK: {
1173     bool bValue = * (static_cast<bool*> (pOption));
1174     m_pEncContext->pSvcParam->bIsLosslessLink = bValue;
1175     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1176              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_IS_LOSSLESS_LINK,bIsLosslessLink = %d", bValue);
1177   }
1178   break;
1179   case ENCODER_OPTION_BITS_VARY_PERCENTAGE: {
1180     int32_t iValue = * (static_cast<int32_t*> (pOption));
1181     m_pEncContext->pSvcParam->iBitsVaryPercentage = WELS_CLIP3 (iValue, 0, 100);
1182     WelsEncoderApplyBitVaryRang (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam,
1183                                  m_pEncContext->pSvcParam->iBitsVaryPercentage);
1184     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1185              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITS_VARY_PERCENTAGE,iBitsVaryPercentage = %d", iValue);
1186   }
1187   break;
1188 
1189   default:
1190     return cmInitParaError;
1191   }
1192 
1193   return 0;
1194 }
1195 
GetOption(ENCODER_OPTION eOptionId,void * pOption)1196 int CWelsH264SVCEncoder::GetOption (ENCODER_OPTION eOptionId, void* pOption) {
1197   if (NULL == pOption) {
1198     return cmInitParaError;
1199   }
1200   if (NULL == m_pEncContext || false == m_bInitialFlag) {
1201     return cmInitExpected;
1202   }
1203 
1204   switch (eOptionId) {
1205   case ENCODER_OPTION_INTER_SPATIAL_PRED: { // Inter spatial layer prediction flag
1206     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1207              "ENCODER_OPTION_INTER_SPATIAL_PRED, this feature not supported at present.");
1208   }
1209   break;
1210   case ENCODER_OPTION_DATAFORMAT: { // Input color space
1211     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1212              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_DATAFORMAT, m_iCspInternal= 0x%x", m_iCspInternal);
1213     * ((int32_t*)pOption) = m_iCspInternal;
1214   }
1215   break;
1216   case ENCODER_OPTION_IDR_INTERVAL: { // IDR Interval
1217     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1218              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_IDR_INTERVAL, uiIntraPeriod= %d",
1219              m_pEncContext->pSvcParam->uiIntraPeriod);
1220     * ((int32_t*)pOption) = m_pEncContext->pSvcParam->uiIntraPeriod;
1221   }
1222   break;
1223   case ENCODER_OPTION_SVC_ENCODE_PARAM_EXT: { // SVC Encoding Parameter
1224     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1225              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT");
1226     memcpy (pOption, m_pEncContext->pSvcParam, sizeof (SEncParamExt)); // confirmed_safe_unsafe_usage
1227   }
1228   break;
1229   case ENCODER_OPTION_SVC_ENCODE_PARAM_BASE: { // SVC Encoding Parameter
1230     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1231              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_BASE");
1232     m_pEncContext->pSvcParam->GetBaseParams ((SEncParamBase*) pOption);
1233   }
1234   break;
1235 
1236   case ENCODER_OPTION_FRAME_RATE: { // Maximal input frame rate
1237     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1238              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_FRAME_RATE, fMaxFrameRate = %.6ff",
1239              m_pEncContext->pSvcParam->fMaxFrameRate);
1240     * ((float*)pOption) = m_pEncContext->pSvcParam->fMaxFrameRate;
1241   }
1242   break;
1243   case ENCODER_OPTION_BITRATE: { // Target bit-rate
1244 
1245     SBitrateInfo* pInfo = (static_cast<SBitrateInfo*> (pOption));
1246     if ((pInfo->iLayer != SPATIAL_LAYER_ALL) && (pInfo->iLayer != SPATIAL_LAYER_0) && (pInfo->iLayer != SPATIAL_LAYER_1)
1247         && (pInfo->iLayer != SPATIAL_LAYER_2) && (pInfo->iLayer != SPATIAL_LAYER_3))
1248       return cmInitParaError;
1249     if (pInfo->iLayer == SPATIAL_LAYER_ALL) {
1250       pInfo->iBitrate = m_pEncContext->pSvcParam->iTargetBitrate;
1251     } else {
1252       pInfo->iBitrate = m_pEncContext->pSvcParam->sSpatialLayers[pInfo->iLayer].iSpatialBitrate;
1253     }
1254     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1255              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_BITRATE, layerId =%d,iBitrate = %d",
1256              pInfo->iLayer, pInfo->iBitrate);
1257   }
1258   break;
1259   case ENCODER_OPTION_MAX_BITRATE: { // Target bit-rate
1260     SBitrateInfo* pInfo = (static_cast<SBitrateInfo*> (pOption));
1261     if ((pInfo->iLayer != SPATIAL_LAYER_ALL) && (pInfo->iLayer != SPATIAL_LAYER_0) && (pInfo->iLayer != SPATIAL_LAYER_1)
1262         && (pInfo->iLayer != SPATIAL_LAYER_2) && (pInfo->iLayer != SPATIAL_LAYER_3))
1263       return cmInitParaError;
1264     if (pInfo->iLayer == SPATIAL_LAYER_ALL) {
1265       pInfo->iBitrate = m_pEncContext->pSvcParam->iMaxBitrate;
1266     } else {
1267       pInfo->iBitrate = m_pEncContext->pSvcParam->sSpatialLayers[pInfo->iLayer].iMaxSpatialBitrate;
1268     }
1269     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
1270              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_MAX_BITRATE,, layerId =%d,iBitrate = %d",
1271              pInfo->iLayer, pInfo->iBitrate);
1272   }
1273   break;
1274   case ENCODER_OPTION_GET_STATISTICS: {
1275     SEncoderStatistics* pStatistics = (static_cast<SEncoderStatistics*> (pOption));
1276     SEncoderStatistics* pEncStatistics = &m_pEncContext->sEncoderStatistics[m_pEncContext->pSvcParam->iSpatialLayerNum - 1];
1277     pStatistics->uiWidth = pEncStatistics->uiWidth;
1278     pStatistics->uiHeight = pEncStatistics->uiHeight;
1279     pStatistics->fAverageFrameSpeedInMs = pEncStatistics->fAverageFrameSpeedInMs;
1280 
1281     // rate control related
1282     pStatistics->fAverageFrameRate = pEncStatistics->fAverageFrameRate;
1283     pStatistics->fLatestFrameRate = pEncStatistics->fLatestFrameRate;
1284     pStatistics->uiBitRate = pEncStatistics->uiBitRate;
1285 
1286     pStatistics->uiInputFrameCount = pEncStatistics->uiInputFrameCount;
1287     pStatistics->uiSkippedFrameCount = pEncStatistics->uiSkippedFrameCount;
1288 
1289     pStatistics->uiResolutionChangeTimes = pEncStatistics->uiResolutionChangeTimes;
1290     pStatistics->uiIDRReqNum = pEncStatistics->uiIDRReqNum;
1291     pStatistics->uiIDRSentNum = pEncStatistics->uiIDRSentNum;
1292     pStatistics->uiLTRSentNum = pEncStatistics->uiLTRSentNum;
1293   }
1294   break;
1295   case ENCODER_OPTION_STATISTICS_LOG_INTERVAL: {
1296     * ((int32_t*)pOption) = m_pEncContext->iStatisticsLogInterval;
1297   }
1298   break;
1299   case ENCODER_OPTION_COMPLEXITY: {
1300     * ((int32_t*)pOption) =  m_pEncContext->pSvcParam->iComplexityMode;
1301   }
1302   break;
1303   default:
1304     return cmInitParaError;
1305   }
1306 
1307   return 0;
1308 }
1309 
DumpSrcPicture(const SSourcePicture * pSrcPic,const int iUsageType)1310 void CWelsH264SVCEncoder::DumpSrcPicture (const SSourcePicture*  pSrcPic, const int iUsageType) {
1311 #ifdef DUMP_SRC_PICTURE
1312   FILE* pFile = NULL;
1313   char strFileName[256] = {0};
1314   const int32_t iDataLength = m_iMaxPicWidth * m_iMaxPicHeight;
1315 
1316   WelsSnprintf (strFileName, sizeof (strFileName), "pic_in_%dx%d.yuv", m_iMaxPicWidth,
1317                 m_iMaxPicHeight);// confirmed_safe_unsafe_usage
1318 
1319   switch (pSrcPic->iColorFormat) {
1320   case videoFormatI420:
1321   case videoFormatYV12:
1322     pFile = WelsFopen (strFileName, "ab+");
1323 
1324     if (NULL != pFile) {
1325       fwrite (pSrcPic->pData[0], sizeof (uint8_t), pSrcPic->iStride[0]*m_iMaxPicHeight, pFile);
1326       fwrite (pSrcPic->pData[1], sizeof (uint8_t), pSrcPic->iStride[1] * (m_iMaxPicHeight >> 1), pFile);
1327       fwrite (pSrcPic->pData[2], sizeof (uint8_t), pSrcPic->iStride[2] * (m_iMaxPicHeight >> 1), pFile);
1328       fflush (pFile);
1329       fclose (pFile);
1330     } else {
1331       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "DumpSrcPicture, strFileName %s open failed!", strFileName);
1332     }
1333     break;
1334   case videoFormatRGB:
1335     WelsStrcat (strFileName, 256, ".rgb"); // confirmed_safe_unsafe_usage
1336     pFile = WelsFopen (strFileName, "ab+");
1337     if (NULL != pFile) {
1338       fwrite (pSrcPic->pData[0], sizeof (uint8_t), iDataLength * 3, pFile);
1339       fflush (pFile);
1340       fclose (pFile);
1341     }
1342   case videoFormatBGR:
1343     WelsStrcat (strFileName, 256, ".bgr"); // confirmed_safe_unsafe_usage
1344     pFile = WelsFopen (strFileName, "ab+");
1345     if (NULL != pFile) {
1346       fwrite (pSrcPic->pData[0], sizeof (uint8_t), iDataLength * 3, pFile);
1347       fflush (pFile);
1348       fclose (pFile);
1349     }
1350     break;
1351   case videoFormatYUY2:
1352     WelsStrcat (strFileName, 256, ".yuy2"); // confirmed_safe_unsafe_usage
1353     pFile = WelsFopen (strFileName, "ab+");
1354     if (NULL != pFile) {
1355       fwrite (pSrcPic->pData[0], sizeof (uint8_t), (CALC_BI_STRIDE (m_iMaxPicWidth,  16)) * m_iMaxPicHeight, pFile);
1356       fflush (pFile);
1357       fclose (pFile);
1358     }
1359     break;
1360   default:
1361     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "Exclusive case, m_iCspInternal= 0x%x", m_iCspInternal);
1362     break;
1363   }
1364 #endif//DUMP_SRC_PICTURE
1365   return;
1366 }
1367 }
1368 
1369 using namespace WelsEnc;
1370 
WelsCreateSVCEncoder(ISVCEncoder ** ppEncoder)1371 int32_t WelsCreateSVCEncoder (ISVCEncoder** ppEncoder) {
1372   if ((*ppEncoder = new CWelsH264SVCEncoder()) != NULL) {
1373     return 0;
1374   }
1375 
1376   return 1;
1377 }
1378 
WelsDestroySVCEncoder(ISVCEncoder * pEncoder)1379 void WelsDestroySVCEncoder (ISVCEncoder* pEncoder) {
1380   CWelsH264SVCEncoder* pSVCEncoder = (CWelsH264SVCEncoder*)pEncoder;
1381 
1382   if (pSVCEncoder) {
1383     delete pSVCEncoder;
1384     pSVCEncoder = NULL;
1385   }
1386 }
1387 
WelsGetCodecVersion()1388 OpenH264Version WelsGetCodecVersion() {
1389   return g_stCodecVersion;
1390 }
1391 
WelsGetCodecVersionEx(OpenH264Version * pVersion)1392 void WelsGetCodecVersionEx (OpenH264Version* pVersion) {
1393   *pVersion = g_stCodecVersion;
1394 }
1395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1396