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 pStatistics->uiAverageFrameQP = pEncStatistics->uiAverageFrameQP;
1286
1287 pStatistics->uiInputFrameCount = pEncStatistics->uiInputFrameCount;
1288 pStatistics->uiSkippedFrameCount = pEncStatistics->uiSkippedFrameCount;
1289
1290 pStatistics->uiResolutionChangeTimes = pEncStatistics->uiResolutionChangeTimes;
1291 pStatistics->uiIDRReqNum = pEncStatistics->uiIDRReqNum;
1292 pStatistics->uiIDRSentNum = pEncStatistics->uiIDRSentNum;
1293 pStatistics->uiLTRSentNum = pEncStatistics->uiLTRSentNum;
1294 }
1295 break;
1296 case ENCODER_OPTION_STATISTICS_LOG_INTERVAL: {
1297 * ((int32_t*)pOption) = m_pEncContext->iStatisticsLogInterval;
1298 }
1299 break;
1300 case ENCODER_OPTION_COMPLEXITY: {
1301 * ((int32_t*)pOption) = m_pEncContext->pSvcParam->iComplexityMode;
1302 }
1303 break;
1304 default:
1305 return cmInitParaError;
1306 }
1307
1308 return 0;
1309 }
1310
DumpSrcPicture(const SSourcePicture * pSrcPic,const int iUsageType)1311 void CWelsH264SVCEncoder::DumpSrcPicture (const SSourcePicture* pSrcPic, const int iUsageType) {
1312 #ifdef DUMP_SRC_PICTURE
1313 FILE* pFile = NULL;
1314 char strFileName[256] = {0};
1315 const int32_t iDataLength = m_iMaxPicWidth * m_iMaxPicHeight;
1316
1317 WelsSnprintf (strFileName, sizeof (strFileName), "pic_in_%dx%d.yuv", m_iMaxPicWidth,
1318 m_iMaxPicHeight);// confirmed_safe_unsafe_usage
1319
1320 switch (pSrcPic->iColorFormat) {
1321 case videoFormatI420:
1322 case videoFormatYV12:
1323 pFile = WelsFopen (strFileName, "ab+");
1324
1325 if (NULL != pFile) {
1326 fwrite (pSrcPic->pData[0], sizeof (uint8_t), pSrcPic->iStride[0]*m_iMaxPicHeight, pFile);
1327 fwrite (pSrcPic->pData[1], sizeof (uint8_t), pSrcPic->iStride[1] * (m_iMaxPicHeight >> 1), pFile);
1328 fwrite (pSrcPic->pData[2], sizeof (uint8_t), pSrcPic->iStride[2] * (m_iMaxPicHeight >> 1), pFile);
1329 fflush (pFile);
1330 fclose (pFile);
1331 } else {
1332 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "DumpSrcPicture, strFileName %s open failed!", strFileName);
1333 }
1334 break;
1335 case videoFormatRGB:
1336 WelsStrcat (strFileName, 256, ".rgb"); // confirmed_safe_unsafe_usage
1337 pFile = WelsFopen (strFileName, "ab+");
1338 if (NULL != pFile) {
1339 fwrite (pSrcPic->pData[0], sizeof (uint8_t), iDataLength * 3, pFile);
1340 fflush (pFile);
1341 fclose (pFile);
1342 }
1343 case videoFormatBGR:
1344 WelsStrcat (strFileName, 256, ".bgr"); // confirmed_safe_unsafe_usage
1345 pFile = WelsFopen (strFileName, "ab+");
1346 if (NULL != pFile) {
1347 fwrite (pSrcPic->pData[0], sizeof (uint8_t), iDataLength * 3, pFile);
1348 fflush (pFile);
1349 fclose (pFile);
1350 }
1351 break;
1352 case videoFormatYUY2:
1353 WelsStrcat (strFileName, 256, ".yuy2"); // confirmed_safe_unsafe_usage
1354 pFile = WelsFopen (strFileName, "ab+");
1355 if (NULL != pFile) {
1356 fwrite (pSrcPic->pData[0], sizeof (uint8_t), (CALC_BI_STRIDE (m_iMaxPicWidth, 16)) * m_iMaxPicHeight, pFile);
1357 fflush (pFile);
1358 fclose (pFile);
1359 }
1360 break;
1361 default:
1362 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "Exclusive case, m_iCspInternal= 0x%x", m_iCspInternal);
1363 break;
1364 }
1365 #endif//DUMP_SRC_PICTURE
1366 return;
1367 }
1368 }
1369
1370 using namespace WelsEnc;
1371
WelsCreateSVCEncoder(ISVCEncoder ** ppEncoder)1372 int32_t WelsCreateSVCEncoder (ISVCEncoder** ppEncoder) {
1373 if ((*ppEncoder = new CWelsH264SVCEncoder()) != NULL) {
1374 return 0;
1375 }
1376
1377 return 1;
1378 }
1379
WelsDestroySVCEncoder(ISVCEncoder * pEncoder)1380 void WelsDestroySVCEncoder (ISVCEncoder* pEncoder) {
1381 CWelsH264SVCEncoder* pSVCEncoder = (CWelsH264SVCEncoder*)pEncoder;
1382
1383 if (pSVCEncoder) {
1384 delete pSVCEncoder;
1385 pSVCEncoder = NULL;
1386 }
1387 }
1388
WelsGetCodecVersion()1389 OpenH264Version WelsGetCodecVersion() {
1390 return g_stCodecVersion;
1391 }
1392
WelsGetCodecVersionEx(OpenH264Version * pVersion)1393 void WelsGetCodecVersionEx (OpenH264Version* pVersion) {
1394 *pVersion = g_stCodecVersion;
1395 }
1396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1397