Coverage Report

Created: 2026-09-14 06:44

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
768
  : m_pWelsTrace (NULL),
138
768
    m_uiDecodeTimeStamp (0),
139
768
    m_bIsBaseline (false),
140
768
    m_iCpuCount (1),
141
768
    m_iThreadCount (0),
142
768
    m_iCtxCount (1),
143
768
    m_pPicBuff (NULL),
144
768
    m_bParamSetsLostFlag (false),
145
768
    m_bFreezeOutput (false),
146
768
    m_DecCtxActiveCount (0),
147
768
    m_pDecThrCtx (NULL),
148
768
    m_pLastDecThrCtx (NULL),
149
768
    m_iLastBufferedIdx (0),
150
768
    m_iStreamSeqNum (0) {
151
768
  memset (&m_sReoderingStatus, 0, sizeof (m_sReoderingStatus));
152
768
  m_sReoderingStatus.iMinPOC = IMinInt32;
153
13.0k
  for (int32_t i = 0; i < 16; ++i) {
154
12.2k
    memset (&m_sPictInfoList[i], 0, sizeof (m_sPictInfoList[i]));
155
12.2k
    m_sPictInfoList[i].iPOC = IMinInt32;
156
12.2k
  }
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
768
  m_pWelsTrace = new welsCodecTrace();
171
768
  if (m_pWelsTrace != NULL) {
172
768
    m_pWelsTrace->SetCodecInstance (this);
173
768
    m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
174
175
768
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
176
768
  }
177
178
768
  ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
179
180
768
  m_iCpuCount = GetCPUCount();
181
768
  if (m_iCpuCount > WELS_DEC_MAX_NUM_CPU) {
182
768
    m_iCpuCount = WELS_DEC_MAX_NUM_CPU;
183
768
  }
184
185
768
  m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];
186
768
  memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);
187
13.0k
  for (int32_t i = 0; i < WELS_DEC_MAX_NUM_CPU; ++i) {
188
12.2k
    m_pDecThrCtxActive[i] = NULL;
189
12.2k
  }
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
768
}
232
233
/***************************************************************************
234
*   Description:
235
*       class CWelsDecoder destructor function, destroy allocced memory
236
*
237
*   Input parameters: none
238
*
239
*   return: none
240
***************************************************************************/
241
768
CWelsDecoder::~CWelsDecoder() {
242
768
  if (m_pWelsTrace != NULL) {
243
768
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
244
768
  }
245
768
  CloseDecoderThreads();
246
768
  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
768
  if (m_pWelsTrace != NULL) {
260
768
    delete m_pWelsTrace;
261
768
    m_pWelsTrace = NULL;
262
768
  }
263
768
  if (m_pDecThrCtx != NULL) {
264
768
    delete[] m_pDecThrCtx;
265
768
    m_pDecThrCtx = NULL;
266
768
  }
267
768
}
268
269
768
long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
270
768
  int iRet = ERR_NONE;
271
768
  if (m_pWelsTrace == NULL) {
272
0
    return cmMallocMemeError;
273
0
  }
274
275
768
  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
768
  iRet = InitDecoder (pParam);
282
768
  if (iRet)
283
0
    return iRet;
284
285
768
  return cmResultSuccess;
286
768
}
287
288
768
long CWelsDecoder::Uninitialize() {
289
768
  UninitDecoder();
290
291
768
  return ERR_NONE;
292
768
}
293
294
2.30k
void CWelsDecoder::UninitDecoder (void) {
295
4.60k
  for (int32_t i = 0; i < m_iCtxCount; ++i) {
296
2.30k
    if (m_pDecThrCtx[i].pCtx != NULL) {
297
768
      if (i > 0) {
298
0
        WelsResetRefPicWithoutUnRef (m_pDecThrCtx[i].pCtx);
299
0
      }
300
768
      UninitDecoderCtx (m_pDecThrCtx[i].pCtx);
301
768
    }
302
2.30k
  }
303
2.30k
}
304
305
768
void CWelsDecoder::OpenDecoderThreads() {
306
768
  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
768
}
335
768
void CWelsDecoder::CloseDecoderThreads() {
336
768
  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
768
}
355
356
1.53k
void CWelsDecoder::UninitDecoderCtx (PWelsDecoderContext& pCtx) {
357
1.53k
  if (pCtx != NULL) {
358
359
768
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoderCtx(), openh264 codec version = %s.",
360
768
             VERSION_NUMBER);
361
362
768
    WelsEndDecoder (pCtx);
363
364
768
    if (pCtx->pMemAlign != NULL) {
365
768
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
366
768
               "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
367
768
               pCtx->pMemAlign->WelsGetMemoryUsage());
368
768
      delete pCtx->pMemAlign;
369
768
      pCtx->pMemAlign = NULL;
370
768
    }
371
372
768
    if (NULL != pCtx) {
373
768
      WelsFree (pCtx, "m_pDecContext");
374
375
768
      pCtx = NULL;
376
768
    }
377
768
    if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = NULL;
378
768
  }
379
1.53k
}
380
381
// the return value of this function is not suitable, it need report failure info to upper layer.
382
768
int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
383
384
768
  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
385
768
           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
386
768
           VERSION_NUMBER, (int32_t)pParam->bParseOnly);
387
768
  if (m_iThreadCount >= 1 && pParam->bParseOnly) {
388
0
    m_iThreadCount = 0;
389
0
  }
390
768
  OpenDecoderThreads();
391
  //reset decoder context
392
768
  memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics));
393
768
  memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo));
394
768
  memset (&m_sVlcTable, 0, sizeof (SVlcTable));
395
768
  UninitDecoder();
396
768
  WelsDecoderLastDecPicInfoDefaults (m_sLastDecPicInfo);
