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