Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/openh264/codec/decoder/plus/src/welsDecoderExt.cpp
Line
Count
Source
1
/*!
2
 * \copy
3
 *     Copyright (c)  2009-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
 *  welsDecoderExt.cpp
33
 *
34
 *  Abstract
35
 *      Cisco OpenH264 decoder extension utilization
36
 *
37
 *  History
38
 *      3/12/2009 Created
39
 *
40
 *
41
 ************************************************************************/
42
//#include <assert.h>
43
#include "welsDecoderExt.h"
44
#include "welsCodecTrace.h"
45
#include "codec_def.h"
46
#include "typedefs.h"
47
#include "memory_align.h"
48
#include "utils.h"
49
#include "version.h"
50
51
//#include "macros.h"
52
#include "decoder.h"
53
#include "decoder_core.h"
54
#include "manage_dec_ref.h"
55
#include "error_concealment.h"
56
57
#include "measure_time.h"
58
extern "C" {
59
#include "decoder_core.h"
60
#include "manage_dec_ref.h"
61
}
62
#include "error_code.h"
63
#include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
64
#include <time.h>
65
#if defined(_WIN32) /*&& defined(_DEBUG)*/
66
67
#include <windows.h>
68
#include <stdio.h>
69
#include <stdarg.h>
70
#include <sys/types.h>
71
#include <malloc.h>
72
#else
73
#include <sys/time.h>
74
#endif
75
76
namespace WelsDec {
77
78
//////////////////////////////////////////////////////////////////////
79
// Construction/Destruction
80
//////////////////////////////////////////////////////////////////////
81
82
/***************************************************************************
83
*   Description:
84
*       class CWelsDecoder constructor function, do initialization  and
85
*       alloc memory required
86
*
87
*   Input parameters: none
88
*
89
*   return: none
90
***************************************************************************/
91
0
DECLARE_PROCTHREAD (pThrProcInit, p) {
92
0
  SWelsDecThreadInfo* sThreadInfo = (SWelsDecThreadInfo*)p;
93
#if defined(WIN32)
94
  _alloca (WELS_DEC_MAX_THREAD_STACK_SIZE * (sThreadInfo->uiThrNum + 1));
95
#endif
96
0
  return sThreadInfo->pThrProcMain (p);
97
0
}
98
99
0
static DECODING_STATE  ConstructAccessUnit (CWelsDecoder* pWelsDecoder, PWelsDecoderThreadCTX pThrCtx) {
100
0
  int iRet = dsErrorFree;
101
  //WelsMutexLock (&pWelsDecoder->m_csDecoder);
102
0
  if (pThrCtx->pCtx->pLastThreadCtx != NULL) {
103
0
    PWelsDecoderThreadCTX pLastThreadCtx = (PWelsDecoderThreadCTX) (pThrCtx->pCtx->pLastThreadCtx);
104
0
    WAIT_EVENT (&pLastThreadCtx->sSliceDecodeStart, WELS_DEC_THREAD_WAIT_INFINITE);
105
0
    RESET_EVENT (&pLastThreadCtx->sSliceDecodeStart);
106
0
  }
107
0
  pThrCtx->pDec = NULL;
108
0
  if (GetThreadCount (pThrCtx->pCtx) > 1) {
109
0
    RESET_EVENT (&pThrCtx->sSliceDecodeFinish);
110
0
  }
111
0
  iRet |= pWelsDecoder->DecodeFrame2WithCtx (pThrCtx->pCtx, NULL, 0, pThrCtx->ppDst, &pThrCtx->sDstInfo);
112
113
  //WelsMutexUnlock (&pWelsDecoder->m_csDecoder);
114
0
  return (DECODING_STATE)iRet;
115
0
}
116
117
0
DECLARE_PROCTHREAD (pThrProcFrame, p) {
118
0
  SWelsDecoderThreadCTX* pThrCtx = (SWelsDecoderThreadCTX*)p;
119
0
  while (1) {
120
0
    RELEASE_SEMAPHORE (pThrCtx->sThreadInfo.sIsBusy);
121
0
    RELEASE_SEMAPHORE (&pThrCtx->sThreadInfo.sIsIdle);
122
0
    WAIT_SEMAPHORE (&pThrCtx->sThreadInfo.sIsActivated, WELS_DEC_THREAD_WAIT_INFINITE);
123
0
    if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_RUN) {
124
0
      CWelsDecoder* pWelsDecoder = (CWelsDecoder*)pThrCtx->threadCtxOwner;
125
0
      ConstructAccessUnit (pWelsDecoder, pThrCtx);
126
0
    } else if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_ABORT) {
127
0
      break;
128
0
    }
129
0
  }
130
0
  return 0;
131
0
}
132
133
CWelsDecoder::CWelsDecoder (void)
134
33
  : m_pWelsTrace (NULL),
135
33
    m_uiDecodeTimeStamp (0),
136
33
    m_bIsBaseline (false),
137
33
    m_iCpuCount (1),
138
33
    m_iThreadCount (0),
139
33
    m_iCtxCount (1),
140
33
    m_pPicBuff (NULL),
141
33
    m_bParamSetsLostFlag (false),
142
33
    m_bFreezeOutput (false),
143
33
    m_DecCtxActiveCount (0),
144
33
    m_pDecThrCtx (NULL),
145
33
    m_pLastDecThrCtx (NULL),
146
33
    m_iLastBufferedIdx (0),
147
33
    m_iStreamSeqNum (0) {
148
#ifdef OUTPUT_BIT_STREAM
149
  char chFileName[1024] = { 0 };  //for .264
150
  int iBufUsed = 0;
151
  int iBufLeft = 1023;
152
  int iCurUsed;
153
154
  char chFileNameSize[1024] = { 0 }; //for .len
155
  int iBufUsedSize = 0;
156
  int iBufLeftSize = 1023;
157
  int iCurUsedSize;
158
#endif//OUTPUT_BIT_STREAM
159
160
161
33
  m_pWelsTrace = new welsCodecTrace();
162
33
  if (m_pWelsTrace != NULL) {
163
33
    m_pWelsTrace->SetCodecInstance (this);
164
33
    m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
165
166
33
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
167
33
  }
168
169
33
  ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
170
171
33
  m_iCpuCount = GetCPUCount();
172
33
  if (m_iCpuCount > WELS_DEC_MAX_NUM_CPU) {
173
33
    m_iCpuCount = WELS_DEC_MAX_NUM_CPU;
174
33
  }
175
176
33
  m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];
177
33
  memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);
178
561
  for (int32_t i = 0; i < WELS_DEC_MAX_NUM_CPU; ++i) {
179
528
    m_pDecThrCtxActive[i] = NULL;
180
528
  }
181
#ifdef OUTPUT_BIT_STREAM
182
  SWelsTime sCurTime;
183
184
  WelsGetTimeOfDay (&sCurTime);
185
186
  iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);
187
  iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);
188
189
  iBufUsed += iCurUsed;
190
  iBufLeft -= iCurUsed;
191
  if (iBufLeft > 0) {
192
    iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
193
    iBufUsed += iCurUsed;
194
    iBufLeft -= iCurUsed;
195
  }
196
197
  iBufUsedSize += iCurUsedSize;
198
  iBufLeftSize -= iCurUsedSize;
199
  if (iBufLeftSize > 0) {
200
    iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
201
    iBufUsedSize += iCurUsedSize;
202
    iBufLeftSize -= iCurUsedSize;
203
  }