397
1.53k
  for (int32_t i = 0; i < m_iCtxCount; ++i) {
398
768
    InitDecoderCtx (m_pDecThrCtx[i].pCtx, pParam);
399
768
    if (m_iThreadCount >= 1) {
400
0
      m_pDecThrCtx[i].pCtx->pThreadCtx = &m_pDecThrCtx[i];
401
0
    }
402
768
  }
403
768
  m_bParamSetsLostFlag = false;
404
768
  m_bFreezeOutput = false;
405
768
  return cmResultSuccess;
406
768
}
407
408
// the return value of this function is not suitable, it need report failure info to upper layer.
409
768
int32_t CWelsDecoder::InitDecoderCtx (PWelsDecoderContext& pCtx, const SDecodingParam* pParam) {
410
411
768
  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
412
768
           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
413
768
           VERSION_NUMBER, (int32_t)pParam->bParseOnly);
414
415
  //reset decoder context
416
768
  UninitDecoderCtx (pCtx);
417
768
  pCtx = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
418
768
  if (NULL == pCtx)
419
0
    return cmMallocMemeError;
420
768
  int32_t iCacheLineSize = 16;   // on chip cache line size in byte
421
768
  pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);
422
768
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pMemAlign), UninitDecoderCtx (pCtx))
423
768
  if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = pCtx;
424
  //fill in default value into context
425
768
  pCtx->pLastDecPicInfo = &m_sLastDecPicInfo;
426
768
  pCtx->pDecoderStatistics = &m_sDecoderStatistics;
427
768
  pCtx->pVlcTable = &m_sVlcTable;
428
768
  pCtx->pPictInfoList = m_sPictInfoList;
429
768
  pCtx->pPictReoderingStatus = &m_sReoderingStatus;
430
768
  pCtx->pCsDecoder = &m_csDecoder;
431
768
  pCtx->pStreamSeqNum = &m_iStreamSeqNum;
432
768
  WelsDecoderDefaults (pCtx, &m_pWelsTrace->m_sLogCtx);
433
768
  WelsDecoderSpsPpsDefaults (pCtx->sSpsPpsCtx);
434
  //check param and update decoder context
435
768
  pCtx->pParam = (SDecodingParam*)pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
436
768
                 "SDecodingParam");
437
768
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoderCtx (pCtx));
438
768
  int32_t iRet = DecoderConfigParam (pCtx, pParam);
439
768
  WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
440
441
  //init decoder
442
768
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (pCtx, &m_pWelsTrace->m_sLogCtx),
443
768
                              UninitDecoderCtx (pCtx))
444
768
  pCtx->pPicBuff = NULL;
445
768
  return cmResultSuccess;
446
768
}
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
657
    SBufferInfo* pDstInfo) {
708
657
  int iRet = dsErrorFree;
709
657
  if (m_iThreadCount >= 1) {
710
0
    SET_EVENT (&m_sReleaseBufferEvent);
711
0
    iRet = ThreadDecodeFrameInternal (kpSrc, kiSrcLen, ppDst, pDstInfo);
712
    // The worker publishes into the shared reorder queue via
713
    // BufferingReadyPicture() while holding m_csDecoder, so every access to that
714
    // queue state on the caller side must take the same lock. The lock must not
715
    // be held across WAIT_EVENT() or the Release* dequeue (which re-locks), so
716
    // snapshot the shared counters under the lock instead of reading them raw.
717
0
    WelsMutexLock (&m_csDecoder);
718
0
    int32_t iNumOfPicts = m_sReoderingStatus.iNumOfPicts;
719
0
    WelsMutexUnlock (&m_csDecoder);
720
0
    if (iNumOfPicts) {
721
0
      WAIT_EVENT (&m_sBufferingEvent, WELS_DEC_THREAD_WAIT_INFINITE);
722
0
      RESET_EVENT (&m_sBufferingEvent);
723
0
      RESET_EVENT (&m_sReleaseBufferEvent);
724
0
      WelsMutexLock (&m_csDecoder);
725
0
      const bool bHasBSlice = m_sReoderingStatus.bHasBSlice;
726
0
      iNumOfPicts = m_sReoderingStatus.iNumOfPicts;
727
0
      WelsMutexUnlock (&m_csDecoder);
728
0
      if (!bHasBSlice) {
729
0
        if (iNumOfPicts > 1) {
730
0
          ReleaseBufferedReadyPictureNoReorder (NULL, ppDst, pDstInfo);
731
0
        }
732
0
      }
733
0
      else {
734
0
        ReleaseBufferedReadyPictureReorder (NULL, ppDst, pDstInfo);
735
0
      }
736
0
    }
737
0
    return (DECODING_STATE)iRet;
738
0
  }
739
  //SBufferInfo sTmpBufferInfo;
740
  //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
741
657
  iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
742
  //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
743
  //ppTmpDst[0] = ppDst[0];
744
  //ppTmpDst[1] = ppDst[1];
745
  //ppTmpDst[2] = ppDst[2];
746
657
  iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
747
  //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
748
  //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
749
  //ppDst[0] = ppTmpDst[0];
750
  //ppDst[1] = ppTmpDst[1];
751
  //ppDst[2] = ppTmpDst[2];
752
  //}
753
657
  return (DECODING_STATE)iRet;
754
657
}
755
756
DECODING_STATE CWelsDecoder::DecodeFrame2WithCtx (PWelsDecoderContext pDecContext, const unsigned char* kpSrc,
757
    const int kiSrcLen,
758
    unsigned char** ppDst,
759
1.31k
    SBufferInfo* pDstInfo) {
760
1.31k
  if (pDecContext == NULL || pDecContext->pParam == NULL) {
761
0
    if (m_pWelsTrace != NULL) {
762
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
763
0
    }
764
0
    return dsInitialOptExpected;
765
0
  }
766
767
1.31k
  if (pDecContext->pParam->bParseOnly) {
768
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
769
0
    pDecContext->iErrorCode |= dsInvalidArgument;
770
0
    return dsInvalidArgument;
771
0
  }
772
1.31k
  if (CheckBsBuffer (pDecContext, kiSrcLen)) {
773
0
    if (ResetDecoder(pDecContext)) {
774
0
      if (pDstInfo) pDstInfo->iBufferStatus = 0;
775
0
      return dsOutOfMemory;
776
0
    }
777
0
    return dsErrorFree;
778
0
  }
779
1.31k
  if (kiSrcLen > 0 && kpSrc != NULL) {
780
#ifdef OUTPUT_BIT_STREAM
781
    if (m_pFBS) {
782
      WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
783
      WelsFflush (m_pFBS);
784
    }
785
    if (m_pFBSSize) {
786
      WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
787
      WelsFflush (m_pFBSSize);
788
    }
789
#endif//OUTPUT_BIT_STREAM
790
657
    pDecContext->bEndOfStreamFlag = false;
791
657
    if (GetThreadCount (pDecContext) <= 0) {
792
657
      pDecContext->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
793
657
    }
794
657
  } else {
795
    //For application MODE, the error detection should be added for safe.
796
    //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
797
657
    pDecContext->bEndOfStreamFlag = true;
798
657
    pDecContext->bInstantDecFlag = true;
799
657
  }
800
801
1.31k
  int64_t iStart, iEnd;
802
1.31k
  iStart = WelsTime();
803
804
1.31k
  if (GetThreadCount (pDecContext) <= 1) {
805
1.31k
    ppDst[0] = ppDst[1] = ppDst[2] = NULL;
806
1.31k
  }
807
1.31k
  pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
808
1.31k
  pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
809
1.31k
  unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
810
1.31k
  if (GetThreadCount (pDecContext) <= 1) {
811
1.31k
    memset (pDstInfo, 0, sizeof (SBufferInfo));
812
1.31k
  }
813
1.31k
  pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
814
1.31k
#ifdef LONG_TERM_REF
815
1.31k
  pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
816
1.31k
  pDecContext->bCurAuContainLtrMarkSeFlag = false;
817
1.31k
  pDecContext->iFrameNumOfAuMarkedLtr = 0;
818
1.31k
  pDecContext->iFrameNum = -1; //initialize
819
1.31k
#endif
820
821
1.31k
  if (GetThreadCount (pDecContext) >= 1) {
822
0
    WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE);
823
0
  }
