• 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       m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
1032       if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount;
1033       m_sPictInfoList[i].bLastGOP = false;
1034       m_iLastBufferedIdx = i;
1035       pDstInfo->iBufferStatus = 0;
1036       ++m_sReoderingStatus.iNumOfPicts;
1037       if (i > m_sReoderingStatus.iLargestBufferedPicIndex) {
1038         m_sReoderingStatus.iLargestBufferedPicIndex = i;
1039       }
1040       break;
1041     }
1042   }
1043 }
1044 
ReleaseBufferedReadyPictureReorder(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo,bool isFlush)1045 void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx, unsigned char** ppDst,
1046     SBufferInfo* pDstInfo, bool isFlush) {
1047   PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1048   if (pCtx == NULL && m_iThreadCount <= 1) {
1049     pCtx = m_pDecThrCtx[0].pCtx;
1050   }
1051   if (m_sReoderingStatus.iLastGOPRemainPicts > 0) {
1052     m_sReoderingStatus.iMinPOC = IMinInt32;
1053     int32_t firstValidIdx = -1;
1054     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1055       if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) {
1056         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1057         m_sReoderingStatus.iPictInfoIndex = i;
1058         firstValidIdx = i;
1059         break;
1060       }
1061     }
1062     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1063       if (i == firstValidIdx) continue;
1064       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC
1065           && m_sPictInfoList[i].bLastGOP) {
1066         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1067         m_sReoderingStatus.iPictInfoIndex = i;
1068       }
1069     }
1070     m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1071 #if defined (_DEBUG)
1072 #ifdef _MOTION_VECTOR_DUMP_
1073     fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1074              m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1075 #endif
1076 #endif
1077     memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1078     ppDst[0] = pDstInfo->pDst[0];
1079     ppDst[1] = pDstInfo->pDst[1];
1080     ppDst[2] = pDstInfo->pDst[2];
1081     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1082     if (pPicBuff != NULL) {
1083       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1084       --pPic->iRefCount;
1085     }
1086     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1087     m_sReoderingStatus.iMinPOC = IMinInt32;
1088     --m_sReoderingStatus.iNumOfPicts;
1089     --m_sReoderingStatus.iLastGOPRemainPicts;
1090     if (m_sReoderingStatus.iLastGOPRemainPicts == 0) {
1091       m_sReoderingStatus.iLastWrittenPOC = IMinInt32;
1092     }
1093     return;
1094   }
1095   if (m_sReoderingStatus.iNumOfPicts > 0) {
1096     m_sReoderingStatus.iMinPOC = IMinInt32;
1097     int32_t firstValidIdx = -1;
1098     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1099       if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
1100         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1101         m_sReoderingStatus.iPictInfoIndex = i;
1102         firstValidIdx = i;
1103         break;
1104       }
1105     }
1106     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1107       if (i == firstValidIdx) continue;
1108       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) {
1109         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1110         m_sReoderingStatus.iPictInfoIndex = i;
1111       }
1112     }
1113   }
1114   if (m_sReoderingStatus.iMinPOC > IMinInt32) {
1115     bool isReady = true;
1116     if (!isFlush) {
1117       int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
1118       isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
1119         && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
1120         || m_sReoderingStatus.iMinPOC < iLastPOC;
1121     }
1122     if (isReady) {
1123       m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1124 #if defined (_DEBUG)
1125 #ifdef _MOTION_VECTOR_DUMP_
1126       fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1127                m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1128 #endif
1129 #endif
1130       memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1131       ppDst[0] = pDstInfo->pDst[0];
1132       ppDst[1] = pDstInfo->pDst[1];
1133       ppDst[2] = pDstInfo->pDst[2];
1134       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1135       if (pPicBuff != NULL) {
1136         PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1137         --pPic->iRefCount;
1138       }
1139       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1140       m_sReoderingStatus.iMinPOC = IMinInt32;
1141       --m_sReoderingStatus.iNumOfPicts;
1142     }
1143   }
1144 }
1145 
1146 //if there is no b-frame, no ordering based on values of POCs is necessary.
1147 //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)1148 void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo)
1149 {
1150   int32_t firstValidIdx = -1;
1151   uint32_t uiDecodingTimeStamp = 0;
1152   for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1153     if (m_sPictInfoList[i].iPOC != IMinInt32) {
1154       uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1155       m_sReoderingStatus.iPictInfoIndex = i;
1156       firstValidIdx = i;
1157       break;
1158     }
1159   }
1160   for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1161     if (i == firstValidIdx) continue;
1162     if (m_sPictInfoList[i].iPOC != IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
1163       uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1164       m_sReoderingStatus.iPictInfoIndex = i;
1165     }
1166   }
1167   if (uiDecodingTimeStamp > 0) {
1168 #if defined (_DEBUG)
1169 #ifdef _MOTION_VECTOR_DUMP_
1170     fprintf(stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC,
1171       uiDecodingTimeStamp);
1172 #endif
1173 #endif
1174     m_sReoderingStatus.iLastWrittenPOC = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC;
1175     memcpy(pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof(SBufferInfo));
1176     ppDst[0] = pDstInfo->pDst[0];
1177     ppDst[1] = pDstInfo->pDst[1];
1178     ppDst[2] = pDstInfo->pDst[2];
1179     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1180     if (pCtx || m_pPicBuff) {
1181       PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1182       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1183       --pPic->iRefCount;
1184     }
1185     if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP) {
1186       --m_sReoderingStatus.iLastGOPRemainPicts;
1187       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1188     }
1189     --m_sReoderingStatus.iNumOfPicts;
1190   }
1191   return;
1192 }
1193 
ReorderPicturesInDisplay(PWelsDecoderContext pDecContext,unsigned char ** ppDst,SBufferInfo * pDstInfo)1194 DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay(PWelsDecoderContext pDecContext, unsigned char** ppDst,
1195   SBufferInfo* pDstInfo) {
1196   DECODING_STATE iRet = dsErrorFree;
1197   if (pDecContext->pSps != NULL) {
1198     m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
1199     if (!m_bIsBaseline) {
1200       if (pDstInfo->iBufferStatus == 1) {
1201         if (m_sReoderingStatus.iLastGOPRemainPicts == 0 && pDecContext->pSliceHeader->eSliceType == B_SLICE &&
1202             pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) {
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           ppDst[0] = pDstInfo->pDst[0];
1205           ppDst[1] = pDstInfo->pDst[1];
1206           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           return iRet;
1214         }
1215         BufferingReadyPicture(pDecContext, ppDst, pDstInfo);
1216         if (!m_sReoderingStatus.bHasBSlice && m_sReoderingStatus.iNumOfPicts > 1) {
1217           ReleaseBufferedReadyPictureNoReorder (pDecContext, ppDst, pDstInfo);
1218         }
1219         else {
1220           ReleaseBufferedReadyPictureReorder (pDecContext, ppDst, pDstInfo);
1221         }
1222       }
1223     }
1224   }
1225   return iRet;
1226 }
1227 
DecodeParser(const unsigned char * kpSrc,const int kiSrcLen,SParserBsInfo * pDstInfo)1228 DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1229   PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1230 
1231   if (pDecContext == NULL || pDecContext->pParam == NULL) {
1232     if (m_pWelsTrace != NULL) {
1233       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1234     }
1235     return dsInitialOptExpected;
1236   }
1237 
1238   if (!pDecContext->pParam->bParseOnly) {
1239     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1240     pDecContext->iErrorCode |= dsInvalidArgument;
1241     return dsInvalidArgument;
1242   }
1243   int64_t iEnd, iStart = WelsTime();
1244   if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1245     if (ResetDecoder (pDecContext))
1246       return dsOutOfMemory;
1247 
1248     return dsErrorFree;
1249   }
1250   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     pDecContext->bEndOfStreamFlag = false;
1258   } 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     pDecContext->bEndOfStreamFlag = true;
1262     pDecContext->bInstantDecFlag = true;
1263   }
1264 
1265   pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1266   pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1267   pDecContext->iFeedbackNalRefIdc = -1; //initialize
1268   if (!pDecContext->bFramePending) { //frame complete
1269     pDecContext->pParserBsInfo->iNalNum = 0;
1270     memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1271   }
1272   pDstInfo->iNalNum = 0;
1273   pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1274   if (pDstInfo) {
1275     pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1276     pDstInfo->uiOutBsTimeStamp = 0;
1277   } else {
1278     pDecContext->uiTimeStamp = 0;
1279   }
1280   WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1281   if (pDecContext->iErrorCode & dsOutOfMemory) {
1282     if (ResetDecoder (pDecContext))
1283       return dsOutOfMemory;
1284     return dsErrorFree;
1285   }
1286 
1287   if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1288     memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1289 
1290     if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1291       pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1292       if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1293         ResetDecStatNums (pDecContext->pDecoderStatistics);
1294         pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1295       }
1296     }
1297   }
1298 
1299   pDecContext->bInstantDecFlag = false; //reset no-delay flag
1300 
1301   if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1302     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1303     pDecContext->bPrintFrameErrorTraceFlag = false;
1304   }
1305   iEnd = WelsTime();
1306   pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1307   return (DECODING_STATE)pDecContext->iErrorCode;
1308 }
1309 
DecodeFrame(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,int * pStride,int & iWidth,int & iHeight)1310 DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1311     const int kiSrcLen,
1312     unsigned char** ppDst,
1313     int* pStride,
1314     int& iWidth,
1315     int& iHeight) {
1316   DECODING_STATE eDecState = dsErrorFree;
1317   SBufferInfo    DstInfo;
1318 
1319   memset (&DstInfo, 0, sizeof (SBufferInfo));
1320   DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1321   DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1322   DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1323   DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1324 
1325   eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1326   if (eDecState == dsErrorFree) {
1327     pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1328     pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1329     iWidth     = DstInfo.UsrData.sSystemBuffer.iWidth;
1330     iHeight    = DstInfo.UsrData.sSystemBuffer.iHeight;
1331   }
1332 
1333   return eDecState;
1334 }
1335 
DecodeFrameEx(const unsigned char * kpSrc,const int kiSrcLen,unsigned char * pDst,int iDstStride,int & iDstLen,int & iWidth,int & iHeight,int & iColorFormat)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     int& iColorFormat) {
1344   DECODING_STATE state = dsErrorFree;
1345 
1346   return state;
1347 }
1348 
ParseAccessUnit(SWelsDecoderThreadCTX & sThreadCtx)1349 DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1350   sThreadCtx.pCtx->bHasNewSps = false;
1351   sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1352   sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1353   sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1354   bool bPicBuffChanged = false;
1355   if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1356     CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1357     sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1358     if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1359       bPicBuffChanged = true;
1360       sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1361       sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1362       sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1363       sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1364     }
1365   }
1366 
1367   //if threadCount > 1, then each thread must contain exact one complete frame.
1368   if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1369     sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0;
1370     sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0;
1371   }
1372 
1373   int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1374                                       &sThreadCtx.sDstInfo);
1375 
1376   int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1377   if (ERR_NONE != iErr) {
1378     return (DECODING_STATE) (iRet | iErr);
1379   }
1380   if (sThreadCtx.pCtx->bNewSeqBegin) {
1381     m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1382   } else if (bPicBuffChanged) {
1383     InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1384   }
1385   if (!sThreadCtx.pCtx->bNewSeqBegin && m_pLastDecThrCtx != NULL) {
1386     sThreadCtx.pCtx->sFrameCrop = m_pLastDecThrCtx->pCtx->pSps->sFrameCrop;
1387   }
1388   m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1389   m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1390   return (DECODING_STATE)iErr;
1391 }
1392 /*
1393 * Run decoding picture in separate thread.
1394 */
1395 
ThreadDecodeFrameInternal(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)1396 int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1397     SBufferInfo* pDstInfo) {
1398   int state = dsErrorFree;
1399   int32_t i, j;
1400   int32_t signal = 0;
1401 
1402   //serial using of threads
1403   if (m_DecCtxActiveCount < m_iThreadCount) {
1404     signal = m_DecCtxActiveCount;
1405   } else {
1406     signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1407   }
1408 
1409   WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1410 
1411   for (i = 0; i < m_DecCtxActiveCount; ++i) {
1412     if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1413       m_pDecThrCtxActive[i] = NULL;
1414       for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1415         m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1416         m_pDecThrCtxActive[j + 1] = NULL;
1417       }
1418       --m_DecCtxActiveCount;
1419       break;
1420     }
1421   }
1422 
1423   m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1424   if (m_pLastDecThrCtx != NULL) {
1425     m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1426   }
1427   m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1428   m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1429   m_pDecThrCtx[signal].ppDst = ppDst;
1430   memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1431 
1432   ParseAccessUnit (m_pDecThrCtx[signal]);
1433   if (m_iThreadCount > 1) {
1434     m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1435   }
1436   m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1437   RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1438 
1439   // wait early picture
1440   if (m_DecCtxActiveCount >= m_iThreadCount) {
1441     WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1442     RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1443   }
1444   return state;
1445 }
1446 
1447 } // namespace WelsDec
1448 
1449 
1450 using namespace WelsDec;
1451 /*
1452 *       WelsGetDecoderCapability
1453 *       @return: DecCapability information
1454 */
WelsGetDecoderCapability(SDecoderCapability * pDecCapability)1455 int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1456   memset (pDecCapability, 0, sizeof (SDecoderCapability));
1457   pDecCapability->iProfileIdc = 66; //Baseline
1458   pDecCapability->iProfileIop = 0xE0; //11100000b
1459   pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1460   pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1461   pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1462   pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1463   pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1464   pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1465   pDecCapability->bRedPicCap = 0; //not support redundant pic
1466 
1467   return ERR_NONE;
1468 }
1469 /* WINAPI is indeed in prefix due to sync to application layer callings!! */
1470 
1471 /*
1472 *   WelsCreateDecoder
1473 *   @return:    success in return 0, otherwise failed.
1474 */
WelsCreateDecoder(ISVCDecoder ** ppDecoder)1475 long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1476 
1477   if (NULL == ppDecoder) {
1478     return ERR_INVALID_PARAMETERS;
1479   }
1480 
1481   *ppDecoder = new CWelsDecoder();
1482 
1483   if (NULL == *ppDecoder) {
1484     return ERR_MALLOC_FAILED;
1485   }
1486 
1487   return ERR_NONE;
1488 }
1489 
1490 /*
1491 *   WelsDestroyDecoder
1492 */
WelsDestroyDecoder(ISVCDecoder * pDecoder)1493 void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1494   if (NULL != pDecoder) {
1495     delete (CWelsDecoder*)pDecoder;
1496   }
1497 }
1498