204
205
  if (iBufLeft > 0) {
206
    iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
207
    iBufUsed += iCurUsed;
208
    iBufLeft -= iCurUsed;
209
  }
210
211
  if (iBufLeftSize > 0) {
212
    iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
213
                                 WelsGetMillisecond (&sCurTime));
214
    iBufUsedSize += iCurUsedSize;
215
    iBufLeftSize -= iCurUsedSize;
216
  }
217
218
219
  m_pFBS = WelsFopen (chFileName, "wb");
220
  m_pFBSSize = WelsFopen (chFileNameSize, "wb");
221
#endif//OUTPUT_BIT_STREAM
222
33
}
223
224
/***************************************************************************
225
*   Description:
226
*       class CWelsDecoder destructor function, destroy allocced memory
227
*
228
*   Input parameters: none
229
*
230
*   return: none
231
***************************************************************************/
232
33
CWelsDecoder::~CWelsDecoder() {
233
33
  if (m_pWelsTrace != NULL) {
234
33
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
235
33
  }
236
33
  CloseDecoderThreads();
237
33
  UninitDecoder();
238
239
#ifdef OUTPUT_BIT_STREAM
240
  if (m_pFBS) {
241
    WelsFclose (m_pFBS);
242
    m_pFBS = NULL;
243
  }
244
  if (m_pFBSSize) {
245
    WelsFclose (m_pFBSSize);
246
    m_pFBSSize = NULL;
247
  }
248
#endif//OUTPUT_BIT_STREAM
249
250
33
  if (m_pWelsTrace != NULL) {
251
33
    delete m_pWelsTrace;
252
33
    m_pWelsTrace = NULL;
253
33
  }
254
33
  if (m_pDecThrCtx != NULL) {
255
33
    delete[] m_pDecThrCtx;
256
33
    m_pDecThrCtx = NULL;
257
33
  }
258
33
}
259
260
33
long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
261
33
  int iRet = ERR_NONE;
262
33
  if (m_pWelsTrace == NULL) {
263
0
    return cmMallocMemeError;
264
0
  }
265
266
33
  if (pParam == NULL) {
267
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");
268
0
    return cmInitParaError;
269
0
  }
270
271
  // H.264 decoder initialization,including memory allocation,then open it ready to decode
272
33
  iRet = InitDecoder (pParam);
273
33
  if (iRet)
274
0
    return iRet;
275
276
33
  return cmResultSuccess;
277
33
}
278
279
33
long CWelsDecoder::Uninitialize() {
280
33
  UninitDecoder();
281
282
33
  return ERR_NONE;
283
33
}
284
285
99
void CWelsDecoder::UninitDecoder (void) {
286
198
  for (int32_t i = 0; i < m_iCtxCount; ++i) {
287
99
    if (m_pDecThrCtx[i].pCtx != NULL) {
288
33
      if (i > 0) {
289
0
        WelsResetRefPicWithoutUnRef (m_pDecThrCtx[i].pCtx);
290
0
      }
291
33
      UninitDecoderCtx (m_pDecThrCtx[i].pCtx);
292
33
    }
293
99
  }
294
99
}
295
296
33
void CWelsDecoder::OpenDecoderThreads() {
297
33
  if (m_iThreadCount >= 1) {
298
0
    m_uiDecodeTimeStamp = 0;
299
0
    CREATE_SEMAPHORE (&m_sIsBusy, m_iThreadCount, m_iThreadCount, NULL);
300
0
    WelsMutexInit (&m_csDecoder);
301
0
    CREATE_EVENT (&m_sBufferingEvent, 1, 0, NULL);
302
0
    SET_EVENT (&m_sBufferingEvent);
303
0
    CREATE_EVENT (&m_sReleaseBufferEvent, 1, 0, NULL);
304
0
    SET_EVENT (&m_sReleaseBufferEvent);
305
0
    for (int32_t i = 0; i < m_iThreadCount; ++i) {
306
0
      m_pDecThrCtx[i].sThreadInfo.uiThrMaxNum = m_iThreadCount;
307
0
      m_pDecThrCtx[i].sThreadInfo.uiThrNum = i;
308
0
      m_pDecThrCtx[i].sThreadInfo.uiThrStackSize = WELS_DEC_MAX_THREAD_STACK_SIZE;
309
0
      m_pDecThrCtx[i].sThreadInfo.pThrProcMain = pThrProcFrame;
310
0
      m_pDecThrCtx[i].sThreadInfo.sIsBusy = &m_sIsBusy;
311
0
      m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
312
0
      m_pDecThrCtx[i].threadCtxOwner = this;
313
0
      m_pDecThrCtx[i].kpSrc = NULL;
314
0
      m_pDecThrCtx[i].kiSrcLen = 0;
315
0
      m_pDecThrCtx[i].ppDst = NULL;
316
0
      m_pDecThrCtx[i].pDec = NULL;
317
0
      CREATE_EVENT (&m_pDecThrCtx[i].sImageReady, 1, 0, NULL);
318
0
      CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart, 1, 0, NULL);
319
0
      CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinish, 1, 0, NULL);
320
0
      CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, 0, 1, NULL);
321
0
      CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated, 0, 1, NULL);
322
0
      CREATE_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle, pThrProcInit, (void*) (& (m_pDecThrCtx[i])));
323
0
    }
324
0
  }
325
33
}
326
33
void CWelsDecoder::CloseDecoderThreads() {
327
33
  if (m_iThreadCount >= 1) {
328
0
    SET_EVENT (&m_sReleaseBufferEvent);
329
0
    for (int32_t i = 0; i < m_iThreadCount; i++) { //waiting the completion begun slices
330
0
      WAIT_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
331
0
      m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_ABORT;
332
0
      RELEASE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated);
333
0
      WAIT_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle);
334
0
      CLOSE_EVENT (&m_pDecThrCtx[i].sImageReady);
335
0
      CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart);
336
0
      CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinish);
337
0
      CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle);
338
0
      CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated);
339
0
    }
340
0
    WelsMutexDestroy (&m_csDecoder);
341
0
    CLOSE_EVENT (&m_sBufferingEvent);
342
0
    CLOSE_EVENT (&m_sReleaseBufferEvent);
343
0
    CLOSE_SEMAPHORE (&m_sIsBusy);
344
0
  }
345
33
}
346
347
66
void CWelsDecoder::UninitDecoderCtx (PWelsDecoderContext& pCtx) {
348
66
  if (pCtx != NULL) {
349
350
33
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoderCtx(), openh264 codec version = %s.",
351
33
             VERSION_NUMBER);
352
353
33
    WelsEndDecoder (pCtx);
354
355
33
    if (pCtx->pMemAlign != NULL) {
356
33
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
357
33
               "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
358
33
               pCtx->pMemAlign->WelsGetMemoryUsage());
359
33
      delete pCtx->pMemAlign;
360
33
      pCtx->pMemAlign = NULL;
361
33
    }
362
363
33
    if (NULL != pCtx) {
364
33
      WelsFree (pCtx, "m_pDecContext");
365
366
33
      pCtx = NULL;
367
33
    }
368
33
    if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = NULL;
369
33
  }
370
66
}
371
372
// the return value of this function is not suitable, it need report failure info to upper layer.
373
33
int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
374
375
33
  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
376
33
           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
377
33
           VERSION_NUMBER, (int32_t)pParam->bParseOnly);
378
33
  if (m_iThreadCount >= 1 && pParam->bParseOnly) {
379
0
    m_iThreadCount = 0;
380
0
  }
381
33
  OpenDecoderThreads();
382
  //reset decoder context