824
825
1.31k
  pDecContext->iFeedbackTidInAu = -1; //initialize
826
1.31k
  pDecContext->iFeedbackNalRefIdc = -1; //initialize
827
1.31k
  if (pDstInfo) {
828
1.31k
    pDstInfo->uiOutYuvTimeStamp = 0;
829
1.31k
    pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
830
1.31k
  } else {
831
0
    pDecContext->uiTimeStamp = 0;
832
0
  }
833
1.31k
  WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, ppDst,
834
1.31k
                pDstInfo, NULL); //iErrorCode has been modified in this function
835
1.31k
  pDecContext->bInstantDecFlag = false; //reset no-delay flag
836
1.31k
  if (pDecContext->iErrorCode) {
837
588
    EWelsNalUnitType eNalType =
838
588
      NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
839
840
588
    eNalType = pDecContext->sCurNalHead.eNalUnitType;
841
588
    if (pDecContext->iErrorCode & dsOutOfMemory) {
842
0
      if (ResetDecoder (pDecContext)) {
843
0
        if (pDstInfo) pDstInfo->iBufferStatus = 0;
844
0
        return dsOutOfMemory;
845
0
      }
846
0
      return dsErrorFree;
847
0
    }
848
588
    if (pDecContext->iErrorCode & dsRefListNullPtrs) {
849
0
      if (ResetDecoder (pDecContext)) {
850
0
        if (pDstInfo) pDstInfo->iBufferStatus = 0;
851
0
        return dsRefListNullPtrs;
852
0
      }
853
0
      return dsErrorFree;
854
0
    }
855
    //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
856
588
    if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
857
588
        (VIDEO_BITSTREAM_AVC == pDecContext->eVideoType)) {
858
588
      if (pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
859
588
#ifdef LONG_TERM_REF
860
588
        pDecContext->bParamSetsLostFlag = true;
861
#else
862
        pDecContext->bReferenceLostAtT0Flag = true;
863
#endif
864
588
      }
865
588
    }
866
867
588
    if (pDecContext->bPrintFrameErrorTraceFlag) {
868
588
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
869
588
               pDecContext->iErrorCode);
870
588
      pDecContext->bPrintFrameErrorTraceFlag = false;
871
588
    } else {
872
0
      pDecContext->iIgnoredErrorInfoPacketCount++;
873
0
      if (pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
874
0
        WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
875
0
        pDecContext->iIgnoredErrorInfoPacketCount = 0;
876
0
      }
877
0
    }
878
588
    if ((pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
879
      //TODO after dec status updated
880
0
      pDecContext->iErrorCode |= dsDataErrorConcealed;
881
882
0
      pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
883
0
      if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
884
0
        ResetDecStatNums (pDecContext->pDecoderStatistics);
885
0
        pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
886
0
      }
887
0
      int32_t iMbConcealedNum = pDecContext->iMbEcedNum + pDecContext->iMbEcedPropNum;
888
0
      pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->iMbNum == 0 ?
889
0
          (pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
890
0
                pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
891
0
                      iMbConcealedNum * 100) / pDecContext->iMbNum));
892
0
      pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->iMbNum == 0 ?
893
0
          (pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
894
0
                pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
895
0
                      pDecContext->iMbEcedPropNum * 100) / pDecContext->iMbNum));
896
0
      pDecContext->pDecoderStatistics->uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
897
0
      pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
