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       ReleaseBufferedReadyPicture (NULL, ppDst, pDstInfo);
701       SET_EVENT (&m_sReleaseBufferEvent);
702     }
703     return (DECODING_STATE)iRet;
704   }
705   //SBufferInfo sTmpBufferInfo;
706   //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
707   iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
708   //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
709   //ppTmpDst[0] = ppDst[0];
710   //ppTmpDst[1] = ppDst[1];
711   //ppTmpDst[2] = ppDst[2];
712   iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
713   //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
714   //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
715   //ppDst[0] = ppTmpDst[0];
716   //ppDst[1] = ppTmpDst[1];
717   //ppDst[2] = ppTmpDst[2];
718   //}
719   return (DECODING_STATE)iRet;
720 }
721 
DecodeFrame2WithCtx(PWelsDecoderContext pDecContext,const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)722 DECODING_STATE CWelsDecoder::DecodeFrame2WithCtx (PWelsDecoderContext pDecContext, const unsigned char* kpSrc,
723     const int kiSrcLen,
724     unsigned char** ppDst,
725     SBufferInfo* pDstInfo) {
726   if (pDecContext == NULL || pDecContext->pParam == NULL) {
727     if (m_pWelsTrace != NULL) {
728       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
729     }
730     return dsInitialOptExpected;
731   }
732 
733   if (pDecContext->pParam->bParseOnly) {
734     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
735     pDecContext->iErrorCode |= dsInvalidArgument;
736     return dsInvalidArgument;
737   }
738   if (CheckBsBuffer (pDecContext, kiSrcLen)) {
739     if (ResetDecoder (pDecContext))
740       return dsOutOfMemory;
741 
742     return dsErrorFree;
743   }
744   if (kiSrcLen > 0 && kpSrc != NULL) {
745 #ifdef OUTPUT_BIT_STREAM
746     if (m_pFBS) {
747       WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
748       WelsFflush (m_pFBS);
749     }
750     if (m_pFBSSize) {
751       WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
752       WelsFflush (m_pFBSSize);
753     }
754 #endif//OUTPUT_BIT_STREAM
755     pDecContext->bEndOfStreamFlag = false;
756     if (GetThreadCount (pDecContext) <= 0) {
757       pDecContext->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
758     }
759   } else {
760     //For application MODE, the error detection should be added for safe.
761     //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
762     pDecContext->bEndOfStreamFlag = true;
763     pDecContext->bInstantDecFlag = true;
764   }
765 
766   int64_t iStart, iEnd;
767   iStart = WelsTime();
768 
769   if (GetThreadCount (pDecContext) <= 1) {
770     ppDst[0] = ppDst[1] = ppDst[2] = NULL;
771   }
772   pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
773   pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
774   unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
775   if (GetThreadCount (pDecContext) <= 1) {
776     memset (pDstInfo, 0, sizeof (SBufferInfo));
777   }
778   pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
779 #ifdef LONG_TERM_REF
780   pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
781   pDecContext->bCurAuContainLtrMarkSeFlag = false;
782   pDecContext->iFrameNumOfAuMarkedLtr = 0;
783   pDecContext->iFrameNum = -1; //initialize
784 #endif
785 
786   pDecContext->iFeedbackTidInAu = -1; //initialize
787   pDecContext->iFeedbackNalRefIdc = -1; //initialize
788   if (pDstInfo) {
789     pDstInfo->uiOutYuvTimeStamp = 0;
790     pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
791   } else {
792     pDecContext->uiTimeStamp = 0;
793   }
794   WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, ppDst,
795                 pDstInfo, NULL); //iErrorCode has been modified in this function
796   pDecContext->bInstantDecFlag = false; //reset no-delay flag
797   if (pDecContext->iErrorCode) {
798     EWelsNalUnitType eNalType =
799       NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
800 
801     eNalType = pDecContext->sCurNalHead.eNalUnitType;
802     if (pDecContext->iErrorCode & dsOutOfMemory) {
803       if (ResetDecoder (pDecContext)) {
804         return dsOutOfMemory;
805       }
806       return dsErrorFree;
807     }
808     if (pDecContext->iErrorCode & dsRefListNullPtrs) {
809       if (ResetDecoder (pDecContext)) {
810         return dsRefListNullPtrs;
811       }
812       return dsErrorFree;
813     }
814     if ((pDecContext->iErrorCode & (dsBitstreamError | dsDataErrorConcealed)) && pDecContext->eSliceType == B_SLICE) {
815       if (ResetDecoder (pDecContext)) {
816         pDstInfo->iBufferStatus = 0;
817         return (DECODING_STATE)pDecContext->iErrorCode;
818       }
819       return dsErrorFree;
820     }
821     //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
822     if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
823         (VIDEO_BITSTREAM_AVC == pDecContext->eVideoType)) {
824       if (pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
825 #ifdef LONG_TERM_REF
826         pDecContext->bParamSetsLostFlag = true;
827 #else
828         pDecContext->bReferenceLostAtT0Flag = true;
829 #endif
830       }
831     }
832 
833     if (pDecContext->bPrintFrameErrorTraceFlag) {
834       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
835                pDecContext->iErrorCode);
836       pDecContext->bPrintFrameErrorTraceFlag = false;
837     } else {
838       pDecContext->iIgnoredErrorInfoPacketCount++;
839       if (pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
840         WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
841         pDecContext->iIgnoredErrorInfoPacketCount = 0;
842       }
843     }
844     if ((pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
845       //TODO after dec status updated
846       pDecContext->iErrorCode |= dsDataErrorConcealed;
847 
848       pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
849       if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
850         ResetDecStatNums (pDecContext->pDecoderStatistics);
851         pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
852       }
853       int32_t iMbConcealedNum = pDecContext->iMbEcedNum + pDecContext->iMbEcedPropNum;
854       pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->iMbNum == 0 ?
855           (pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
856                 pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
857                       iMbConcealedNum * 100) / pDecContext->iMbNum));
858       pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->iMbNum == 0 ?
859           (pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
860                 pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
861                       pDecContext->iMbEcedPropNum * 100) / pDecContext->iMbNum));
862       pDecContext->pDecoderStatistics->uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
863       pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
864           pDecContext->pDecoderStatistics->uiAvgEcRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
865       pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
866           pDecContext->pDecoderStatistics->uiAvgEcPropRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
867     }
868     iEnd = WelsTime();
869     pDecContext->dDecTime += (iEnd - iStart) / 1e3;
870 
871     OutputStatisticsLog (*pDecContext->pDecoderStatistics);
872 
873     if (GetThreadCount (pDecContext) >= 1) {
874       WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE);
875       RESET_EVENT (&m_sBufferingEvent);
876       BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
877       SET_EVENT (&m_sBufferingEvent);
878     } else {
879       ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
880     }
881 
882     return (DECODING_STATE)pDecContext->iErrorCode;
883   }
884   // else Error free, the current codec works well
885 
886   if (pDstInfo->iBufferStatus == 1) {
887 
888     pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
889     if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
890       ResetDecStatNums (pDecContext->pDecoderStatistics);
891       pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
892     }
893 
894     OutputStatisticsLog (*pDecContext->pDecoderStatistics);
895   }
896   iEnd = WelsTime();
897   pDecContext->dDecTime += (iEnd - iStart) / 1e3;
898 
899   if (GetThreadCount (pDecContext) >= 1) {
900     WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE);
901     RESET_EVENT (&m_sBufferingEvent);
902     BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
903     SET_EVENT (&m_sBufferingEvent);
904   } else {
905     ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
906   }
907   return dsErrorFree;
908 }
909 
DecodeFrame2(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)910 DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
911     const int kiSrcLen,
912     unsigned char** ppDst,
913     SBufferInfo* pDstInfo) {
914   PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
915   return DecodeFrame2WithCtx (pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo);
916 }
917 
FlushFrame(unsigned char ** ppDst,SBufferInfo * pDstInfo)918 DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
919     SBufferInfo* pDstInfo) {
920   bool bEndOfStreamFlag = true;
921   if (m_iThreadCount <= 1) {
922     for (int32_t j = 0; j < m_iCtxCount; ++j) {
923       if (!m_pDecThrCtx[j].pCtx->bEndOfStreamFlag) {
924         bEndOfStreamFlag = false;
925       }
926     }
927   }
928   if (bEndOfStreamFlag && m_sReoderingStatus.iNumOfPicts > 0) {
929     m_sReoderingStatus.iMinPOC = IMinInt32;
930     if (m_bIsBaseline) {
931       uint32_t uiDecodingTimeStamp = 0;
932       int32_t firstValidIdx = -1;
933       for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
934         if (m_sPictInfoList[i].iPOC > IMinInt32) {
935           uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
936           m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
937           m_sReoderingStatus.iPictInfoIndex = i;
938           firstValidIdx = i;
939           break;
940         }
941       }
942       for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
943         if (i == firstValidIdx) continue;
944         if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
945           uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
946           m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
947           m_sReoderingStatus.iPictInfoIndex = i;
948         }
949       }
950     } else {
951       int32_t firstValidIdx = -1;
952       for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
953         if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
954           m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
955           m_sReoderingStatus.iPictInfoIndex = i;
956           firstValidIdx = i;
957           break;
958         }
959       }
960       for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
961         if (i == firstValidIdx) continue;
962         if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) {
963           m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
964           m_sReoderingStatus.iPictInfoIndex = i;
965         }
966       }
967     }
968   }
969   if (m_sReoderingStatus.iMinPOC > IMinInt32) {
970     m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
971 #if defined (_DEBUG)
972 #ifdef _MOTION_VECTOR_DUMP_
973     fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
974              m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
975 #endif
976 #endif
977     memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
978     ppDst[0] = pDstInfo->pDst[0];
979     ppDst[1] = pDstInfo->pDst[1];
980     ppDst[2] = pDstInfo->pDst[2];
981     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
982     PPicBuff pPicBuff = m_iThreadCount <= 1 ? m_pDecThrCtx[0].pCtx->pPicBuff : m_pPicBuff;
983     if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx < pPicBuff->iCapacity) {
984       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
985       --pPic->iRefCount;
986     }
987     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
988     m_sReoderingStatus.iMinPOC = IMinInt32;
989     --m_sReoderingStatus.iNumOfPicts;
990   }
991 
992   return dsErrorFree;
993 }
994 
OutputStatisticsLog(SDecoderStatistics & sDecoderStatistics)995 void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
996   if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
997       && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
998     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
999              "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
1000               uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
1001               uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
1002               uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
1003               iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
1004               uiProfile=%d, uiLevel=%d, \
1005               iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
1006              sDecoderStatistics.uiWidth,
1007              sDecoderStatistics.uiHeight,
1008              sDecoderStatistics.fAverageFrameSpeedInMs,
1009              sDecoderStatistics.fActualAverageFrameSpeedInMs,
1010 
1011              sDecoderStatistics.uiDecodedFrameCount,
1012              sDecoderStatistics.uiResolutionChangeTimes,
1013              sDecoderStatistics.uiIDRCorrectNum,
1014 
1015              sDecoderStatistics.uiAvgEcRatio,
1016              sDecoderStatistics.uiAvgEcPropRatio,
1017              sDecoderStatistics.uiEcIDRNum,
1018              sDecoderStatistics.uiEcFrameNum,
1019 
1020              sDecoderStatistics.uiIDRLostNum,
1021              sDecoderStatistics.uiFreezingIDRNum,
1022              sDecoderStatistics.uiFreezingNonIDRNum,
1023              sDecoderStatistics.iAvgLumaQp,
1024 
1025              sDecoderStatistics.iSpsReportErrorNum,
1026              sDecoderStatistics.iSubSpsReportErrorNum,
1027              sDecoderStatistics.iPpsReportErrorNum,
1028              sDecoderStatistics.iSpsNoExistNalNum,
1029              sDecoderStatistics.iSubSpsNoExistNalNum,
1030              sDecoderStatistics.iPpsNoExistNalNum,
1031 
1032              sDecoderStatistics.uiProfile,
1033              sDecoderStatistics.uiLevel,
1034 
1035              sDecoderStatistics.iCurrentActiveSpsId,
1036              sDecoderStatistics.iCurrentActivePpsId);
1037   }
1038 }
1039 
BufferingReadyPicture(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo)1040 void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst,
1041     SBufferInfo* pDstInfo) {
1042   if (pDstInfo->iBufferStatus == 0) {
1043     return;
1044   }
1045   m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83;
1046   if (!m_bIsBaseline) {
1047     if (m_sReoderingStatus.iNumOfPicts && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb
1048         && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) {
1049       m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts;
1050 
1051       for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1052         if (m_sPictInfoList[i].iPOC > IMinInt32) {
1053           m_sPictInfoList[i].bLastGOP = true;
1054         }
1055       }
1056     } else {
1057       if (m_sReoderingStatus.iNumOfPicts > 0) {
1058         //This can happen when decoder moves to next GOP without being able to decoder first picture PicOrderCntLsb = 0
1059         bool hasGOPChanged = false;
1060         for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1061           if (m_sPictInfoList[i].iPOC == pCtx->pSliceHeader->iPicOrderCntLsb) {
1062             hasGOPChanged = true;
1063             break;
1064           }
1065         }
1066         if (hasGOPChanged) {
1067           m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts;
1068           for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1069             if (m_sPictInfoList[i].iPOC > IMinInt32) {
1070               m_sPictInfoList[i].bLastGOP = true;
1071             }
1072           }
1073         }
1074       }
1075     }
1076   }
1077   for (int32_t i = 0; i < 16; ++i) {
1078     if (m_sPictInfoList[i].iPOC == IMinInt32) {
1079       memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
1080       m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb;
1081       m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp;
1082       m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
1083       if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount;
1084       m_sPictInfoList[i].bLastGOP = false;
1085       m_iLastBufferedIdx = i;
1086       pDstInfo->iBufferStatus = 0;
1087       ++m_sReoderingStatus.iNumOfPicts;
1088       if (i > m_sReoderingStatus.iLargestBufferedPicIndex) {
1089         m_sReoderingStatus.iLargestBufferedPicIndex = i;
1090       }
1091       break;
1092     }
1093   }
1094 }
1095 
ReleaseBufferedReadyPicture(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo)1096 void CWelsDecoder::ReleaseBufferedReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst,
1097     SBufferInfo* pDstInfo) {
1098   PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1099   if (pCtx == NULL && m_iThreadCount <= 1) {
1100     pCtx = m_pDecThrCtx[0].pCtx;
1101   }
1102   if (!m_bIsBaseline && m_sReoderingStatus.iLastGOPRemainPicts > 0) {
1103     m_sReoderingStatus.iMinPOC = IMinInt32;
1104     int32_t firstValidIdx = -1;
1105     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1106       if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) {
1107         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1108         m_sReoderingStatus.iPictInfoIndex = i;
1109         firstValidIdx = i;
1110         break;
1111       }
1112     }
1113     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1114       if (i == firstValidIdx) continue;
1115       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC
1116           && m_sPictInfoList[i].bLastGOP) {
1117         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1118         m_sReoderingStatus.iPictInfoIndex = i;
1119       }
1120     }
1121     m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1122 #if defined (_DEBUG)
1123 #ifdef _MOTION_VECTOR_DUMP_
1124     fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1125              m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1126 #endif
1127 #endif
1128     memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1129     ppDst[0] = pDstInfo->pDst[0];
1130     ppDst[1] = pDstInfo->pDst[1];
1131     ppDst[2] = pDstInfo->pDst[2];
1132     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1133     PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1134     --pPic->iRefCount;
1135     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1136     m_sReoderingStatus.iMinPOC = IMinInt32;
1137     --m_sReoderingStatus.iNumOfPicts;
1138     --m_sReoderingStatus.iLastGOPRemainPicts;
1139     if (m_sReoderingStatus.iLastGOPRemainPicts == 0) {
1140       m_sReoderingStatus.iLastWrittenPOC = IMinInt32;
1141     }
1142     return;
1143   }
1144   if (m_sReoderingStatus.iNumOfPicts && m_bIsBaseline) {
1145     uint32_t uiDecodingTimeStamp = 0;
1146     int32_t firstValidIdx = -1;
1147     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1148       if (m_sPictInfoList[i].iPOC > IMinInt32) {
1149         uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1150         m_sReoderingStatus.iPictInfoIndex = i;
1151         firstValidIdx = i;
1152         break;
1153       }
1154     }
1155     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1156       if (i == firstValidIdx) continue;
1157       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
1158         uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1159         m_sReoderingStatus.iPictInfoIndex = i;
1160       }
1161     }
1162     if (uiDecodingTimeStamp > 0) {
1163 #if defined (_DEBUG)
1164 #ifdef _MOTION_VECTOR_DUMP_
1165       fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC,
1166                uiDecodingTimeStamp);
1167 #endif
1168 #endif
1169       memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1170       ppDst[0] = pDstInfo->pDst[0];
1171       ppDst[1] = pDstInfo->pDst[1];
1172       ppDst[2] = pDstInfo->pDst[2];
1173       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1174       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1175       --pPic->iRefCount;
1176       --m_sReoderingStatus.iNumOfPicts;
1177     }
1178     return;
1179   }
1180   if (m_sReoderingStatus.iNumOfPicts > 0) {
1181     m_sReoderingStatus.iMinPOC = IMinInt32;
1182     int32_t firstValidIdx = -1;
1183     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1184       if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
1185         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1186         m_sReoderingStatus.iPictInfoIndex = i;
1187         firstValidIdx = i;
1188         break;
1189       }
1190     }
1191     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1192       if (i == firstValidIdx) continue;
1193       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) {
1194         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1195         m_sReoderingStatus.iPictInfoIndex = i;
1196       }
1197     }
1198   }
1199   if (m_sReoderingStatus.iMinPOC > IMinInt32) {
1200     int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
1201     bool isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
1202                     && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
1203                    || m_sReoderingStatus.iMinPOC < iLastPOC;
1204     if (isReady) {
1205       m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1206 #if defined (_DEBUG)
1207 #ifdef _MOTION_VECTOR_DUMP_
1208       fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1209                m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1210 #endif
1211 #endif
1212       memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1213       ppDst[0] = pDstInfo->pDst[0];
1214       ppDst[1] = pDstInfo->pDst[1];
1215       ppDst[2] = pDstInfo->pDst[2];
1216       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1217       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1218       --pPic->iRefCount;
1219       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1220       m_sReoderingStatus.iMinPOC = IMinInt32;
1221       --m_sReoderingStatus.iNumOfPicts;
1222     }
1223   }
1224 }
1225 
ReorderPicturesInDisplay(PWelsDecoderContext pDecContext,unsigned char ** ppDst,SBufferInfo * pDstInfo)1226 DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (PWelsDecoderContext pDecContext, unsigned char** ppDst,
1227     SBufferInfo* pDstInfo) {
1228   DECODING_STATE iRet = dsErrorFree;
1229   if ((pDstInfo->iBufferStatus == 1) && (pDecContext->pPps->bEntropyCodingModeFlag)) {
1230     m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
1231     if (!m_bIsBaseline) {
1232       BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
1233       ReleaseBufferedReadyPicture (pDecContext, ppDst, pDstInfo);
1234     }
1235   }
1236   return iRet;
1237 }
1238 
DecodeParser(const unsigned char * kpSrc,const int kiSrcLen,SParserBsInfo * pDstInfo)1239 DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1240   PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1241 
1242   if (pDecContext == NULL || pDecContext->pParam == NULL) {
1243     if (m_pWelsTrace != NULL) {
1244       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1245     }
1246     return dsInitialOptExpected;
1247   }
1248 
1249   if (!pDecContext->pParam->bParseOnly) {
1250     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1251     pDecContext->iErrorCode |= dsInvalidArgument;
1252     return dsInvalidArgument;
1253   }
1254   int64_t iEnd, iStart = WelsTime();
1255   if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1256     if (ResetDecoder (pDecContext))
1257       return dsOutOfMemory;
1258 
1259     return dsErrorFree;
1260   }
1261   if (kiSrcLen > 0 && kpSrc != NULL) {
1262 #ifdef OUTPUT_BITSTREAM
1263     if (m_pFBS) {
1264       WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
1265       WelsFflush (m_pFBS);
1266     }
1267 #endif//OUTPUT_BIT_STREAM
1268     pDecContext->bEndOfStreamFlag = false;
1269   } else {
1270     //For application MODE, the error detection should be added for safe.
1271     //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
1272     pDecContext->bEndOfStreamFlag = true;
1273     pDecContext->bInstantDecFlag = true;
1274   }
1275 
1276   pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1277   pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1278   pDecContext->iFeedbackNalRefIdc = -1; //initialize
1279   if (!pDecContext->bFramePending) { //frame complete
1280     pDecContext->pParserBsInfo->iNalNum = 0;
1281     memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1282   }
1283   pDstInfo->iNalNum = 0;
1284   pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1285   if (pDstInfo) {
1286     pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1287     pDstInfo->uiOutBsTimeStamp = 0;
1288   } else {
1289     pDecContext->uiTimeStamp = 0;
1290   }
1291   WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1292   if (pDecContext->iErrorCode & dsOutOfMemory) {
1293     if (ResetDecoder (pDecContext))
1294       return dsOutOfMemory;
1295     return dsErrorFree;
1296   }
1297 
1298   if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1299     memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1300 
1301     if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1302       pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1303       if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1304         ResetDecStatNums (pDecContext->pDecoderStatistics);
1305         pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1306       }
1307     }
1308   }
1309 
1310   pDecContext->bInstantDecFlag = false; //reset no-delay flag
1311 
1312   if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1313     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1314     pDecContext->bPrintFrameErrorTraceFlag = false;
1315   }
1316   iEnd = WelsTime();
1317   pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1318   return (DECODING_STATE)pDecContext->iErrorCode;
1319 }
1320 
DecodeFrame(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,int * pStride,int & iWidth,int & iHeight)1321 DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1322     const int kiSrcLen,
1323     unsigned char** ppDst,
1324     int* pStride,
1325     int& iWidth,
1326     int& iHeight) {
1327   DECODING_STATE eDecState = dsErrorFree;
1328   SBufferInfo    DstInfo;
1329 
1330   memset (&DstInfo, 0, sizeof (SBufferInfo));
1331   DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1332   DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1333   DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1334   DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1335 
1336   eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1337   if (eDecState == dsErrorFree) {
1338     pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1339     pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1340     iWidth     = DstInfo.UsrData.sSystemBuffer.iWidth;
1341     iHeight    = DstInfo.UsrData.sSystemBuffer.iHeight;
1342   }
1343 
1344   return eDecState;
1345 }
1346 
DecodeFrameEx(const unsigned char * kpSrc,const int kiSrcLen,unsigned char * pDst,int iDstStride,int & iDstLen,int & iWidth,int & iHeight,int & iColorFormat)1347 DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
1348     const int kiSrcLen,
1349     unsigned char* pDst,
1350     int iDstStride,
1351     int& iDstLen,
1352     int& iWidth,
1353     int& iHeight,
1354     int& iColorFormat) {
1355   DECODING_STATE state = dsErrorFree;
1356 
1357   return state;
1358 }
1359 
ParseAccessUnit(SWelsDecoderThreadCTX & sThreadCtx)1360 DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1361   sThreadCtx.pCtx->bHasNewSps = false;
1362   sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1363   sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1364   sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1365   bool bPicBuffChanged = false;
1366   if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1367     CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1368     sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1369     if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1370       bPicBuffChanged = true;
1371       sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1372       sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1373       sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1374       sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1375     }
1376   }
1377   int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1378                                       &sThreadCtx.sDstInfo);
1379 
1380   int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1381   if (ERR_NONE != iErr) {
1382     return (DECODING_STATE) (iRet | iErr);
1383   }
1384   if (sThreadCtx.pCtx->bNewSeqBegin) {
1385     m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1386   } else if (bPicBuffChanged) {
1387     InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1388   }
1389   m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1390   m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1391   return (DECODING_STATE)iErr;
1392 }
1393 /*
1394 * Run decoding picture in separate thread.
1395 */
1396 
ThreadDecodeFrameInternal(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)1397 int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1398     SBufferInfo* pDstInfo) {
1399   int state = dsErrorFree;
1400   int32_t i, j;
1401   int32_t signal = 0;
1402 
1403   //serial using of threads
1404   if (m_DecCtxActiveCount < m_iThreadCount) {
1405     signal = m_DecCtxActiveCount;
1406   } else {
1407     signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1408   }
1409 
1410   WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1411 
1412   for (i = 0; i < m_DecCtxActiveCount; ++i) {
1413     if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1414       m_pDecThrCtxActive[i] = NULL;
1415       for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1416         m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1417         m_pDecThrCtxActive[j + 1] = NULL;
1418       }
1419       --m_DecCtxActiveCount;
1420       break;
1421     }
1422   }
1423 
1424   m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1425   if (m_pLastDecThrCtx != NULL) {
1426     m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1427   }
1428   m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1429   m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1430   m_pDecThrCtx[signal].ppDst = ppDst;
1431   memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1432 
1433   ParseAccessUnit (m_pDecThrCtx[signal]);
1434   if (m_iThreadCount > 1) {
1435     m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1436   }
1437   m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1438   RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1439 
1440   // wait early picture
1441   if (m_DecCtxActiveCount >= m_iThreadCount) {
1442     WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1443     RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1444   }
1445   return state;
1446 }
1447 
1448 } // namespace WelsDec
1449 
1450 
1451 using namespace WelsDec;
1452 /*
1453 *       WelsGetDecoderCapability
1454 *       @return: DecCapability information
1455 */
WelsGetDecoderCapability(SDecoderCapability * pDecCapability)1456 int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1457   memset (pDecCapability, 0, sizeof (SDecoderCapability));
1458   pDecCapability->iProfileIdc = 66; //Baseline
1459   pDecCapability->iProfileIop = 0xE0; //11100000b
1460   pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1461   pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1462   pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1463   pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1464   pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1465   pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1466   pDecCapability->bRedPicCap = 0; //not support redundant pic
1467 
1468   return ERR_NONE;
1469 }
1470 /* WINAPI is indeed in prefix due to sync to application layer callings!! */
1471 
1472 /*
1473 *   WelsCreateDecoder
1474 *   @return:    success in return 0, otherwise failed.
1475 */
WelsCreateDecoder(ISVCDecoder ** ppDecoder)1476 long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1477 
1478   if (NULL == ppDecoder) {
1479     return ERR_INVALID_PARAMETERS;
1480   }
1481 
1482   *ppDecoder = new CWelsDecoder();
1483 
1484   if (NULL == *ppDecoder) {
1485     return ERR_MALLOC_FAILED;
1486   }
1487 
1488   return ERR_NONE;
1489 }
1490 
1491 /*
1492 *   WelsDestroyDecoder
1493 */
WelsDestroyDecoder(ISVCDecoder * pDecoder)1494 void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1495   if (NULL != pDecoder) {
1496     delete (CWelsDecoder*)pDecoder;
1497   }
1498 }
1499