383
33
  memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics));
384
33
  memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo));
385
33
  memset (&m_sVlcTable, 0, sizeof (SVlcTable));
386
33
  UninitDecoder();
387
33
  WelsDecoderLastDecPicInfoDefaults (m_sLastDecPicInfo);
388
66
  for (int32_t i = 0; i < m_iCtxCount; ++i) {
389
33
    InitDecoderCtx (m_pDecThrCtx[i].pCtx, pParam);
390
33
    if (m_iThreadCount >= 1) {
391
0
      m_pDecThrCtx[i].pCtx->pThreadCtx = &m_pDecThrCtx[i];
392
0
    }
393
33
  }
394
33
  m_bParamSetsLostFlag = false;
395
33
  m_bFreezeOutput = false;
396
33
  return cmResultSuccess;
397
33
}
398
399
// the return value of this function is not suitable, it need report failure info to upper layer.
400
33
int32_t CWelsDecoder::InitDecoderCtx (PWelsDecoderContext& pCtx, const SDecodingParam* pParam) {
401
402
33
  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
403
33
           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
404
33
           VERSION_NUMBER, (int32_t)pParam->bParseOnly);
405
406
  //reset decoder context
407
33
  UninitDecoderCtx (pCtx);
408
33
  pCtx = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
409
33
  if (NULL == pCtx)
410
0
    return cmMallocMemeError;
411
33
  int32_t iCacheLineSize = 16;   // on chip cache line size in byte
412
33
  pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);
413
33
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pMemAlign), UninitDecoderCtx (pCtx))
414
33
  if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = pCtx;
415
  //fill in default value into context
416
33
  pCtx->pLastDecPicInfo = &m_sLastDecPicInfo;
417
33
  pCtx->pDecoderStatistics = &m_sDecoderStatistics;
418
33
  pCtx->pVlcTable = &m_sVlcTable;
419
33
  pCtx->pPictInfoList = m_sPictInfoList;
420
33
  pCtx->pPictReoderingStatus = &m_sReoderingStatus;
421
33
  pCtx->pCsDecoder = &m_csDecoder;
422
33
  pCtx->pStreamSeqNum = &m_iStreamSeqNum;
423
33
  WelsDecoderDefaults (pCtx, &m_pWelsTrace->m_sLogCtx);
424
33
  WelsDecoderSpsPpsDefaults (pCtx->sSpsPpsCtx);
425
  //check param and update decoder context
426
33
  pCtx->pParam = (SDecodingParam*)pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
427
33
                 "SDecodingParam");
428
33
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoderCtx (pCtx));
429
33
  int32_t iRet = DecoderConfigParam (pCtx, pParam);
430
33
  WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
431
432
  //init decoder
433
33
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (pCtx, &m_pWelsTrace->m_sLogCtx),
434
33
                              UninitDecoderCtx (pCtx))
435
33
  pCtx->pPicBuff = NULL;
436
33
  return cmResultSuccess;
437
33
}
438
439
0
int32_t CWelsDecoder::ResetDecoder (PWelsDecoderContext& pCtx) {
440
  // TBC: need to be modified when context and trace point are null
441
0
  if (m_iThreadCount >= 1) {
442
0
    ThreadResetDecoder (pCtx);
443
0
  } else {
444
0
    if (pCtx != NULL && m_pWelsTrace != NULL) {
445
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",
446
0
               pCtx->iErrorCode);
447
0
      SDecodingParam sPrevParam;
448
0
      memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));
449
450
0
      WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoderCtx (pCtx, &sPrevParam),
451
0
                                  UninitDecoderCtx (pCtx));
452
0
    } else if (m_pWelsTrace != NULL) {
453
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
454
0
    }
455
0
    ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, false);
456
0
  }
457
0
  return ERR_INFO_UNINIT;
458
0
}
459
460
0
int32_t CWelsDecoder::ThreadResetDecoder (PWelsDecoderContext& pCtx) {
461
  // TBC: need to be modified when context and trace point are null
462
0
  SDecodingParam sPrevParam;
463
0
  if (pCtx != NULL && m_pWelsTrace != NULL) {
464
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", pCtx->iErrorCode);
465
0
    memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));
466
0
    ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
467
0
    CloseDecoderThreads();
468
0
    UninitDecoder();
469
0
    InitDecoder (&sPrevParam);
470
0
  } else if (m_pWelsTrace != NULL) {
471
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
472
0
  }
473
0
  return ERR_INFO_UNINIT;
474
0
}
475
476
/*
477
 * Set Option
478
 */
479
0
long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
480
0
  int iVal = 0;
481
0
  if (eOptID == DECODER_OPTION_NUM_OF_THREADS) {
482
0
    if (pOption != NULL) {
483
0
      int32_t threadCount = * ((int32_t*)pOption);
484
0
      if (threadCount < 0) threadCount = 0;
485
0
      if (threadCount > m_iCpuCount) {
486
0
        threadCount = m_iCpuCount;
487
0
      }
488
0
      if (threadCount > 3) {
489
0
        threadCount = 3;
490
0
      }
491
0
      if (threadCount != m_iThreadCount) {
492
0
        m_iThreadCount = threadCount;
493
0
        if (m_pDecThrCtx != NULL) {
494
0
          delete [] m_pDecThrCtx;
495
0
          m_iCtxCount = m_iThreadCount == 0 ? 1 : m_iThreadCount;
496
0
          m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];
497
0
          memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);
498
0
        }
499
0
      }
500
0
    }
501
0
    return cmResultSuccess;
502
0
  }
503
0
  for (int32_t i = 0; i < m_iCtxCount; ++i) {
504
0
    PWelsDecoderContext pDecContext = m_pDecThrCtx[i].pCtx;
505
0
    if (pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
506
0
        eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
507
0
      return dsInitialOptExpected;
508
0
    if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded
509
0
      if (pOption == NULL)
510
0
        return cmInitParaError;
511
512
0
      iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag
513
514
0
      if (pDecContext == NULL) return dsInitialOptExpected;
515
516
0
      pDecContext->bEndOfStreamFlag = iVal ? true : false;
517
0
      if (iVal && m_iThreadCount >= 1)
518
0
        SET_EVENT (&m_sReleaseBufferEvent);
519
520
0
      return cmResultSuccess;
521
0
    } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status
522
0
      if (pOption == NULL)
523
0
        return cmInitParaError;
524
525
0
      if (pDecContext == NULL) return dsInitialOptExpected;
526
527
0
      iVal = * ((int*)pOption); // int value for error concealment idc
528
0
      iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
529
0
      if ((pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) {
530
0
        WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
531
0
                 "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
532
0
        return cmInitParaError;
533
0
      }
534
535
0
      pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal;
536
0
      InitErrorCon (pDecContext);
537
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
538
0
               "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal);
539
540
0
      return cmResultSuccess;
541
0
    } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
542
0
      if (m_pWelsTrace) {
543
0
        uint32_t level = * ((uint32_t*)pOption);
544
0
        m_pWelsTrace->SetTraceLevel (level);
545
0
      }
546
0
      return cmResultSuccess;
547
0
    } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
548
0
      if (m_pWelsTrace) {
549
0
        WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
550
0
        m_pWelsTrace->SetTraceCallback (callback);
551
0
        WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
552
0
                 "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.",
553
0
                 callback);
554
0
      }
555
0
      return cmResultSuccess;
556
0
    } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
557
0
      if (m_pWelsTrace) {
558
0
        void* ctx = * ((void**)pOption);
559
0
        m_pWelsTrace->SetTraceCallbackContext (ctx);
560
0
      }