898
0
          pDecContext->pDecoderStatistics->uiAvgEcRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
899
0
      pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
900
0
          pDecContext->pDecoderStatistics->uiAvgEcPropRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
901
0
    }
902
588
    iEnd = WelsTime();
903
588
    pDecContext->dDecTime += (iEnd - iStart) / 1e3;
904
905
588
    OutputStatisticsLog (*pDecContext->pDecoderStatistics);
906
588
    if (GetThreadCount (pDecContext) >= 1) {
907
0
      BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
908
0
      SET_EVENT (&m_sBufferingEvent);
909
588
    } else {
910
588
      ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
911
588
    }
912
913
588
    return (DECODING_STATE)pDecContext->iErrorCode;
914
588
  }
915
  // else Error free, the current codec works well
916
917
726
  if (pDstInfo->iBufferStatus == 1) {
918
919
0
    pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
920
0
    if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
921
0
      ResetDecStatNums (pDecContext->pDecoderStatistics);
922
0
      pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
923
0
    }
924
925
0
    OutputStatisticsLog (*pDecContext->pDecoderStatistics);
926
0
  }
927
726
  iEnd = WelsTime();
928
726
  pDecContext->dDecTime += (iEnd - iStart) / 1e3;
929
930
726
  if (GetThreadCount (pDecContext) >= 1) {
931
0
    BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
932
0
    SET_EVENT (&m_sBufferingEvent);
933
726
  } else {
934
726
    ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
935
726
  }
936
726
  return dsErrorFree;
937
1.31k
}
938
939
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
940
    const int kiSrcLen,
941
    unsigned char** ppDst,
942
1.31k
    SBufferInfo* pDstInfo) {
943
1.31k
  PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
944
1.31k
  return DecodeFrame2WithCtx (pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo);
945
1.31k
}
946
947
DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
948
3.38k
    SBufferInfo* pDstInfo) {
949
3.38k
  bool bEndOfStreamFlag = true;
950
3.38k
  if (m_iThreadCount <= 1) {
951
6.76k
    for (int32_t j = 0; j < m_iCtxCount; ++j) {
952
3.38k
      if (!m_pDecThrCtx[j].pCtx->bEndOfStreamFlag) {
953
0
        bEndOfStreamFlag = false;
954
0
      }
955
3.38k
    }
956
3.38k
  }
957
  // Read the shared reorder-queue counters under m_csDecoder in
958
  // threaded mode (the worker mutates them in BufferingReadyPicture()); the
959
  // Release* dequeue re-locks internally, so do not hold the lock across it.
960
3.38k
  if (m_iThreadCount >= 1) WelsMutexLock (&m_csDecoder);
961
3.38k
  const int32_t iNumOfPicts = m_sReoderingStatus.iNumOfPicts;
962
3.38k
  const bool bHasBSlice = m_sReoderingStatus.bHasBSlice;
963
3.38k
  if (m_iThreadCount >= 1) WelsMutexUnlock (&m_csDecoder);
964
3.38k
  if (bEndOfStreamFlag && iNumOfPicts > 0) {
965
0
    if (!bHasBSlice) {
966
0
      ReleaseBufferedReadyPictureNoReorder (NULL, ppDst, pDstInfo);
967
0
    }
968
0
    else {
969
0
      ReleaseBufferedReadyPictureReorder (NULL, ppDst, pDstInfo, true);
970
0
    }
971
0
  }
972
3.38k
  return dsErrorFree;
973
3.38k
}
974
975
588
void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
976
588
  if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
977
0
      && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
978
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
979
0
             "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
980
0
              uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
981
0
              uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
982
0
              uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
983
0
              iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
984
0
              uiProfile=%d, uiLevel=%d, \
985
0
              iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
986
0
             sDecoderStatistics.uiWidth,
987
0
             sDecoderStatistics.uiHeight,
988
0
             sDecoderStatistics.fAverageFrameSpeedInMs,
989
0
             sDecoderStatistics.fActualAverageFrameSpeedInMs,
990
991
0
             sDecoderStatistics.uiDecodedFrameCount,
992
0
             sDecoderStatistics.uiResolutionChangeTimes,
993
0
             sDecoderStatistics.uiIDRCorrectNum,
994
995
0
             sDecoderStatistics.uiAvgEcRatio,
996
0
             sDecoderStatistics.uiAvgEcPropRatio,
997
0
             sDecoderStatistics.uiEcIDRNum,
998
0
             sDecoderStatistics.uiEcFrameNum,
999
1000
0
             sDecoderStatistics.uiIDRLostNum,
1001
0
             sDecoderStatistics.uiFreezingIDRNum,
1002
0
             sDecoderStatistics.uiFreezingNonIDRNum,
1003
0
             sDecoderStatistics.iAvgLumaQp,
1004
1005
0
             sDecoderStatistics.iSpsReportErrorNum,
1006
0
             sDecoderStatistics.iSubSpsReportErrorNum,
1007
0
             sDecoderStatistics.iPpsReportErrorNum,
1008
0
             sDecoderStatistics.iSpsNoExistNalNum,
1009
0
             sDecoderStatistics.iSubSpsNoExistNalNum,
1010
0
             sDecoderStatistics.iPpsNoExistNalNum,
1011
1012
0
             sDecoderStatistics.uiProfile,
1013
0
             sDecoderStatistics.uiLevel,
1014
1015
0
             sDecoderStatistics.iCurrentActiveSpsId,
1016
0
             sDecoderStatistics.iCurrentActivePpsId);
1017
0
  }
