Coverage Report

Created: 2026-09-02 06:43

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