561
0
      return cmResultSuccess;
562
0
    } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
563
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
564
0
               "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
565
0
      return cmInitParaError;
566
0
    } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
567
0
      if (pOption) {
568
0
        if (pDecContext == NULL) return dsInitialOptExpected;
569
0
        pDecContext->pDecoderStatistics->iStatisticsLogInterval = (* ((unsigned int*)pOption));
570
0
        return cmResultSuccess;
571
0
      }
572
0
    } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
573
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
574
0
               "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
575
0
      return cmInitParaError;
576
0
    }
577
0
  }
578
0
  return cmInitParaError;
579
0
}
580
581
/*
582
 *  Get Option
583
 */
584
0
long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
585
0
  int iVal = 0;
586
0
  if (DECODER_OPTION_NUM_OF_THREADS == eOptID) {
587
0
    * ((int*)pOption) = m_iThreadCount;
588
0
    return cmResultSuccess;
589
0
  }
590
0
  PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
591
0
  if (pDecContext == NULL)
592
0
    return cmInitExpected;
593
594
0
  if (pOption == NULL)
595
0
    return cmInitParaError;
596
597
0
  if (DECODER_OPTION_END_OF_STREAM == eOptID) {
598
0
    iVal = pDecContext->bEndOfStreamFlag;
599
0
    * ((int*)pOption) = iVal;
600
0
    return cmResultSuccess;
601
0
  }
602
0
#ifdef LONG_TERM_REF
603
0
  else if (DECODER_OPTION_IDR_PIC_ID == eOptID) {
604
0
    iVal = pDecContext->uiCurIdrPicId;
605
0
    * ((int*)pOption) = iVal;
606
0
    return cmResultSuccess;
607
0
  } else if (DECODER_OPTION_FRAME_NUM == eOptID) {
608
0
    iVal = pDecContext->iFrameNum;
609
0
    * ((int*)pOption) = iVal;
610
0
    return cmResultSuccess;
611
0
  } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) {
612
0
    iVal = pDecContext->bCurAuContainLtrMarkSeFlag;
613
0
    * ((int*)pOption) = iVal;
614
0
    return cmResultSuccess;
615
0
  } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) {
616
0
    iVal = pDecContext->iFrameNumOfAuMarkedLtr;
617
0
    * ((int*)pOption) = iVal;
618
0
    return cmResultSuccess;
619
0
  }
620
0
#endif
621
0
  else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU
622
0
    iVal = pDecContext->iFeedbackVclNalInAu;
623
0
    * ((int*)pOption) = iVal;
624
0
    return cmResultSuccess;
625
0
  } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID
626
0
    iVal = pDecContext->iFeedbackTidInAu;
627
0
    * ((int*)pOption) = iVal;
628
0
    return cmResultSuccess;
629
0
  } else if (DECODER_OPTION_IS_REF_PIC == eOptID) {
630
0
    iVal = pDecContext->iFeedbackNalRefIdc;
631
0
    if (iVal > 0)
632
0
      iVal = 1;
633
0
    * ((int*)pOption) = iVal;
634
0
    return cmResultSuccess;
635
0
  } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) {
636
0
    iVal = (int)pDecContext->pParam->eEcActiveIdc;
637
0
    * ((int*)pOption) = iVal;
638
0
    return cmResultSuccess;
639
0
  } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
640
0
    SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
641
642
0
    memcpy (pDecoderStatistics, pDecContext->pDecoderStatistics, sizeof (SDecoderStatistics));
643
644
0
    if (pDecContext->pDecoderStatistics->uiDecodedFrameCount != 0) { //not original status
645
0
      pDecoderStatistics->fAverageFrameSpeedInMs = (float) (pDecContext->dDecTime) /
646
0
          (pDecContext->pDecoderStatistics->uiDecodedFrameCount);
647
0
      pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (pDecContext->dDecTime) /
648
0
          (pDecContext->pDecoderStatistics->uiDecodedFrameCount + pDecContext->pDecoderStatistics->uiFreezingIDRNum +
649
0
           pDecContext->pDecoderStatistics->uiFreezingNonIDRNum);
650
0
    }
651
0
    return cmResultSuccess;
652
0
  } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
653
0
    if (pOption) {
654
0
      iVal = pDecContext->pDecoderStatistics->iStatisticsLogInterval;
655
0
      * ((unsigned int*)pOption) = iVal;
656
0
      return cmResultSuccess;
657
0
    }
658
0
  } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
659
0
    PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
660
0
    memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
661
0
    if (!pDecContext->pSps) {
662
0
      return cmInitExpected;
663
0
    } else {
664
0
      pVuiSarInfo->uiSarWidth = pDecContext->pSps->sVui.uiSarWidth;
665
0
      pVuiSarInfo->uiSarHeight = pDecContext->pSps->sVui.uiSarHeight;
666
0
      pVuiSarInfo->bOverscanAppropriateFlag = pDecContext->pSps->sVui.bOverscanAppropriateFlag;
667
0
      return cmResultSuccess;
668
0
    }
669
0
  } else if (DECODER_OPTION_PROFILE == eOptID) {
670
0
    if (!pDecContext->pSps) {
671
0
      return cmInitExpected;
672
0
    }
673
0
    iVal = (int)pDecContext->pSps->uiProfileIdc;
674
0
    * ((int*)pOption) = iVal;
675
0
    return cmResultSuccess;
676
0
  } else if (DECODER_OPTION_LEVEL == eOptID) {
677
0
    if (!pDecContext->pSps) {
678
0
      return cmInitExpected;
679
0
    }
680
0
    iVal = (int)pDecContext->pSps->uiLevelIdc;
681
0
    * ((int*)pOption) = iVal;
682
0
    return cmResultSuccess;
683
0
  } else if (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER == eOptID) {
684
0
    for (int32_t activeThread = 0; activeThread < m_DecCtxActiveCount; ++activeThread) {
685
0
      WAIT_SEMAPHORE (&m_pDecThrCtxActive[activeThread]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
686
0
      RELEASE_SEMAPHORE (&m_pDecThrCtxActive[activeThread]->sThreadInfo.sIsIdle);
687
0
    }
688
0
    * ((int*)pOption) = m_sReoderingStatus.iNumOfPicts;
689
0
    return cmResultSuccess;
690
0
  }
691
692
0
  return cmInitParaError;
693
0
}
694
695
DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
696
    const int kiSrcLen,
697
    unsigned char** ppDst,