1018
588
}
1019
1020
void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst,
1021
0
    SBufferInfo* pDstInfo) {
1022
0
  if (pDstInfo->iBufferStatus == 0) {
1023
0
    return;
1024
0
  }
1025
  // Publish into the shared reorder queue (m_sPictInfoList /
1026
  // m_sReoderingStatus) under m_csDecoder so the caller-side Release* dequeue
1027
  // cannot observe or mutate a half-updated slot concurrently.
1028
0
  if (m_iThreadCount >= 1) WelsMutexLock (&m_csDecoder);
1029
0
  m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83;
1030
0
  if (!m_bIsBaseline) {
1031
0
    if (pCtx->pSliceHeader->eSliceType == B_SLICE) {
1032
0
      m_sReoderingStatus.bHasBSlice = true;
1033
0
    }
1034
0
  }
1035
0
  for (int32_t i = 0; i < 16; ++i) {
1036
0
    if (m_sPictInfoList[i].iPOC == IMinInt32) {
1037
0
      memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
1038
0
      m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb;
1039
0
      m_sPictInfoList[i].iSeqNum = pCtx->iSeqNum;
1040
0
      m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp;
1041
0
      if (pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb != NULL) {
1042
0
        PPicture pPrevPic = (GetThreadCount (pCtx) > 1 && pCtx->pThreadCtx != NULL)
1043
0
                           ? ((PWelsDecoderThreadCTX)pCtx->pThreadCtx)->pPreviousDecodedPictureInDpb
1044
0
                           : pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb;
1045
0
        if (pPrevPic != NULL) {
1046
0
          m_sPictInfoList[i].iPicBuffIdx = pPrevPic->iPicBuffIdx;
1047
0
          if (GetThreadCount (pCtx) <= 1) ++pPrevPic->iRefCount;
1048
0
        }
1049
0
      }
1050
0
      m_iLastBufferedIdx = i;
1051
0
      pDstInfo->iBufferStatus = 0;
1052
0
      ++m_sReoderingStatus.iNumOfPicts;
1053
0
      if (i > m_sReoderingStatus.iLargestBufferedPicIndex) {
1054
0
        m_sReoderingStatus.iLargestBufferedPicIndex = i;
1055
0
      }
1056
0
      break;
1057
0
    }
1058
0
  }
1059
0
  if (m_iThreadCount >= 1) WelsMutexUnlock (&m_csDecoder);
1060
0
}
1061
1062
void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx, unsigned char** ppDst,
1063
0
    SBufferInfo* pDstInfo, bool isFlush) {
1064
  // Serialize the full dequeue against the worker's
1065
  // BufferingReadyPicture() publication on the shared m_sPictInfoList /
1066
  // m_sReoderingStatus queue state.
1067
0
  if (m_iThreadCount >= 1) WelsMutexLock (&m_csDecoder);
1068
0
  PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1069
0
  if (pCtx == NULL && m_iThreadCount <= 1) {
1070
0
    pCtx = m_pDecThrCtx[0].pCtx;
1071
0
  }
1072
0
  if (m_sReoderingStatus.iNumOfPicts > 0) {
1073
0
    m_sReoderingStatus.iMinPOC = IMinInt32;
1074
0
    int32_t firstValidIdx = -1;
1075
0
    for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1076
0
      if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
1077
0
        m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1078
0
        m_sReoderingStatus.iMinSeqNum = m_sPictInfoList[i].iSeqNum;
1079
0
        m_sReoderingStatus.iPictInfoIndex = i;
1080
0
        firstValidIdx = i;
1081
0
        break;
1082
0
      }
1083
0
    }
1084
0
    for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1085
0
      if (i == firstValidIdx) continue;
1086
0
      if (m_sPictInfoList[i].iPOC > IMinInt32
1087
0
          && ((m_sPictInfoList[i].iSeqNum == m_sReoderingStatus.iMinSeqNum) ? (m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) : (m_sPictInfoList[i].iSeqNum - m_sReoderingStatus.iMinSeqNum < 0))) {
1088
0
        m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1089
0
        m_sReoderingStatus.iMinSeqNum = m_sPictInfoList[i].iSeqNum;
1090
0
        m_sReoderingStatus.iPictInfoIndex = i;
1091
0
      }
1092
0
    }
1093
0
  }
1094
0
  if (m_sReoderingStatus.iMinPOC > IMinInt32) {
1095
0
    bool isReady = true;
1096
0
    if (!isFlush) {
1097
0
      int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
1098
0
      int32_t iLastSeqNum = pCtx != NULL ? pCtx->iSeqNum : m_sPictInfoList[m_iLastBufferedIdx].iSeqNum;
1099
0
      isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
1100
0
        && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
1101
0
        || m_sReoderingStatus.iMinPOC < iLastPOC
1102
0
        || m_sReoderingStatus.iMinSeqNum - iLastSeqNum < 0;
1103
0
    }
1104
0
    if (isReady) {
1105
0
      m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1106
0
      m_sReoderingStatus.iLastWrittenSeqNum = m_sReoderingStatus.iMinSeqNum;
1107
#if defined (_DEBUG)
1108
#ifdef _MOTION_VECTOR_DUMP_
1109
      fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1110
               m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1111
#endif
1112
#endif
1113
0
      memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1114
0
      ppDst[0] = pDstInfo->pDst[0];
1115
0
      ppDst[1] = pDstInfo->pDst[1];
1116
0
      ppDst[2] = pDstInfo->pDst[2];
1117
0
      m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1118
0
      int32_t iPicBuffIdx = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx;
1119
0
      if (pPicBuff != NULL) {
1120
0
        if (iPicBuffIdx >= 0 && iPicBuffIdx < pPicBuff->iCapacity)
1121
0
        {
1122
0
            PPicture pPic = pPicBuff->ppPic[iPicBuffIdx];
1123
0
            --pPic->iRefCount;
1124
0
            if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
1125
0
              pPic->pSetUnRef(pPic);
1126
0
        }
1127
0
      }
1128
0
      m_sReoderingStatus.iMinPOC = IMinInt32;
1129
0
      --m_sReoderingStatus.iNumOfPicts;
1130
0
    }
1131
0
  }
