Coverage Report

Created: 2026-07-25 07:06

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