698
1
    SBufferInfo* pDstInfo) {
699
1
  int iRet = dsErrorFree;
700
1
  if (m_iThreadCount >= 1) {
701
0
    SET_EVENT (&m_sReleaseBufferEvent);
702
0
    iRet = ThreadDecodeFrameInternal (kpSrc, kiSrcLen, ppDst, pDstInfo);
703
0
    if (m_sReoderingStatus.iNumOfPicts) {
704
0
      WAIT_EVENT (&m_sBufferingEvent, WELS_DEC_THREAD_WAIT_INFINITE);
705
0
      RESET_EVENT (&m_sBufferingEvent);
706
0
      RESET_EVENT (&m_sReleaseBufferEvent);
707
0
      if (!m_sReoderingStatus.bHasBSlice) {
708
0
        if (m_sReoderingStatus.iNumOfPicts > 1) {
709
0
          ReleaseBufferedReadyPictureNoReorder (NULL, ppDst, pDstInfo);
710
0
        }
711
0
      }
712
0
      else {
713
0
        ReleaseBufferedReadyPictureReorder (NULL, ppDst, pDstInfo);
714
0
      }
715
0
    }
716
0
    return (DECODING_STATE)iRet;
717
0
  }
718
  //SBufferInfo sTmpBufferInfo;
719
  //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
720
1
  iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
721
  //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
722
  //ppTmpDst[0] = ppDst[0];
723
  //ppTmpDst[1] = ppDst[1];
724
  //ppTmpDst[2] = ppDst[2];
725
1
  iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
726
  //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
727
  //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
728
  //ppDst[0] = ppTmpDst[0];
729
  //ppDst[1] = ppTmpDst[1];
730
  //ppDst[2] = ppTmpDst[2];
731
  //}
732
1
  return (DECODING_STATE)iRet;
733
1
}
734
735
DECODING_STATE CWelsDecoder::DecodeFrame2WithCtx (PWelsDecoderContext pDecContext, const unsigned char* kpSrc,
736
    const int kiSrcLen,
737
    unsigned char** ppDst,
738
2
    SBufferInfo* pDstInfo) {
739
2
  if (pDecContext == NULL || pDecContext->pParam == NULL) {
740
0
    if (m_pWelsTrace != NULL) {
741
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
742
0
    }
743
0
    return dsInitialOptExpected;
744
0
  }
745
746
2
  if (pDecContext->pParam->bParseOnly) {
747
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
748
0
    pDecContext->iErrorCode |= dsInvalidArgument;
749
0
    return dsInvalidArgument;
750
0
  }
751
2
  if (CheckBsBuffer (pDecContext, kiSrcLen)) {
752
0
    if (ResetDecoder(pDecContext)) {
753
0
      if (pDstInfo) pDstInfo->iBufferStatus = 0;
754
0
      return dsOutOfMemory;
755
0
    }
756
0
    return dsErrorFree;
757
0
  }
758
2
  if (kiSrcLen > 0 && kpSrc != NULL) {
759
#ifdef OUTPUT_BIT_STREAM
760
    if (m_pFBS) {
761
      WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
762
      WelsFflush (m_pFBS);
763
    }
764
    if (m_pFBSSize) {
765
      WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
766
      WelsFflush (m_pFBSSize);
767
    }
768
#endif//OUTPUT_BIT_STREAM
769
1
    pDecContext->bEndOfStreamFlag = false;
770
1
    if (GetThreadCount (pDecContext) <= 0) {
771
1
      pDecContext->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
772
1
    }
773
1
  } else {
774
    //For application MODE, the error detection should be added for safe.
775
    //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
776
1
    pDecContext->bEndOfStreamFlag = true;
777
1
    pDecContext->bInstantDecFlag = true;
778
1
  }
779
780
2
  int64_t iStart, iEnd;
781
2
  iStart = WelsTime();
782
783
2
  if (GetThreadCount (pDecContext) <= 1) {
784
2
    ppDst[0] = ppDst[1] = ppDst[2] = NULL;
785
2
  }
786
2
  pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
787
2
  pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
788
2
  unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
789
2
  if (GetThreadCount (pDecContext) <= 1) {
790
2
    memset (pDstInfo, 0, sizeof (SBufferInfo));
791
2
  }
792
2
  pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
793
2
#ifdef LONG_TERM_REF
794
2
  pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
795
2
  pDecContext->bCurAuContainLtrMarkSeFlag = false;
796
2
  pDecContext->iFrameNumOfAuMarkedLtr = 0;
797
2
  pDecContext->iFrameNum = -1; //initialize
798
2
#endif
799
800
2
  if (GetThreadCount (pDecContext) >= 1) {
801
0
    WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE);
802
0
  }
803
804
2
  pDecContext->iFeedbackTidInAu = -1; //initialize
805
2
  pDecContext->iFeedbackNalRefIdc = -1; //initialize
806
2
  if (pDstInfo) {
807
2
    pDstInfo->uiOutYuvTimeStamp = 0;
808
2
    pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
809
2
  } else {
810
0
    pDecContext->uiTimeStamp = 0;
811
0
  }
812
2
  WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, ppDst,
813
2
                pDstInfo, NULL); //iErrorCode has been modified in this function
814
2
  pDecContext->bInstantDecFlag = false; //reset no-delay flag
815
2
  if (pDecContext->iErrorCode) {
816
1
    EWelsNalUnitType eNalType =
817
1
      NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
818
819
1
    eNalType = pDecContext->sCurNalHead.eNalUnitType;
820
1
    if (pDecContext->iErrorCode & dsOutOfMemory) {
821
0
      if (ResetDecoder (pDecContext)) {
822
0
        if (pDstInfo) pDstInfo->iBufferStatus = 0;
823
0
        return dsOutOfMemory;
824
0
      }
825
0
      return dsErrorFree;
826
0
    }
827
1
    if (pDecContext->iErrorCode & dsRefListNullPtrs) {
828
0
      if (ResetDecoder (pDecContext)) {
829
0
        if (pDstInfo) pDstInfo->iBufferStatus = 0;
830
0
        return dsRefListNullPtrs;
831
0
      }
832
0
      return dsErrorFree;
833
0
    }
834
    //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
835
1
    if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
836
1
        (VIDEO_BITSTREAM_AVC == pDecContext->eVideoType)) {
837
1
      if (pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
838
1
#ifdef LONG_TERM_REF
839
1
        pDecContext->bParamSetsLostFlag = true;
840
#else
841
        pDecContext->bReferenceLostAtT0Flag = true;
842
#endif
843
1
      }
844
1
    }
845
846
1
    if (pDecContext->bPrintFrameErrorTraceFlag) {
847
1
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
848
1
               pDecContext->iErrorCode);
849
1
      pDecContext->bPrintFrameErrorTraceFlag = false;
850
1
    } else {
851
0
      pDecContext->iIgnoredErrorInfoPacketCount++;
852
0
      if (pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
853
0
        WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
854
0
        pDecContext->iIgnoredErrorInfoPacketCount = 0;
855
0
      }
856
0
    }
857
1
    if ((pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
858
      //TODO after dec status updated
859
0
      pDecContext->iErrorCode |= dsDataErrorConcealed;
860
861
0
      pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
862
0
      if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
863
0
        ResetDecStatNums (pDecContext->pDecoderStatistics);
864
0
        pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
865
0
      }
866
0
      int32_t iMbConcealedNum = pDecContext->iMbEcedNum + pDecContext->iMbEcedPropNum;
867
0
      pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->iMbNum == 0 ?
868
0
          (pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
869
0
                pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
870
0
                      iMbConcealedNum * 100) / pDecContext->iMbNum));
871
0
      pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->iMbNum == 0 ?
872
0
          (pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
873
0
                pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
874
0
                      pDecContext->iMbEcedPropNum * 100) / pDecContext->iMbNum));
875
0
      pDecContext->pDecoderStatistics->uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
876
0
      pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
877
0
          pDecContext->pDecoderStatistics->uiAvgEcRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
878
0
      pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
879
0
          pDecContext->pDecoderStatistics->uiAvgEcPropRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
880
0
    }
881
1
    iEnd = WelsTime();
882
1
    pDecContext->dDecTime += (iEnd - iStart) / 1e3;
883
884
1
    OutputStatisticsLog (*pDecContext->pDecoderStatistics);
885
1
    if (GetThreadCount (pDecContext) >= 1) {
886
0
      BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
887
0
      SET_EVENT (&m_sBufferingEvent);
888
1
    } else {
889
1
      ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
890
1
    }