1132
0
  if (m_iThreadCount >= 1) WelsMutexUnlock (&m_csDecoder);
1133
0
}
1134
1135
//if there is no b-frame, no ordering based on values of POCs is necessary.
1136
//The function is added to force to avoid picture reordering because some h.264 streams do not follow H.264 POC specifications. 
1137
void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo)
1138
0
{
1139
  // Serialize the full dequeue against the worker's
1140
  // BufferingReadyPicture() publication on the shared m_sPictInfoList /
1141
  // m_sReoderingStatus queue state.
1142
0
  if (m_iThreadCount >= 1) WelsMutexLock (&m_csDecoder);
1143
0
  int32_t firstValidIdx = -1;
1144
0
  uint32_t uiDecodingTimeStamp = 0;
1145
0
  for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1146
0
    if (m_sPictInfoList[i].iPOC != IMinInt32) {
1147
0
      uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1148
0
      m_sReoderingStatus.iPictInfoIndex = i;
1149
0
      firstValidIdx = i;
1150
0
      break;
1151
0
    }
1152
0
  }
1153
0
  for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1154
0
    if (i == firstValidIdx) continue;
1155
0
    if (m_sPictInfoList[i].iPOC != IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
1156
0
      uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1157
0
      m_sReoderingStatus.iPictInfoIndex = i;
1158
0
    }
1159
0
  }
1160
0
  if (uiDecodingTimeStamp > 0) {
1161
#if defined (_DEBUG)
1162
#ifdef _MOTION_VECTOR_DUMP_
1163
    fprintf(stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC,
1164
      uiDecodingTimeStamp);
1165
#endif
1166
#endif
1167
0
    m_sReoderingStatus.iLastWrittenPOC = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC;
1168
0
    m_sReoderingStatus.iLastWrittenSeqNum = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iSeqNum;
1169
0
    memcpy(pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof(SBufferInfo));
1170
0
    ppDst[0] = pDstInfo->pDst[0];
1171
0
    ppDst[1] = pDstInfo->pDst[1];
1172
0
    ppDst[2] = pDstInfo->pDst[2];
1173
0
    m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1174
0
    if (pCtx || m_pPicBuff) {
1175
0
      PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1176
0
      int32_t iPicBuffIdx = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx;
1177
0
      if (pPicBuff != NULL && iPicBuffIdx >= 0 && iPicBuffIdx < pPicBuff->iCapacity) {
1178
0
        PPicture pPic = pPicBuff->ppPic[iPicBuffIdx];
1179
0
        --pPic->iRefCount;
1180
0
        if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
1181
0
          pPic->pSetUnRef(pPic);
1182
0
      }
1183
0
    }
1184
0
    --m_sReoderingStatus.iNumOfPicts;
1185
0
  }
1186
0
  if (m_iThreadCount >= 1) WelsMutexUnlock (&m_csDecoder);
1187
0
  return;
1188
0
}
1189
1190
DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay(PWelsDecoderContext pDecContext, unsigned char** ppDst,
1191
1.31k
  SBufferInfo* pDstInfo) {
1192
1.31k
  DECODING_STATE iRet = dsErrorFree;
1193
1.31k
  if (pDecContext->pSps != NULL) {
1194
0
    m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
1195
0
    if (!m_bIsBaseline) {
1196
0
      if (pDstInfo->iBufferStatus == 1) {
1197
0
        if (pDecContext->pSliceHeader->eSliceType == B_SLICE &&
1198
0
            ((pDecContext->iSeqNum == m_sReoderingStatus.iLastWrittenSeqNum) ?
1199
0
              (pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) :
1200
0
              (pDecContext->iSeqNum - m_sReoderingStatus.iLastWrittenSeqNum == 1 && pDecContext->pSliceHeader->iPicOrderCntLsb == 0))) {
1201
0
          m_sReoderingStatus.iLastWrittenPOC = pDecContext->pSliceHeader->iPicOrderCntLsb;
1202
0
          m_sReoderingStatus.iLastWrittenSeqNum = pDecContext->iSeqNum;
1203
          //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
1204
0
          ppDst[0] = pDstInfo->pDst[0];
1205
0
          ppDst[1] = pDstInfo->pDst[1];
1206
0
          ppDst[2] = pDstInfo->pDst[2];
1207
#if defined (_DEBUG)
1208
#ifdef _MOTION_VECTOR_DUMP_
1209
          fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", pDecContext->pSliceHeader->iPicOrderCntLsb,
1210
             pDecContext->uiDecodingTimeStamp);
1211
#endif
1212
#endif
1213
0
          return iRet;
1214
0
        }
1215
0
        BufferingReadyPicture(pDecContext, ppDst, pDstInfo);
1216
0
        if (!m_sReoderingStatus.bHasBSlice && m_sReoderingStatus.iNumOfPicts > 1) {
1217
0
          ReleaseBufferedReadyPictureNoReorder (pDecContext, ppDst, pDstInfo);
1218
0
        }
1219
0
        else {
1220
0
          ReleaseBufferedReadyPictureReorder (pDecContext, ppDst, pDstInfo);
1221
0
        }
1222
0
      }
1223
0
    }
1224
0
  }
1225
1.31k
  return iRet;
1226
1.31k
}
1227
1228
0
DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1229
0
  PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1230
1231
0
  if (pDecContext == NULL || pDecContext->pParam == NULL) {
1232
0
    if (m_pWelsTrace != NULL) {
1233
0
      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1234
0
    }
1235
0
    return dsInitialOptExpected;
1236
0
  }
1237
1238
0
  if (!pDecContext->pParam->bParseOnly) {
1239
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1240
0
    pDecContext->iErrorCode |= dsInvalidArgument;
1241
0
    return dsInvalidArgument;
1242
0
  }
