Coverage Report

Created: 2026-08-31 06:22

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