891
892
1
    return (DECODING_STATE)pDecContext->iErrorCode;
893
1
  }
894
  // else Error free, the current codec works well
895
896
1
  if (pDstInfo->iBufferStatus == 1) {
897
898
0
    pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
899
0
    if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
900
0
      ResetDecStatNums (pDecContext->pDecoderStatistics);
901
0
      pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
902
0
    }
903
904
0
    OutputStatisticsLog (*pDecContext->pDecoderStatistics);
905
0
  }
906
1
  iEnd = WelsTime();
907
1
  pDecContext->dDecTime += (iEnd - iStart) / 1e3;
908
909
1
  if (GetThreadCount (pDecContext) >= 1) {
910
0
    BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
911
0
    SET_EVENT (&m_sBufferingEvent);
912
1
  } else {
913
1
    ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
914
1
  }
915
1
  return dsErrorFree;
916
2
}
917
918
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
919
    const int kiSrcLen,
920
    unsigned char** ppDst,
921
2
    SBufferInfo* pDstInfo) {
922
2
  PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
923
2
  return DecodeFrame2WithCtx (pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo);
924
2
}
925
926
DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
927
0
    SBufferInfo* pDstInfo) {
928
0
  bool bEndOfStreamFlag = true;
929
0
  if (m_iThreadCount <= 1) {
930
0
    for (int32_t j = 0; j < m_iCtxCount; ++j) {
931
0
      if (!m_pDecThrCtx[j].pCtx->bEndOfStreamFlag) {
932
0
        bEndOfStreamFlag = false;
933
0
      }
934
0
    }
935
0
  }
936
0
  if (bEndOfStreamFlag && m_sReoderingStatus.iNumOfPicts > 0) {
937
0
    if (!m_sReoderingStatus.bHasBSlice) {
938
0
      ReleaseBufferedReadyPictureNoReorder (NULL, ppDst, pDstInfo);
939
0
    }
940
0
    else {
941
0
      ReleaseBufferedReadyPictureReorder (NULL, ppDst, pDstInfo, true);
942
0
    }
943
0
  }
944
0
  return dsErrorFree;
945
0
}
946
947
1
void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
948
1
  if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
949
0
      && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
950
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
951
0
             "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
952
0
              uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
953
0
              uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
954
0
              uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
955
0
              iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
956
0
              uiProfile=%d, uiLevel=%d, \
957
0
              iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
958
0
             sDecoderStatistics.uiWidth,
959
0
             sDecoderStatistics.uiHeight,
960
0
             sDecoderStatistics.fAverageFrameSpeedInMs,
961
0
             sDecoderStatistics.fActualAverageFrameSpeedInMs,
962
963
0
             sDecoderStatistics.uiDecodedFrameCount,
964
0
             sDecoderStatistics.uiResolutionChangeTimes,
965
0
             sDecoderStatistics.uiIDRCorrectNum,
966
967
0
             sDecoderStatistics.uiAvgEcRatio,
968
0
             sDecoderStatistics.uiAvgEcPropRatio,
969
0
             sDecoderStatistics.uiEcIDRNum,
970
0
             sDecoderStatistics.uiEcFrameNum,
971
972
0
             sDecoderStatistics.uiIDRLostNum,
973
0
             sDecoderStatistics.uiFreezingIDRNum,
974
0
             sDecoderStatistics.uiFreezingNonIDRNum,
975
0
             sDecoderStatistics.iAvgLumaQp,
976
977
0
             sDecoderStatistics.iSpsReportErrorNum,
978
0
             sDecoderStatistics.iSubSpsReportErrorNum,
979
0
             sDecoderStatistics.iPpsReportErrorNum,
980
0
             sDecoderStatistics.iSpsNoExistNalNum,
981
0
             sDecoderStatistics.iSubSpsNoExistNalNum,
982
0
             sDecoderStatistics.iPpsNoExistNalNum,
983
984
0
             sDecoderStatistics.uiProfile,
985
0
             sDecoderStatistics.uiLevel,
986
987
0
             sDecoderStatistics.iCurrentActiveSpsId,
988
0
             sDecoderStatistics.iCurrentActivePpsId);
989
0
  }
990
1
}
991
992
void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst,
993
0
    SBufferInfo* pDstInfo) {
994
0
  if (pDstInfo->iBufferStatus == 0) {
995
0
    return;
996
0
  }
997
0
  m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83;
998
0
  if (!m_bIsBaseline) {
999
0
    if (pCtx->pSliceHeader->eSliceType == B_SLICE) {
1000
0
      m_sReoderingStatus.bHasBSlice = true;
1001
0
    }
1002
0
  }
1003
0
  for (int32_t i = 0; i < 16; ++i) {
1004
0
    if (m_sPictInfoList[i].iPOC == IMinInt32) {
1005
0
      memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
1006
0
      m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb;
1007
0
      m_sPictInfoList[i].iSeqNum = pCtx->iSeqNum;
1008
0
      m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp;
1009
0
      if (pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb != NULL) {
1010
0
        m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
1011
0
        if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount;
1012
0
      }
1013
0
      m_iLastBufferedIdx = i;
1014
0
      pDstInfo->iBufferStatus = 0;
1015
0
      ++m_sReoderingStatus.iNumOfPicts;
1016
0
      if (i > m_sReoderingStatus.iLargestBufferedPicIndex) {
1017
0
        m_sReoderingStatus.iLargestBufferedPicIndex = i;
1018
0
      }
1019
0
      break;
1020
0
    }
1021
0
  }
1022
0
}
1023
1024
void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx, unsigned char** ppDst,
1025
0
    SBufferInfo* pDstInfo, bool isFlush) {
1026
0
  PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1027
0
  if (pCtx == NULL && m_iThreadCount <= 1) {
1028
0
    pCtx = m_pDecThrCtx[0].pCtx;
1029
0
  }
1030
0
  if (m_sReoderingStatus.iNumOfPicts > 0) {
1031
0
    m_sReoderingStatus.iMinPOC = IMinInt32;
1032
0
    int32_t firstValidIdx = -1;
1033
0
    for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1034
0
      if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
1035
0
        m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1036
0
        m_sReoderingStatus.iMinSeqNum = m_sPictInfoList[i].iSeqNum;
1037
0
        m_sReoderingStatus.iPictInfoIndex = i;
1038
0
        firstValidIdx = i;
1039
0
        break;
1040
0
      }
1041
0
    }
1042
0
    for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1043
0
      if (i == firstValidIdx) continue;
1044
0
      if (m_sPictInfoList[i].iPOC > IMinInt32
1045
0
          && ((m_sPictInfoList[i].iSeqNum == m_sReoderingStatus.iMinSeqNum) ? (m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) : (m_sPictInfoList[i].iSeqNum - m_sReoderingStatus.iMinSeqNum < 0))) {
1046
0
        m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1047
0
        m_sReoderingStatus.iMinSeqNum = m_sPictInfoList[i].iSeqNum;
1048
0
        m_sReoderingStatus.iPictInfoIndex = i;
1049
0
      }
1050
0
    }
1051
0
  }