1243
0
  int64_t iEnd, iStart = WelsTime();
1244
0
  if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1245
0
    if (ResetDecoder (pDecContext))
1246
0
      return dsOutOfMemory;
1247
1248
0
    return dsErrorFree;
1249
0
  }
1250
0
  if (kiSrcLen > 0 && kpSrc != NULL) {
1251
#ifdef OUTPUT_BITSTREAM
1252
    if (m_pFBS) {
1253
      WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
1254
      WelsFflush (m_pFBS);
1255
    }
1256
#endif//OUTPUT_BIT_STREAM
1257
0
    pDecContext->bEndOfStreamFlag = false;
1258
0
  } else {
1259
    //For application MODE, the error detection should be added for safe.
1260
    //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
1261
0
    pDecContext->bEndOfStreamFlag = true;
1262
0
    pDecContext->bInstantDecFlag = true;
1263
0
  }
1264
1265
0
  pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1266
0
  pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1267
0
  pDecContext->iFeedbackNalRefIdc = -1; //initialize
1268
0
  if (!pDecContext->bFramePending) { //frame complete
1269
0
    pDecContext->pParserBsInfo->iNalNum = 0;
1270
0
    memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1271
0
  }
1272
0
  pDstInfo->iNalNum = 0;
1273
0
  pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1274
0
  if (pDstInfo) {
1275
0
    pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1276
0
    pDstInfo->uiOutBsTimeStamp = 0;
1277
0
  } else {
1278
0
    pDecContext->uiTimeStamp = 0;
1279
0
  }
1280
0
  WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1281
0
  if (pDecContext->iErrorCode & dsOutOfMemory) {
1282
0
    if (ResetDecoder (pDecContext))
1283
0
      return dsOutOfMemory;
1284
0
    return dsErrorFree;
1285
0
  }
1286
1287
0
  if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1288
0
    memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1289
1290
0
    if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1291
0
      pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1292
0
      if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1293
0
        ResetDecStatNums (pDecContext->pDecoderStatistics);
1294
0
        pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1295
0
      }
1296
0
    }
1297
0
  }
1298
1299
0
  pDecContext->bInstantDecFlag = false; //reset no-delay flag
1300
1301
0
  if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1302
0
    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1303
0
    pDecContext->bPrintFrameErrorTraceFlag = false;
1304
0
  }
1305
0
  iEnd = WelsTime();
1306
0
  pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1307
0
  return (DECODING_STATE)pDecContext->iErrorCode;
1308
0
}
1309
1310
DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1311
    const int kiSrcLen,
1312
    unsigned char** ppDst,
1313
    int* pStride,
1314
    int& iWidth,
1315
0
    int& iHeight) {
1316
0
  DECODING_STATE eDecState = dsErrorFree;
1317
0
  SBufferInfo    DstInfo;
1318
1319
0
  memset (&DstInfo, 0, sizeof (SBufferInfo));
1320
0
  DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1321
0
  DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1322
0
  DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1323
0
  DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1324
1325
0
  eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1326
0
  if (eDecState == dsErrorFree) {
1327
0
    pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1328
0
    pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1329
0
    iWidth     = DstInfo.UsrData.sSystemBuffer.iWidth;
1330
0
    iHeight    = DstInfo.UsrData.sSystemBuffer.iHeight;
1331
0
  }
1332
1333
0
  return eDecState;
1334
0
}
1335
1336
DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
1337
    const int kiSrcLen,
1338
    unsigned char* pDst,
1339
    int iDstStride,
1340
    int& iDstLen,
1341
    int& iWidth,
1342
    int& iHeight,
1343
0
    int& iColorFormat) {
1344
0
  DECODING_STATE state = dsErrorFree;
1345
1346
0
  return state;
1347
0
}
1348
1349
0
DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1350
0
  sThreadCtx.pCtx->bHasNewSps = false;
1351
0
  sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1352
0
  sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1353
0
  sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1354
0
  bool bPicBuffChanged = false;
1355
0
  if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1356
0
    CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1357
0
    sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1358
0
    if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1359
0
      bPicBuffChanged = true;
1360
0
      sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1361
0
      sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1362
0
      sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1363
0
      sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1364
0
    }
1365
0
  }
1366
1367
  //if threadCount > 1, then each thread must contain exact one complete frame.
1368
0
  if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1369
0
    sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0;
1370
0
    sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0;
1371
0
  }
1372
1373
0
  int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1374
0
                                      &sThreadCtx.sDstInfo);
