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