1052
0
  if (m_sReoderingStatus.iMinPOC > IMinInt32) {
1053
0
    bool isReady = true;
1054
0
    if (!isFlush) {
1055
0
      int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
1056
0
      int32_t iLastSeqNum = pCtx != NULL ? pCtx->iSeqNum : m_sPictInfoList[m_iLastBufferedIdx].iSeqNum;
1057
0
      isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
1058
0
        && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
1059
0
        || m_sReoderingStatus.iMinPOC < iLastPOC
1060
0
        || m_sReoderingStatus.iMinSeqNum - iLastSeqNum < 0;
1061
0
    }
1062
0
    if (isReady) {
1063
0
      m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1064
0
      m_sReoderingStatus.iLastWrittenSeqNum = m_sReoderingStatus.iMinSeqNum;
1065
#if defined (_DEBUG)
1066
#ifdef _MOTION_VECTOR_DUMP_
1067
      fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1068
               m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1069
#endif
1070
#endif
1071
0
      memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1072
0
      ppDst[0] = pDstInfo->pDst[0];
1073
0
      ppDst[1] = pDstInfo->pDst[1];
1074
0
      ppDst[2] = pDstInfo->pDst[2];
1075
0
      m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1076
0
      int32_t iPicBuffIdx = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx;
1077
0
      if (pPicBuff != NULL) {
1078
0
        if (iPicBuffIdx >= 0 && iPicBuffIdx < pPicBuff->iCapacity)
1079
0
        {
1080
0
            PPicture pPic = pPicBuff->ppPic[iPicBuffIdx];
1081
0
            --pPic->iRefCount;
1082
0
            if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
1083
0
              pPic->pSetUnRef(pPic);
1084
0
        }
1085
0
      }
1086
0
      m_sReoderingStatus.iMinPOC = IMinInt32;
1087
0
      --m_sReoderingStatus.iNumOfPicts;
1088
0
    }
1089
0
  }
1090
0
}
1091
1092
//if there is no b-frame, no ordering based on values of POCs is necessary.
1093
//The function is added to force to avoid picture reordering because some h.264 streams do not follow H.264 POC specifications. 
1094
void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo)
1095
0
{
1096
0
  int32_t firstValidIdx = -1;
1097
0
  uint32_t uiDecodingTimeStamp = 0;
1098
0
  for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1099
0
    if (m_sPictInfoList[i].iPOC != IMinInt32) {
1100
0
      uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1101
0
      m_sReoderingStatus.iPictInfoIndex = i;
1102
0
      firstValidIdx = i;
1103
0
      break;
1104
0
    }
1105
0
  }
1106
0
  for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1107
0
    if (i == firstValidIdx) continue;
1108
0
    if (m_sPictInfoList[i].iPOC != IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
1109
0
      uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1110
0
      m_sReoderingStatus.iPictInfoIndex = i;
1111
0
    }
1112
0
  }
1113
0
  if (uiDecodingTimeStamp > 0) {
1114
#if defined (_DEBUG)
1115
#ifdef _MOTION_VECTOR_DUMP_
1116
    fprintf(stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC,
1117
      uiDecodingTimeStamp);
1118
#endif
1119
#endif
1120
0
    m_sReoderingStatus.iLastWrittenPOC = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC;
1121
0
    m_sReoderingStatus.iLastWrittenSeqNum = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iSeqNum;
1122
0
    memcpy(pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof(SBufferInfo));
1123
0
    ppDst[0] = pDstInfo->pDst[0];
1124
0
    ppDst[1] = pDstInfo->pDst[1];
1125
0
    ppDst[2] = pDstInfo->pDst[2];
1126
0
    m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1127
0
    if (pCtx || m_pPicBuff) {
1128
0
      PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1129
0
      PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1130
0
      --pPic->iRefCount;
1131
0
      if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
1132
0
        pPic->pSetUnRef(pPic);
1133
0
    }
1134
0
    --m_sReoderingStatus.iNumOfPicts;
1135
0
  }
1136
0
  return;
1137
0
}
1138
1139
DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay(PWelsDecoderContext pDecContext, unsigned char** ppDst,
1140
2
  SBufferInfo* pDstInfo) {
1141
2
  DECODING_STATE iRet = dsErrorFree;
1142
2
  if (pDecContext->pSps != NULL) {
1143
0
    m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
1144
0
    if (!m_bIsBaseline) {
1145
0
      if (pDstInfo->iBufferStatus == 1) {
1146
0
        if (pDecContext->pSliceHeader->eSliceType == B_SLICE &&
1147
0
            ((pDecContext->iSeqNum == m_sReoderingStatus.iLastWrittenSeqNum) ?
1148
0
              (pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) :
1149
0
              (pDecContext->iSeqNum - m_sReoderingStatus.iLastWrittenSeqNum == 1 && pDecContext->pSliceHeader->iPicOrderCntLsb == 0))) {
1150
0
          m_sReoderingStatus.iLastWrittenPOC = pDecContext->pSliceHeader->iPicOrderCntLsb;
1151
0
          m_sReoderingStatus.iLastWrittenSeqNum = pDecContext->iSeqNum;
1152
          //issue #3478, use b-slice type to determine correct picture order as the first priority as POC order is not as reliable as based on b-slice
1153
0
          ppDst[0] = pDstInfo->pDst[0];
1154
0
          ppDst[1] = pDstInfo->pDst[1];
1155
0
          ppDst[2] = pDstInfo->pDst[2];
1156
#if defined (_DEBUG)
1157
#ifdef _MOTION_VECTOR_DUMP_
1158
          fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", pDecContext->pSliceHeader->iPicOrderCntLsb,
1159
             pDecContext->uiDecodingTimeStamp);
1160
#endif
1161
#endif
1162
0
          return iRet;
1163
0
        }
1164
0
        BufferingReadyPicture(pDecContext, ppDst, pDstInfo);
1165
0
        if (!m_sReoderingStatus.bHasBSlice && m_sReoderingStatus.iNumOfPicts > 1) {
1166
0
          ReleaseBufferedReadyPictureNoReorder (pDecContext, ppDst, pDstInfo);
1167
0
        }
1168
0
        else {
1169
0
          ReleaseBufferedReadyPictureReorder (pDecContext, ppDst, pDstInfo);
1170
0
        }
1171
0
      }
1172
0
    }
1173
0
  }
1174
2
  return iRet;
1175
2
}
1176
1177
0
DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1178
0
  PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1179
1180
0
  if (pDecContext == NULL || pDecContext->pParam == NULL) {
1181
0
    if (m_pWelsTrace != NULL) {
1182
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1183
0
    }
1184
0
    return dsInitialOptExpected;
1185
0
  }
1186
1187
0
  if (!pDecContext->pParam->bParseOnly) {
1188
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1189
0
    pDecContext->iErrorCode |= dsInvalidArgument;
1190
0
    return dsInvalidArgument;
1191
0
  }
1192
0
  int64_t iEnd, iStart = WelsTime();
1193
0
  if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1194
0
    if (ResetDecoder (pDecContext))
1195
0
      return dsOutOfMemory;
1196
1197
0
    return dsErrorFree;
1198
0
  }
1199
0
  if (kiSrcLen > 0 && kpSrc != NULL) {
1200
#ifdef OUTPUT_BITSTREAM
1201
    if (m_pFBS) {
1202
      WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
1203
      WelsFflush (m_pFBS);
1204
    }
1205
#endif//OUTPUT_BIT_STREAM
1206
0
    pDecContext->bEndOfStreamFlag = false;
1207
0
  } else {
1208
    //For application MODE, the error detection should be added for safe.
1209
    //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
1210
0
    pDecContext->bEndOfStreamFlag = true;
1211
0
    pDecContext->bInstantDecFlag = true;
1212
0
  }
1213
1214
0
  pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1215
0
  pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1216
0
  pDecContext->iFeedbackNalRefIdc = -1; //initialize