1375
1376
0
  int32_t iErr = WelsDecodeInitAccessUnitStart (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1377
0
  if (ERR_NONE != iErr) {
1378
0
    return (DECODING_STATE) (iRet | iErr);
1379
0
  }
1380
0
  if (sThreadCtx.pCtx->bNewSeqBegin) {
1381
0
    if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1382
      // Wait for older workers before replacing shared DPB storage.
1383
0
      for (int32_t i = 0; i < m_DecCtxActiveCount; ++i) {
1384
0
        if (m_pDecThrCtxActive[i] != NULL && m_pDecThrCtxActive[i] != &sThreadCtx) {
1385
0
          WAIT_SEMAPHORE (&m_pDecThrCtxActive[i]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1386
0
          RELEASE_SEMAPHORE (&m_pDecThrCtxActive[i]->sThreadInfo.sIsIdle);
1387
0
        }
1388
0
      }
1389
0
      sThreadCtx.pCtx->pLastThreadCtx = NULL;
1390
0
    }
1391
0
    iErr = AllocPicBuffOnNewSeqBegin (sThreadCtx.pCtx);
1392
0
    if (ERR_NONE != iErr) {
1393
0
      return (DECODING_STATE) (iRet | iErr);
1394
0
    }
1395
0
    m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1396
    // Keep sibling contexts from carrying stale DPB references.
1397
0
    for (int32_t i = 0; i < m_iCtxCount; ++i) {
1398
0
      if (&m_pDecThrCtx[i] != &sThreadCtx && m_pDecThrCtx[i].pCtx != NULL) {
1399
0
        m_pDecThrCtx[i].pCtx->pPicBuff = m_pPicBuff;
1400
0
        m_pDecThrCtx[i].pCtx->bHaveGotMemory = sThreadCtx.pCtx->bHaveGotMemory;
1401
0
        m_pDecThrCtx[i].pCtx->iPicQueueNumber = sThreadCtx.pCtx->iPicQueueNumber;
1402
0
        m_pDecThrCtx[i].pCtx->iImgWidthInPixel = sThreadCtx.pCtx->iImgWidthInPixel;
1403
0
        m_pDecThrCtx[i].pCtx->iImgHeightInPixel = sThreadCtx.pCtx->iImgHeightInPixel;
1404
0
        m_pDecThrCtx[i].pCtx->pDec = NULL;
1405
0
        m_pDecThrCtx[i].pCtx->pLastThreadCtx = NULL;
1406
0
        iErr = InitialDqLayersContext (m_pDecThrCtx[i].pCtx, sThreadCtx.pCtx->iImgWidthInPixel,
1407
0
                                       sThreadCtx.pCtx->iImgHeightInPixel);
1408
0
        if (ERR_NONE != iErr) {
1409
0
          return (DECODING_STATE) (iRet | iErr);
1410
0
        }
1411
0
      }
1412
0
    }
1413
0
  } else if (bPicBuffChanged) {
1414
0
    InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1415
0
  }
1416
0
  if (!sThreadCtx.pCtx->bNewSeqBegin && m_pLastDecThrCtx != NULL) {
1417
0
    sThreadCtx.pCtx->sFrameCrop = m_pLastDecThrCtx->pCtx->pSps->sFrameCrop;
1418
0
  }
1419
0
  m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1420
0
  m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1421
0
  return (DECODING_STATE) (iRet | iErr);
1422
0
}
1423
/*
1424
* Run decoding picture in separate thread.
1425
*/
1426
1427
int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1428
0
    SBufferInfo* pDstInfo) {
1429
0
  int state = dsErrorFree;
1430
0
  int32_t i, j;
1431
0
  int32_t signal = 0;
1432
1433
  //serial using of threads
1434
0
  if (m_DecCtxActiveCount < m_iThreadCount) {
1435
0
    signal = m_DecCtxActiveCount;
1436
0
  } else {
1437
0
    signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1438
0
  }
1439
1440
0
  WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1441
1442
0
  for (i = 0; i < m_DecCtxActiveCount; ++i) {
1443
0
    if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1444
0
      m_pDecThrCtxActive[i] = NULL;
1445
0
      for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1446
0
        m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1447
0
        m_pDecThrCtxActive[j + 1] = NULL;
1448
0
      }
1449
0
      --m_DecCtxActiveCount;
1450
0
      break;
1451
0
    }
1452
0
  }
1453
1454
0
  if (m_pLastDecThrCtx != NULL) {
1455
0
    m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1456
0
  }
1457
0
  m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1458
0
  m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1459
0
  m_pDecThrCtx[signal].ppDst = ppDst;
1460
0
  memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1461
1462
0
  state = ParseAccessUnit (m_pDecThrCtx[signal]);
1463
0
  if (state != dsErrorFree) {
1464
0
    RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle);
1465
0
    return state;
1466
0
  }
1467
1468
0
  if (m_iThreadCount > 1 && m_pDecThrCtx[signal].pCtx->pAccessUnitList->uiAvailUnitsNum == 0) {
1469
0
    RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle);
1470
0
    return state;
1471
0
  }
1472
1473
0
  m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1474
0
  if (m_iThreadCount > 1) {
1475
0
    m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1476
0
  }
1477
0
  m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1478
0
  RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1479
1480
  // wait early picture
1481
0
  if (m_DecCtxActiveCount >= m_iThreadCount) {
1482
0
    WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1483
0
    RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1484
0
  }
1485
0
  return state;
1486
0
}
1487
1488
} // namespace WelsDec
1489
1490
1491
using namespace WelsDec;
1492
/*
1493
*       WelsGetDecoderCapability
1494
*       @return: DecCapability information
1495
*/
1496
0
int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1497
0
  memset (pDecCapability, 0, sizeof (SDecoderCapability));
1498
0
  pDecCapability->iProfileIdc = 66; //Baseline
1499
0
  pDecCapability->iProfileIop = 0xE0; //11100000b
1500
0
  pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1501
0
  pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1502
0
  pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1503
0
  pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1504
0
  pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1505
0
  pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1506
0
  pDecCapability->bRedPicCap = 0; //not support redundant pic
1507
1508
0
  return ERR_NONE;
1509
0
}
1510
/* WINAPI is indeed in prefix due to sync to application layer callings!! */
1511
1512
/*
1513
*   WelsCreateDecoder
1514
*   @return:    success in return 0, otherwise failed.
1515
*/
1516
768
long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1517
1518
768
  if (NULL == ppDecoder) {
1519
0
    return ERR_INVALID_PARAMETERS;
1520
0
  }
1521
1522
768
  *ppDecoder = new CWelsDecoder();
1523
1524
768
  if (NULL == *ppDecoder) {
1525
0
    return ERR_MALLOC_FAILED;
1526
0
  }
1527
1528
768
  return ERR_NONE;
1529
768
}
1530
1531
/*
1532
*   WelsDestroyDecoder
1533
*/
1534
768
void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1535
768
  if (NULL != pDecoder) {
1536
768
    delete (CWelsDecoder*)pDecoder;
1537
768
  }
1538
768
}