1217
0
  if (!pDecContext->bFramePending) { //frame complete
1218
0
    pDecContext->pParserBsInfo->iNalNum = 0;
1219
0
    memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1220
0
  }
1221
0
  pDstInfo->iNalNum = 0;
1222
0
  pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1223
0
  if (pDstInfo) {
1224
0
    pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1225
0
    pDstInfo->uiOutBsTimeStamp = 0;
1226
0
  } else {
1227
0
    pDecContext->uiTimeStamp = 0;
1228
0
  }
1229
0
  WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1230
0
  if (pDecContext->iErrorCode & dsOutOfMemory) {
1231
0
    if (ResetDecoder (pDecContext))
1232
0
      return dsOutOfMemory;
1233
0
    return dsErrorFree;
1234
0
  }
1235
1236
0
  if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1237
0
    memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1238
1239
0
    if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1240
0
      pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1241
0
      if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1242
0
        ResetDecStatNums (pDecContext->pDecoderStatistics);
1243
0
        pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1244
0
      }
1245
0
    }
1246
0
  }
1247
1248
0
  pDecContext->bInstantDecFlag = false; //reset no-delay flag
1249
1250
0
  if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1251
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1252
0
    pDecContext->bPrintFrameErrorTraceFlag = false;
1253
0
  }
1254
0
  iEnd = WelsTime();
1255
0
  pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1256
0
  return (DECODING_STATE)pDecContext->iErrorCode;
1257
0
}
1258
1259
DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1260
    const int kiSrcLen,
1261
    unsigned char** ppDst,
1262
    int* pStride,
1263
    int& iWidth,
1264
0
    int& iHeight) {
1265
0
  DECODING_STATE eDecState = dsErrorFree;
1266
0
  SBufferInfo    DstInfo;
1267
1268
0
  memset (&DstInfo, 0, sizeof (SBufferInfo));
1269
0
  DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1270
0
  DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1271
0
  DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1272
0
  DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1273
1274
0
  eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1275
0
  if (eDecState == dsErrorFree) {
1276
0
    pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1277
0
    pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1278
0
    iWidth     = DstInfo.UsrData.sSystemBuffer.iWidth;
1279
0
    iHeight    = DstInfo.UsrData.sSystemBuffer.iHeight;
1280
0
  }
1281
1282
0
  return eDecState;
1283
0
}
1284
1285
DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
1286
    const int kiSrcLen,
1287
    unsigned char* pDst,
1288
    int iDstStride,
1289
    int& iDstLen,
1290
    int& iWidth,
1291
    int& iHeight,
1292
0
    int& iColorFormat) {
1293
0
  DECODING_STATE state = dsErrorFree;
1294
1295
0
  return state;
1296
0
}
1297
1298
0
DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1299
0
  sThreadCtx.pCtx->bHasNewSps = false;
1300
0
  sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1301
0
  sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1302
0
  sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1303
0
  bool bPicBuffChanged = false;
1304
0
  if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1305
0
    CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1306
0
    sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1307
0
    if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1308
0
      bPicBuffChanged = true;
1309
0
      sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1310
0
      sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1311
0
      sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1312
0
      sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1313
0
    }
1314
0
  }
1315
1316
  //if threadCount > 1, then each thread must contain exact one complete frame.
1317
0
  if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1318
0
    sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0;
1319
0
    sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0;
1320
0
  }
1321
1322
0
  int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1323
0
                                      &sThreadCtx.sDstInfo);
1324
1325
0
  int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1326
0
  if (ERR_NONE != iErr) {
1327
0
    return (DECODING_STATE) (iRet | iErr);
1328
0
  }
1329
0
  if (sThreadCtx.pCtx->bNewSeqBegin) {
1330
0
    m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1331
0
  } else if (bPicBuffChanged) {
1332
0
    InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1333
0
  }
1334
0
  if (!sThreadCtx.pCtx->bNewSeqBegin && m_pLastDecThrCtx != NULL) {
1335
0
    sThreadCtx.pCtx->sFrameCrop = m_pLastDecThrCtx->pCtx->pSps->sFrameCrop;
1336
0
  }
1337
0
  m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1338
0
  m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1339
0
  return (DECODING_STATE)iErr;
1340
0
}
1341
/*
1342
* Run decoding picture in separate thread.
1343
*/
1344
1345
int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1346
0
    SBufferInfo* pDstInfo) {
1347
0
  int state = dsErrorFree;
1348
0
  int32_t i, j;
1349
0
  int32_t signal = 0;
1350
1351
  //serial using of threads
1352
0
  if (m_DecCtxActiveCount < m_iThreadCount) {
1353
0
    signal = m_DecCtxActiveCount;
1354
0
  } else {
1355
0
    signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1356
0
  }
1357
1358
0
  WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1359
1360
0
  for (i = 0; i < m_DecCtxActiveCount; ++i) {
1361
0
    if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1362
0
      m_pDecThrCtxActive[i] = NULL;
1363
0
      for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1364
0
        m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1365
0
        m_pDecThrCtxActive[j + 1] = NULL;
1366
0
      }
1367
0
      --m_DecCtxActiveCount;
1368
0
      break;
1369
0
    }
1370
0
  }
1371
1372
0
  m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1373
0
  if (m_pLastDecThrCtx != NULL) {
1374
0
    m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1375
0
  }
1376
0
  m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1377
0
  m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1378
0
  m_pDecThrCtx[signal].ppDst = ppDst;
1379
0
  memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1380
1381
0
  ParseAccessUnit (m_pDecThrCtx[signal]);
1382
0
  if (m_iThreadCount > 1) {
1383
0
    m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1384
0
  }
1385
0
  m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1386
0
  RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1387
1388
  // wait early picture
1389
0
  if (m_DecCtxActiveCount >= m_iThreadCount) {
1390
0
    WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1391
0
    RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1392
0
  }
1393
0
  return state;
1394
0
}
1395
1396
} // namespace WelsDec
1397
1398
1399
using namespace WelsDec;
1400
/*
1401
*       WelsGetDecoderCapability
1402
*       @return: DecCapability information
1403
*/
1404
0
int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1405
0
  memset (pDecCapability, 0, sizeof (SDecoderCapability));
1406
0
  pDecCapability->iProfileIdc = 66; //Baseline
1407
0
  pDecCapability->iProfileIop = 0xE0; //11100000b
1408
0
  pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1409
0
  pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1410
0
  pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1411
0
  pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1412
0
  pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1413
0
  pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1414
0
  pDecCapability->bRedPicCap = 0; //not support redundant pic
1415
1416
0
  return ERR_NONE;
1417
0
}
1418
/* WINAPI is indeed in prefix due to sync to application layer callings!! */
1419
1420
/*
1421
*   WelsCreateDecoder
1422
*   @return:    success in return 0, otherwise failed.
1423
*/
1424
33
long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1425
1426
33
  if (NULL == ppDecoder) {
1427
0
    return ERR_INVALID_PARAMETERS;
1428
0
  }
1429
1430
33
  *ppDecoder = new CWelsDecoder();
1431
1432
33
  if (NULL == *ppDecoder) {
1433
0
    return ERR_MALLOC_FAILED;
1434
0
  }
1435
1436
33
  return ERR_NONE;
1437
33
}
1438
1439
/*
1440
*   WelsDestroyDecoder
1441
*/
1442
33
void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1443
33
  if (NULL != pDecoder) {
1444
33
    delete (CWelsDecoder*)pDecoder;
1445
33
  }
1446
33
}