History

B-frame decoding support for Main and High Profile with two test cases.

xiaotianshi2 committed 8 years ago

Commit 657d2171 parent e3e838355 files · +17936 −13825Browse files

Showing the changes to codec/decoder/plus/src/welsDecoderExt.cpp (1 of 55 files). Show all

Unified · Split

codec/decoder/plus/src/welsDecoderExt.cpp+1009−860
@@ -1,860 +1,1009 @@
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 "error_concealment.h"
55−
56−#include "measure_time.h"
57−extern "C" {
58−#include "decoder_core.h"
59−#include "manage_dec_ref.h"
60−}
61−#include "error_code.h"
62−#include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
63−#include <time.h>
64−#if defined(_WIN32) /*&& defined(_DEBUG)*/
65−
66−#include <windows.h>
67−#include <stdio.h>
68−#include <stdarg.h>
69−#include <sys/types.h>
70−#else
71−#include <sys/time.h>
72−#endif
73−
74−namespace WelsDec {
75−
76−//////////////////////////////////////////////////////////////////////
77−// Construction/Destruction
78−//////////////////////////////////////////////////////////////////////
79−
80−/***************************************************************************
81−* Description:
82−* class CWelsDecoder constructor function, do initialization and
83−* alloc memory required
84−*
85−* Input parameters: none
86−*
87−* return: none
88−***************************************************************************/
89−CWelsDecoder::CWelsDecoder (void)
90− : m_pDecContext (NULL),
91− m_pWelsTrace (NULL) {
92−#ifdef OUTPUT_BIT_STREAM
93− char chFileName[1024] = { 0 }; //for .264
94− int iBufUsed = 0;
95− int iBufLeft = 1023;
96− int iCurUsed;
97−
98− char chFileNameSize[1024] = { 0 }; //for .len
99− int iBufUsedSize = 0;
100− int iBufLeftSize = 1023;
101− int iCurUsedSize;
102−#endif//OUTPUT_BIT_STREAM
103−
104−
105− m_pWelsTrace = new welsCodecTrace();
106− if (m_pWelsTrace != NULL) {
107− m_pWelsTrace->SetCodecInstance (this);
108− m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
109−
110− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
111− }
112−
113−#ifdef OUTPUT_BIT_STREAM
114− SWelsTime sCurTime;
115−
116− WelsGetTimeOfDay (&sCurTime);
117−
118− iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);
119− iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);
120−
121− iBufUsed += iCurUsed;
122− iBufLeft -= iCurUsed;
123− if (iBufLeft > 0) {
124− iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
125− iBufUsed += iCurUsed;
126− iBufLeft -= iCurUsed;
127− }
128−
129− iBufUsedSize += iCurUsedSize;
130− iBufLeftSize -= iCurUsedSize;
131− if (iBufLeftSize > 0) {
132− iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
133− iBufUsedSize += iCurUsedSize;
134− iBufLeftSize -= iCurUsedSize;
135− }
136−
137− if (iBufLeft > 0) {
138− iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
139− iBufUsed += iCurUsed;
140− iBufLeft -= iCurUsed;
141− }
142−
143− if (iBufLeftSize > 0) {
144− iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
145− WelsGetMillisecond (&sCurTime));
146− iBufUsedSize += iCurUsedSize;
147− iBufLeftSize -= iCurUsedSize;
148− }
149−
150−
151− m_pFBS = WelsFopen (chFileName, "wb");
152− m_pFBSSize = WelsFopen (chFileNameSize, "wb");
153−#endif//OUTPUT_BIT_STREAM
154−
155−}
156−
157−/***************************************************************************
158−* Description:
159−* class CWelsDecoder destructor function, destroy allocced memory
160−*
161−* Input parameters: none
162−*
163−* return: none
164−***************************************************************************/
165−CWelsDecoder::~CWelsDecoder() {
166− if (m_pWelsTrace != NULL) {
167− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
168− }
169−
170− UninitDecoder();
171−
172−#ifdef OUTPUT_BIT_STREAM
173− if (m_pFBS) {
174− WelsFclose (m_pFBS);
175− m_pFBS = NULL;
176− }
177− if (m_pFBSSize) {
178− WelsFclose (m_pFBSSize);
179− m_pFBSSize = NULL;
180− }
181−#endif//OUTPUT_BIT_STREAM
182−
183− if (m_pWelsTrace != NULL) {
184− delete m_pWelsTrace;
185− m_pWelsTrace = NULL;
186− }
187−}
188−
189−long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
190− int iRet = ERR_NONE;
191− if (m_pWelsTrace == NULL) {
192− return cmMallocMemeError;
193− }
194−
195− if (pParam == NULL) {
196− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");
197− return cmInitParaError;
198− }
199−
200− // H.264 decoder initialization,including memory allocation,then open it ready to decode
201− iRet = InitDecoder (pParam);
202− if (iRet)
203− return iRet;
204−
205− return cmResultSuccess;
206−}
207−
208−long CWelsDecoder::Uninitialize() {
209− UninitDecoder();
210−
211− return ERR_NONE;
212−}
213−
214−void CWelsDecoder::UninitDecoder (void) {
215− if (NULL == m_pDecContext)
216− return;
217−
218− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoder(), openh264 codec version = %s.",
219− VERSION_NUMBER);
220−
221− WelsEndDecoder (m_pDecContext);
222−
223− if (m_pDecContext->pMemAlign != NULL) {
224− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
225− "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
226− m_pDecContext->pMemAlign->WelsGetMemoryUsage());
227− delete m_pDecContext->pMemAlign;
228− m_pDecContext->pMemAlign = NULL;
229− }
230−
231− if (NULL != m_pDecContext) {
232− WelsFree (m_pDecContext, "m_pDecContext");
233−
234− m_pDecContext = NULL;
235− }
236−
237−}
238−
239−// the return value of this function is not suitable, it need report failure info to upper layer.
240−int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
241−
242− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
243− "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
244− VERSION_NUMBER, (int32_t)pParam->bParseOnly);
245−
246− //reset decoder context
247− if (m_pDecContext) //free
248− UninitDecoder();
249− m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
250− if (NULL == m_pDecContext)
251− return cmMallocMemeError;
252− int32_t iCacheLineSize = 16; // on chip cache line size in byte
253− m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize);
254− WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pMemAlign), UninitDecoder())
255−
256− //fill in default value into context
257− WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
258−
259− //check param and update decoder context
260− m_pDecContext->pParam = (SDecodingParam*) m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
261− "SDecodingParam");
262− WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder());
263− int32_t iRet = DecoderConfigParam (m_pDecContext, pParam);
264− WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
265−
266− //init decoder
267− WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx),
268− UninitDecoder())
269−
270− return cmResultSuccess;
271−}
272−
273−int32_t CWelsDecoder::ResetDecoder() {
274− // TBC: need to be modified when context and trace point are null
275− if (m_pDecContext != NULL && m_pWelsTrace != NULL) {
276− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",
277− m_pDecContext->iErrorCode);
278− SDecodingParam sPrevParam;
279− memcpy (&sPrevParam, m_pDecContext->pParam, sizeof (SDecodingParam));
280−
281− WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoder (&sPrevParam), UninitDecoder());
282− } else if (m_pWelsTrace != NULL) {
283− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
284− }
285− return ERR_INFO_UNINIT;
286−}
287−
288−/*
289− * Set Option
290− */
291−long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
292− int iVal = 0;
293−
294− if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
295− eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
296− return dsInitialOptExpected;
297− if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded
298− if (pOption == NULL)
299− return cmInitParaError;
300−
301− iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag
302−
303− m_pDecContext->bEndOfStreamFlag = iVal ? true : false;
304−
305− return cmResultSuccess;
306− } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status
307− if (pOption == NULL)
308− return cmInitParaError;
309−
310− iVal = * ((int*)pOption); // int value for error concealment idc
311− iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
312− if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t) ERROR_CON_DISABLE)) {
313− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
314− "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
315− return cmInitParaError;
316− }
317−
318− m_pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC) iVal;
319− InitErrorCon (m_pDecContext);
320− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
321− "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal);
322−
323− return cmResultSuccess;
324− } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
325− if (m_pWelsTrace) {
326− uint32_t level = * ((uint32_t*)pOption);
327− m_pWelsTrace->SetTraceLevel (level);
328− }
329− return cmResultSuccess;
330− } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
331− if (m_pWelsTrace) {
332− WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
333− m_pWelsTrace->SetTraceCallback (callback);
334− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
335− "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.",
336− callback);
337− }
338− return cmResultSuccess;
339− } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
340− if (m_pWelsTrace) {
341− void* ctx = * ((void**)pOption);
342− m_pWelsTrace->SetTraceCallbackContext (ctx);
343− }
344− return cmResultSuccess;
345− } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
346− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
347− "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
348− return cmInitParaError;
349− } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
350− if (pOption) {
351− m_pDecContext->sDecoderStatistics.iStatisticsLogInterval = (* ((unsigned int*)pOption));
352− return cmResultSuccess;
353− }
354− } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
355− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
356− "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
357− return cmInitParaError;
358− }
359− return cmInitParaError;
360−}
361−
362−/*
363− * Get Option
364− */
365−long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
366− int iVal = 0;
367−
368− if (m_pDecContext == NULL)
369− return cmInitExpected;
370−
371− if (pOption == NULL)
372− return cmInitParaError;
373−
374− if (DECODER_OPTION_END_OF_STREAM == eOptID) {
375− iVal = m_pDecContext->bEndOfStreamFlag;
376− * ((int*)pOption) = iVal;
377− return cmResultSuccess;
378− }
379−#ifdef LONG_TERM_REF
380− else if (DECODER_OPTION_IDR_PIC_ID == eOptID) {
381− iVal = m_pDecContext->uiCurIdrPicId;
382− * ((int*)pOption) = iVal;
383− return cmResultSuccess;
384− } else if (DECODER_OPTION_FRAME_NUM == eOptID) {
385− iVal = m_pDecContext->iFrameNum;
386− * ((int*)pOption) = iVal;
387− return cmResultSuccess;
388− } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) {
389− iVal = m_pDecContext->bCurAuContainLtrMarkSeFlag;
390− * ((int*)pOption) = iVal;
391− return cmResultSuccess;
392− } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) {
393− iVal = m_pDecContext->iFrameNumOfAuMarkedLtr;
394− * ((int*)pOption) = iVal;
395− return cmResultSuccess;
396− }
397−#endif
398− else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU
399− iVal = m_pDecContext->iFeedbackVclNalInAu;
400− * ((int*)pOption) = iVal;
401− return cmResultSuccess;
402− } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID
403− iVal = m_pDecContext->iFeedbackTidInAu;
404− * ((int*)pOption) = iVal;
405− return cmResultSuccess;
406− } else if (DECODER_OPTION_IS_REF_PIC == eOptID) {
407− iVal = m_pDecContext->iFeedbackNalRefIdc;
408− if (iVal > 0)
409− iVal = 1;
410− * ((int*)pOption) = iVal;
411− return cmResultSuccess;
412− } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) {
413− iVal = (int) m_pDecContext->pParam->eEcActiveIdc;
414− * ((int*)pOption) = iVal;
415− return cmResultSuccess;
416− } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
417− SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
418−
419− memcpy (pDecoderStatistics, &m_pDecContext->sDecoderStatistics, sizeof (SDecoderStatistics));
420−
421− if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount != 0) { //not original status
422− pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
423− (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
424− pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
425− (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount + m_pDecContext->sDecoderStatistics.uiFreezingIDRNum +
426− m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
427− }
428− return cmResultSuccess;
429− } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
430− if (pOption) {
431− iVal = m_pDecContext->sDecoderStatistics.iStatisticsLogInterval;
432− * ((unsigned int*)pOption) = iVal;
433− return cmResultSuccess;
434− }
435− } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
436− PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
437− memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
438− if (!m_pDecContext->pSps) {
439− return cmInitExpected;
440− } else {
441− pVuiSarInfo->uiSarWidth = m_pDecContext->pSps->sVui.uiSarWidth;
442− pVuiSarInfo->uiSarHeight = m_pDecContext->pSps->sVui.uiSarHeight;
443− pVuiSarInfo->bOverscanAppropriateFlag = m_pDecContext->pSps->sVui.bOverscanAppropriateFlag;
444− return cmResultSuccess;
445− }
446− } else if (DECODER_OPTION_PROFILE == eOptID) {
447− if (!m_pDecContext->pSps) {
448− return cmInitExpected;
449− }
450− iVal = (int) m_pDecContext->pSps->uiProfileIdc;
451− * ((int*)pOption) = iVal;
452− return cmResultSuccess;
453− } else if (DECODER_OPTION_LEVEL == eOptID) {
454− if (!m_pDecContext->pSps) {
455− return cmInitExpected;
456− }
457− iVal = (int) m_pDecContext->pSps->uiLevelIdc;
458− * ((int*)pOption) = iVal;
459− return cmResultSuccess;
460− }
461−
462− return cmInitParaError;
463−}
464−
465−DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
466− const int kiSrcLen,
467− unsigned char** ppDst,
468− SBufferInfo* pDstInfo) {
469− int iRet;
470− //SBufferInfo sTmpBufferInfo;
471− //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
472−
473− iRet = (int) DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
474− //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
475− //ppTmpDst[0] = ppDst[0];
476− //ppTmpDst[1] = ppDst[1];
477− //ppTmpDst[2] = ppDst[2];
478− iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
479− //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
480− //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
481− //ppDst[0] = ppTmpDst[0];
482− //ppDst[1] = ppTmpDst[1];
483− //ppDst[2] = ppTmpDst[2];
484− //}
485−
486− return (DECODING_STATE) iRet;
487−}
488−
489−DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
490− const int kiSrcLen,
491− unsigned char** ppDst,
492− SBufferInfo* pDstInfo) {
493− if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
494− if (m_pWelsTrace != NULL) {
495− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
496− }
497− return dsInitialOptExpected;
498− }
499−
500− if (m_pDecContext->pParam->bParseOnly) {
501− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
502− m_pDecContext->iErrorCode |= dsInvalidArgument;
503− return dsInvalidArgument;
504− }
505− if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
506− if (ResetDecoder())
507− return dsOutOfMemory;
508−
509− return dsErrorFree;
510− }
511− if (kiSrcLen > 0 && kpSrc != NULL) {
512−#ifdef OUTPUT_BIT_STREAM
513− if (m_pFBS) {
514− WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
515− WelsFflush (m_pFBS);
516− }
517− if (m_pFBSSize) {
518− WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
519− WelsFflush (m_pFBSSize);
520− }
521−#endif//OUTPUT_BIT_STREAM
522− m_pDecContext->bEndOfStreamFlag = false;
523− } else {
524− //For application MODE, the error detection should be added for safe.
525− //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
526− m_pDecContext->bEndOfStreamFlag = true;
527− m_pDecContext->bInstantDecFlag = true;
528− }
529−
530− int64_t iStart, iEnd;
531− iStart = WelsTime();
532− ppDst[0] = ppDst[1] = ppDst[2] = NULL;
533− m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
534− m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
535− unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
536− memset (pDstInfo, 0, sizeof (SBufferInfo));
537− pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
538−#ifdef LONG_TERM_REF
539− m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
540− m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
541− m_pDecContext->iFrameNumOfAuMarkedLtr = 0;
542− m_pDecContext->iFrameNum = -1; //initialize
543−#endif
544−
545− m_pDecContext->iFeedbackTidInAu = -1; //initialize
546− m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
547− if (pDstInfo) {
548− pDstInfo->uiOutYuvTimeStamp = 0;
549− m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
550− } else {
551− m_pDecContext->uiTimeStamp = 0;
552− }
553− WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
554− pDstInfo, NULL); //iErrorCode has been modified in this function
555− m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
556− if (m_pDecContext->iErrorCode) {
557− EWelsNalUnitType eNalType =
558− NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
559−
560− eNalType = m_pDecContext->sCurNalHead.eNalUnitType;
561−
562− if (m_pDecContext->iErrorCode & dsOutOfMemory) {
563− if (ResetDecoder())
564− return dsOutOfMemory;
565−
566− return dsErrorFree;
567− }
568− //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
569− if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
570− (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) {
571− if (m_pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
572−#ifdef LONG_TERM_REF
573− m_pDecContext->bParamSetsLostFlag = true;
574−#else
575− m_pDecContext->bReferenceLostAtT0Flag = true;
576−#endif
577− }
578− }
579−
580− if (m_pDecContext->bPrintFrameErrorTraceFlag) {
581− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
582− m_pDecContext->iErrorCode);
583− m_pDecContext->bPrintFrameErrorTraceFlag = false;
584− } else {
585− m_pDecContext->iIgnoredErrorInfoPacketCount ++;
586− if (m_pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
587− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
588− m_pDecContext->iIgnoredErrorInfoPacketCount = 0;
589− }
590− }
591− if ((m_pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
592− //TODO after dec status updated
593− m_pDecContext->iErrorCode |= dsDataErrorConcealed;
594−
595− m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
596− if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
597− ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
598− m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
599− }
600− int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum;
601− m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ?
602− (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
603− m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
604− iMbConcealedNum * 100) / m_pDecContext->iMbNum));
605− m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ?
606− (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
607− m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
608− m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum));
609− m_pDecContext->sDecoderStatistics.uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
610− m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
611− m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
612− m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
613− m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
614− }
615− iEnd = WelsTime();
616− m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
617−
618− OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
619−
620− return (DECODING_STATE) m_pDecContext->iErrorCode;
621− }
622− // else Error free, the current codec works well
623−
624− if (pDstInfo->iBufferStatus == 1) {
625−
626− m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
627− if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
628− ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
629− m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
630− }
631−
632− OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
633− }
634− iEnd = WelsTime();
635− m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
636−
637−
638−
639− return dsErrorFree;
640−}
641−
642−void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
643− if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
644− && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
645− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
646− "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
647− uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
648− uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
649− uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
650− iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
651− uiProfile=%d, uiLevel=%d, \
652− iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
653− sDecoderStatistics.uiWidth,
654− sDecoderStatistics.uiHeight,
655− sDecoderStatistics.fAverageFrameSpeedInMs,
656− sDecoderStatistics.fActualAverageFrameSpeedInMs,
657−
658− sDecoderStatistics.uiDecodedFrameCount,
659− sDecoderStatistics.uiResolutionChangeTimes,
660− sDecoderStatistics.uiIDRCorrectNum,
661−
662− sDecoderStatistics.uiAvgEcRatio,
663− sDecoderStatistics.uiAvgEcPropRatio,
664− sDecoderStatistics.uiEcIDRNum,
665− sDecoderStatistics.uiEcFrameNum,
666−
667− sDecoderStatistics.uiIDRLostNum,
668− sDecoderStatistics.uiFreezingIDRNum,
669− sDecoderStatistics.uiFreezingNonIDRNum,
670− sDecoderStatistics.iAvgLumaQp,
671−
672− sDecoderStatistics.iSpsReportErrorNum,
673− sDecoderStatistics.iSubSpsReportErrorNum,
674− sDecoderStatistics.iPpsReportErrorNum,
675− sDecoderStatistics.iSpsNoExistNalNum,
676− sDecoderStatistics.iSubSpsNoExistNalNum,
677− sDecoderStatistics.iPpsNoExistNalNum,
678−
679− sDecoderStatistics.uiProfile,
680− sDecoderStatistics.uiLevel,
681−
682− sDecoderStatistics.iCurrentActiveSpsId,
683− sDecoderStatistics.iCurrentActivePpsId);
684− }
685−}
686−
687−DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
688− const int kiSrcLen,
689− SParserBsInfo* pDstInfo) {
690− if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
691− if (m_pWelsTrace != NULL) {
692− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
693− }
694− return dsInitialOptExpected;
695− }
696−
697− if (!m_pDecContext->pParam->bParseOnly) {
698− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
699− m_pDecContext->iErrorCode |= dsInvalidArgument;
700− return dsInvalidArgument;
701− }
702− int64_t iEnd, iStart = WelsTime();
703− if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
704− if (ResetDecoder())
705− return dsOutOfMemory;
706−
707− return dsErrorFree;
708− }
709− if (kiSrcLen > 0 && kpSrc != NULL) {
710−#ifdef OUTPUT_BITSTREAM
711− if (m_pFBS) {
712− WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
713− WelsFflush (m_pFBS);
714− }
715−#endif//OUTPUT_BIT_STREAM
716− m_pDecContext->bEndOfStreamFlag = false;
717− } else {
718− //For application MODE, the error detection should be added for safe.
719− //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
720− m_pDecContext->bEndOfStreamFlag = true;
721− m_pDecContext->bInstantDecFlag = true;
722− }
723−
724− m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
725− m_pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
726− m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
727− if (!m_pDecContext->bFramePending) { //frame complete
728− m_pDecContext->pParserBsInfo->iNalNum = 0;
729− memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
730− }
731− pDstInfo->iNalNum = 0;
732− pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
733− if (pDstInfo) {
734− m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
735− pDstInfo->uiOutBsTimeStamp = 0;
736− } else {
737− m_pDecContext->uiTimeStamp = 0;
738− }
739− WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
740− if (m_pDecContext->iErrorCode & dsOutOfMemory) {
741− if (ResetDecoder())
742− return dsOutOfMemory;
743− return dsErrorFree;
744− }
745−
746− if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) {
747− memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
748−
749− if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
750− m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
751− if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
752− ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
753− m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
754− }
755− }
756− }
757−
758− m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
759−
760− if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) {
761− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode);
762− m_pDecContext->bPrintFrameErrorTraceFlag = false;
763− }
764− iEnd = WelsTime();
765− m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
766−
767− return (DECODING_STATE) m_pDecContext->iErrorCode;
768−}
769−
770−DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
771− const int kiSrcLen,
772− unsigned char** ppDst,
773− int* pStride,
774− int& iWidth,
775− int& iHeight) {
776− DECODING_STATE eDecState = dsErrorFree;
777− SBufferInfo DstInfo;
778−
779− memset (&DstInfo, 0, sizeof (SBufferInfo));
780− DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
781− DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
782− DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
783− DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
784−
785− eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
786− if (eDecState == dsErrorFree) {
787− pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
788− pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
789− iWidth = DstInfo.UsrData.sSystemBuffer.iWidth;
790− iHeight = DstInfo.UsrData.sSystemBuffer.iHeight;
791− }
792−
793− return eDecState;
794−}
795−
796−DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
797− const int kiSrcLen,
798− unsigned char* pDst,
799− int iDstStride,
800− int& iDstLen,
801− int& iWidth,
802− int& iHeight,
803− int& iColorFormat) {
804− DECODING_STATE state = dsErrorFree;
805−
806− return state;
807−}
808−
809−
810−} // namespace WelsDec
811−
812−
813−using namespace WelsDec;
814−/*
815−* WelsGetDecoderCapability
816−* @return: DecCapability information
817−*/
818−int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
819− memset (pDecCapability, 0, sizeof (SDecoderCapability));
820− pDecCapability->iProfileIdc = 66; //Baseline
821− pDecCapability->iProfileIop = 0xE0; //11100000b
822− pDecCapability->iLevelIdc = 32; //level_idc = 3.2
823− pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
824− pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
825− pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
826− pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
827− pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
828− pDecCapability->bRedPicCap = 0; //not support redundant pic
829−
830− return ERR_NONE;
831−}
832−/* WINAPI is indeed in prefix due to sync to application layer callings!! */
833−
834−/*
835−* WelsCreateDecoder
836−* @return: success in return 0, otherwise failed.
837−*/
838−long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
839−
840− if (NULL == ppDecoder) {
841− return ERR_INVALID_PARAMETERS;
842− }
843−
844− *ppDecoder = new CWelsDecoder();
845−
846− if (NULL == *ppDecoder) {
847− return ERR_MALLOC_FAILED;
848− }
849−
850− return ERR_NONE;
851−}
852−
853−/*
854−* WelsDestroyDecoder
855−*/
856−void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
857− if (NULL != pDecoder) {
858− delete (CWelsDecoder*)pDecoder;
859− }
860−}
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 "error_concealment.h"
55+
56+#include "measure_time.h"
57+extern "C" {
58+#include "decoder_core.h"
59+#include "manage_dec_ref.h"
60+}
61+#include "error_code.h"
62+#include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
63+#include <time.h>
64+#if defined(_WIN32) /*&& defined(_DEBUG)*/
65+
66+#include <windows.h>
67+#include <stdio.h>
68+#include <stdarg.h>
69+#include <sys/types.h>
70+#else
71+#include <sys/time.h>
72+#endif
73+
74+#define _PICTURE_REORDERING_ 1
75+
76+namespace WelsDec {
77+
78+//////////////////////////////////////////////////////////////////////
79+// Construction/Destruction
80+//////////////////////////////////////////////////////////////////////
81+
82+/***************************************************************************
83+* Description:
84+* class CWelsDecoder constructor function, do initialization and
85+* alloc memory required
86+*
87+* Input parameters: none
88+*
89+* return: none
90+***************************************************************************/
91+CWelsDecoder::CWelsDecoder (void)
92+ : m_pDecContext (NULL),
93+ m_pWelsTrace (NULL),
94+ m_iPictInfoIndex (0),
95+ m_iMinPOC (-1),
96+ m_iNumOfPicts (0),
97+ m_iLastGOPRemainPicts (0),
98+ m_LastWrittenPOC (0) {
99+#ifdef OUTPUT_BIT_STREAM
100+ char chFileName[1024] = { 0 }; //for .264
101+ int iBufUsed = 0;
102+ int iBufLeft = 1023;
103+ int iCurUsed;
104+
105+ char chFileNameSize[1024] = { 0 }; //for .len
106+ int iBufUsedSize = 0;
107+ int iBufLeftSize = 1023;
108+ int iCurUsedSize;
109+#endif//OUTPUT_BIT_STREAM
110+
111+
112+ m_pWelsTrace = new welsCodecTrace();
113+ if (m_pWelsTrace != NULL) {
114+ m_pWelsTrace->SetCodecInstance (this);
115+ m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
116+
117+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
118+ }
119+
120+ for (int32_t i = 0; i < 10; ++i) {
121+ m_sPictInfoList[i].bLastGOP = false;
122+ m_sPictInfoList[i].iPOC = -1;
123+ }
124+
125+#ifdef OUTPUT_BIT_STREAM
126+ SWelsTime sCurTime;
127+
128+ WelsGetTimeOfDay (&sCurTime);
129+
130+ iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);
131+ iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);
132+
133+ iBufUsed += iCurUsed;
134+ iBufLeft -= iCurUsed;
135+ if (iBufLeft > 0) {
136+ iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
137+ iBufUsed += iCurUsed;
138+ iBufLeft -= iCurUsed;
139+ }
140+
141+ iBufUsedSize += iCurUsedSize;
142+ iBufLeftSize -= iCurUsedSize;
143+ if (iBufLeftSize > 0) {
144+ iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
145+ iBufUsedSize += iCurUsedSize;
146+ iBufLeftSize -= iCurUsedSize;
147+ }
148+
149+ if (iBufLeft > 0) {
150+ iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
151+ iBufUsed += iCurUsed;
152+ iBufLeft -= iCurUsed;
153+ }
154+
155+ if (iBufLeftSize > 0) {
156+ iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
157+ WelsGetMillisecond (&sCurTime));
158+ iBufUsedSize += iCurUsedSize;
159+ iBufLeftSize -= iCurUsedSize;
160+ }
161+
162+
163+ m_pFBS = WelsFopen (chFileName, "wb");
164+ m_pFBSSize = WelsFopen (chFileNameSize, "wb");
165+#endif//OUTPUT_BIT_STREAM
166+}
167+
168+/***************************************************************************
169+* Description:
170+* class CWelsDecoder destructor function, destroy allocced memory
171+*
172+* Input parameters: none
173+*
174+* return: none
175+***************************************************************************/
176+CWelsDecoder::~CWelsDecoder() {
177+ if (m_pWelsTrace != NULL) {
178+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
179+ }
180+
181+ UninitDecoder();
182+
183+#ifdef OUTPUT_BIT_STREAM
184+ if (m_pFBS) {
185+ WelsFclose (m_pFBS);
186+ m_pFBS = NULL;
187+ }
188+ if (m_pFBSSize) {
189+ WelsFclose (m_pFBSSize);
190+ m_pFBSSize = NULL;
191+ }
192+#endif//OUTPUT_BIT_STREAM
193+
194+ if (m_pWelsTrace != NULL) {
195+ delete m_pWelsTrace;
196+ m_pWelsTrace = NULL;
197+ }
198+}
199+
200+long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
201+ int iRet = ERR_NONE;
202+ if (m_pWelsTrace == NULL) {
203+ return cmMallocMemeError;
204+ }
205+
206+ if (pParam == NULL) {
207+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");
208+ return cmInitParaError;
209+ }
210+
211+ // H.264 decoder initialization,including memory allocation,then open it ready to decode
212+ iRet = InitDecoder (pParam);
213+ if (iRet)
214+ return iRet;
215+
216+ return cmResultSuccess;
217+}
218+
219+long CWelsDecoder::Uninitialize() {
220+ UninitDecoder();
221+
222+ return ERR_NONE;
223+}
224+
225+void CWelsDecoder::UninitDecoder (void) {
226+ if (NULL == m_pDecContext)
227+ return;
228+
229+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoder(), openh264 codec version = %s.",
230+ VERSION_NUMBER);
231+
232+ WelsEndDecoder (m_pDecContext);
233+
234+ if (m_pDecContext->pMemAlign != NULL) {
235+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
236+ "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
237+ m_pDecContext->pMemAlign->WelsGetMemoryUsage());
238+ delete m_pDecContext->pMemAlign;
239+ m_pDecContext->pMemAlign = NULL;
240+ }
241+
242+ if (NULL != m_pDecContext) {
243+ WelsFree (m_pDecContext, "m_pDecContext");
244+
245+ m_pDecContext = NULL;
246+ }
247+}
248+
249+// the return value of this function is not suitable, it need report failure info to upper layer.
250+int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
251+
252+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
253+ "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
254+ VERSION_NUMBER, (int32_t)pParam->bParseOnly);
255+
256+ //reset decoder context
257+ if (m_pDecContext) //free
258+ UninitDecoder();
259+ m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
260+ if (NULL == m_pDecContext)
261+ return cmMallocMemeError;
262+ int32_t iCacheLineSize = 16; // on chip cache line size in byte
263+ m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize);
264+ WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pMemAlign), UninitDecoder())
265+
266+ //fill in default value into context
267+ WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
268+
269+ //check param and update decoder context
270+ m_pDecContext->pParam = (SDecodingParam*)m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
271+ "SDecodingParam");
272+ WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder());
273+ int32_t iRet = DecoderConfigParam (m_pDecContext, pParam);
274+ WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
275+
276+ //init decoder
277+ WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx),
278+ UninitDecoder())
279+
280+ return cmResultSuccess;
281+}
282+
283+int32_t CWelsDecoder::ResetDecoder() {
284+ // TBC: need to be modified when context and trace point are null
285+ if (m_pDecContext != NULL && m_pWelsTrace != NULL) {
286+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",
287+ m_pDecContext->iErrorCode);
288+ SDecodingParam sPrevParam;
289+ memcpy (&sPrevParam, m_pDecContext->pParam, sizeof (SDecodingParam));
290+
291+ WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoder (&sPrevParam), UninitDecoder());
292+ } else if (m_pWelsTrace != NULL) {
293+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
294+ }
295+ return ERR_INFO_UNINIT;
296+}
297+
298+/*
299+ * Set Option
300+ */
301+long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
302+ int iVal = 0;
303+
304+ if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
305+ eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
306+ return dsInitialOptExpected;
307+ if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded
308+ if (pOption == NULL)
309+ return cmInitParaError;
310+
311+ iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag
312+
313+ m_pDecContext->bEndOfStreamFlag = iVal ? true : false;
314+
315+ return cmResultSuccess;
316+ } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status
317+ if (pOption == NULL)
318+ return cmInitParaError;
319+
320+ iVal = * ((int*)pOption); // int value for error concealment idc
321+ iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
322+ if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) {
323+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
324+ "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
325+ return cmInitParaError;
326+ }
327+
328+ m_pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal;
329+ InitErrorCon (m_pDecContext);
330+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
331+ "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal);
332+
333+ return cmResultSuccess;
334+ } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
335+ if (m_pWelsTrace) {
336+ uint32_t level = * ((uint32_t*)pOption);
337+ m_pWelsTrace->SetTraceLevel (level);
338+ }
339+ return cmResultSuccess;
340+ } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
341+ if (m_pWelsTrace) {
342+ WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
343+ m_pWelsTrace->SetTraceCallback (callback);
344+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
345+ "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.",
346+ callback);
347+ }
348+ return cmResultSuccess;
349+ } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
350+ if (m_pWelsTrace) {
351+ void* ctx = * ((void**)pOption);
352+ m_pWelsTrace->SetTraceCallbackContext (ctx);
353+ }
354+ return cmResultSuccess;
355+ } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
356+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
357+ "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
358+ return cmInitParaError;
359+ } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
360+ if (pOption) {
361+ m_pDecContext->sDecoderStatistics.iStatisticsLogInterval = (* ((unsigned int*)pOption));
362+ return cmResultSuccess;
363+ }
364+ } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
365+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
366+ "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
367+ return cmInitParaError;
368+ }
369+ return cmInitParaError;
370+}
371+
372+/*
373+ * Get Option
374+ */
375+long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
376+ int iVal = 0;
377+
378+ if (m_pDecContext == NULL)
379+ return cmInitExpected;
380+
381+ if (pOption == NULL)
382+ return cmInitParaError;
383+
384+ if (DECODER_OPTION_END_OF_STREAM == eOptID) {
385+ iVal = m_pDecContext->bEndOfStreamFlag;
386+ * ((int*)pOption) = iVal;
387+ return cmResultSuccess;
388+ }
389+#ifdef LONG_TERM_REF
390+ else if (DECODER_OPTION_IDR_PIC_ID == eOptID) {
391+ iVal = m_pDecContext->uiCurIdrPicId;
392+ * ((int*)pOption) = iVal;
393+ return cmResultSuccess;
394+ } else if (DECODER_OPTION_FRAME_NUM == eOptID) {
395+ iVal = m_pDecContext->iFrameNum;
396+ * ((int*)pOption) = iVal;
397+ return cmResultSuccess;
398+ } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) {
399+ iVal = m_pDecContext->bCurAuContainLtrMarkSeFlag;
400+ * ((int*)pOption) = iVal;
401+ return cmResultSuccess;
402+ } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) {
403+ iVal = m_pDecContext->iFrameNumOfAuMarkedLtr;
404+ * ((int*)pOption) = iVal;
405+ return cmResultSuccess;
406+ }
407+#endif
408+ else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU
409+ iVal = m_pDecContext->iFeedbackVclNalInAu;
410+ * ((int*)pOption) = iVal;
411+ return cmResultSuccess;
412+ } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID
413+ iVal = m_pDecContext->iFeedbackTidInAu;
414+ * ((int*)pOption) = iVal;
415+ return cmResultSuccess;
416+ } else if (DECODER_OPTION_IS_REF_PIC == eOptID) {
417+ iVal = m_pDecContext->iFeedbackNalRefIdc;
418+ if (iVal > 0)
419+ iVal = 1;
420+ * ((int*)pOption) = iVal;
421+ return cmResultSuccess;
422+ } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) {
423+ iVal = (int)m_pDecContext->pParam->eEcActiveIdc;
424+ * ((int*)pOption) = iVal;
425+ return cmResultSuccess;
426+ } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
427+ SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
428+
429+ memcpy (pDecoderStatistics, &m_pDecContext->sDecoderStatistics, sizeof (SDecoderStatistics));
430+
431+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount != 0) { //not original status
432+ pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
433+ (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
434+ pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
435+ (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount + m_pDecContext->sDecoderStatistics.uiFreezingIDRNum +
436+ m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
437+ }
438+ return cmResultSuccess;
439+ } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
440+ if (pOption) {
441+ iVal = m_pDecContext->sDecoderStatistics.iStatisticsLogInterval;
442+ * ((unsigned int*)pOption) = iVal;
443+ return cmResultSuccess;
444+ }
445+ } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
446+ PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
447+ memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
448+ if (!m_pDecContext->pSps) {
449+ return cmInitExpected;
450+ } else {
451+ pVuiSarInfo->uiSarWidth = m_pDecContext->pSps->sVui.uiSarWidth;
452+ pVuiSarInfo->uiSarHeight = m_pDecContext->pSps->sVui.uiSarHeight;
453+ pVuiSarInfo->bOverscanAppropriateFlag = m_pDecContext->pSps->sVui.bOverscanAppropriateFlag;
454+ return cmResultSuccess;
455+ }
456+ } else if (DECODER_OPTION_PROFILE == eOptID) {
457+ if (!m_pDecContext->pSps) {
458+ return cmInitExpected;
459+ }
460+ iVal = (int)m_pDecContext->pSps->uiProfileIdc;
461+ * ((int*)pOption) = iVal;
462+ return cmResultSuccess;
463+ } else if (DECODER_OPTION_LEVEL == eOptID) {
464+ if (!m_pDecContext->pSps) {
465+ return cmInitExpected;
466+ }
467+ iVal = (int)m_pDecContext->pSps->uiLevelIdc;
468+ * ((int*)pOption) = iVal;
469+ return cmResultSuccess;
470+ } else if (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER == eOptID) {
471+ if (m_pDecContext->pSps && m_pDecContext->pSps->uiProfileIdc != 66 && m_pDecContext->pPps->bEntropyCodingModeFlag) {
472+ * ((int*)pOption) = m_iNumOfPicts > 0 ? m_iNumOfPicts : 0;
473+ }
474+ return cmResultSuccess;
475+ }
476+
477+ return cmInitParaError;
478+}
479+
480+DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
481+ const int kiSrcLen,
482+ unsigned char** ppDst,
483+ SBufferInfo* pDstInfo) {
484+ int iRet;
485+ //SBufferInfo sTmpBufferInfo;
486+ //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
487+ iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
488+ //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
489+ //ppTmpDst[0] = ppDst[0];
490+ //ppTmpDst[1] = ppDst[1];
491+ //ppTmpDst[2] = ppDst[2];
492+ iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
493+ //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
494+ //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
495+ //ppDst[0] = ppTmpDst[0];
496+ //ppDst[1] = ppTmpDst[1];
497+ //ppDst[2] = ppTmpDst[2];
498+ //}
499+ return (DECODING_STATE)iRet;
500+}
501+
502+DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
503+ const int kiSrcLen,
504+ unsigned char** ppDst,
505+ SBufferInfo* pDstInfo) {
506+ if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
507+ if (m_pWelsTrace != NULL) {
508+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
509+ }
510+ return dsInitialOptExpected;
511+ }
512+
513+ if (m_pDecContext->pParam->bParseOnly) {
514+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
515+ m_pDecContext->iErrorCode |= dsInvalidArgument;
516+ return dsInvalidArgument;
517+ }
518+ if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
519+ if (ResetDecoder())
520+ return dsOutOfMemory;
521+
522+ return dsErrorFree;
523+ }
524+ if (kiSrcLen > 0 && kpSrc != NULL) {
525+#ifdef OUTPUT_BIT_STREAM
526+ if (m_pFBS) {
527+ WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
528+ WelsFflush (m_pFBS);
529+ }
530+ if (m_pFBSSize) {
531+ WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
532+ WelsFflush (m_pFBSSize);
533+ }
534+#endif//OUTPUT_BIT_STREAM
535+ m_pDecContext->bEndOfStreamFlag = false;
536+ } else {
537+ //For application MODE, the error detection should be added for safe.
538+ //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
539+ m_pDecContext->bEndOfStreamFlag = true;
540+ m_pDecContext->bInstantDecFlag = true;
541+ }
542+
543+ int64_t iStart, iEnd;
544+ iStart = WelsTime();
545+
546+ ppDst[0] = ppDst[1] = ppDst[2] = NULL;
547+ m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
548+ m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
549+ unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
550+ memset (pDstInfo, 0, sizeof (SBufferInfo));
551+ pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
552+#ifdef LONG_TERM_REF
553+ m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
554+ m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
555+ m_pDecContext->iFrameNumOfAuMarkedLtr = 0;
556+ m_pDecContext->iFrameNum = -1; //initialize
557+#endif
558+
559+ m_pDecContext->iFeedbackTidInAu = -1; //initialize
560+ m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
561+ if (pDstInfo) {
562+ pDstInfo->uiOutYuvTimeStamp = 0;
563+ m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
564+ } else {
565+ m_pDecContext->uiTimeStamp = 0;
566+ }
567+ WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
568+ pDstInfo, NULL); //iErrorCode has been modified in this function
569+ m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
570+ if (m_pDecContext->iErrorCode) {
571+ EWelsNalUnitType eNalType =
572+ NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
573+
574+ eNalType = m_pDecContext->sCurNalHead.eNalUnitType;
575+
576+ if (m_pDecContext->iErrorCode & dsOutOfMemory) {
577+ if (ResetDecoder())
578+ return dsOutOfMemory;
579+
580+ return dsErrorFree;
581+ }
582+ //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
583+ if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
584+ (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) {
585+ if (m_pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
586+#ifdef LONG_TERM_REF
587+ m_pDecContext->bParamSetsLostFlag = true;
588+#else
589+ m_pDecContext->bReferenceLostAtT0Flag = true;
590+#endif
591+ }
592+ }
593+
594+ if (m_pDecContext->bPrintFrameErrorTraceFlag) {
595+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
596+ m_pDecContext->iErrorCode);
597+ m_pDecContext->bPrintFrameErrorTraceFlag = false;
598+ } else {
599+ m_pDecContext->iIgnoredErrorInfoPacketCount++;
600+ if (m_pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
601+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
602+ m_pDecContext->iIgnoredErrorInfoPacketCount = 0;
603+ }
604+ }
605+ if ((m_pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
606+ //TODO after dec status updated
607+ m_pDecContext->iErrorCode |= dsDataErrorConcealed;
608+
609+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
610+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
611+ ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
612+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
613+ }
614+ int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum;
615+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ?
616+ (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
617+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
618+ iMbConcealedNum * 100) / m_pDecContext->iMbNum));
619+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ?
620+ (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
621+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
622+ m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum));
623+ m_pDecContext->sDecoderStatistics.uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
624+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
625+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
626+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
627+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
628+ }
629+ iEnd = WelsTime();
630+ m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
631+
632+ OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
633+
634+#ifdef _PICTURE_REORDERING_
635+ ReorderPicturesInDisplay (ppDst, pDstInfo);
636+#endif
637+
638+ return (DECODING_STATE)m_pDecContext->iErrorCode;
639+ }
640+ // else Error free, the current codec works well
641+
642+ if (pDstInfo->iBufferStatus == 1) {
643+
644+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
645+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
646+ ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
647+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
648+ }
649+
650+ OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
651+ }
652+ iEnd = WelsTime();
653+ m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
654+
655+#ifdef _PICTURE_REORDERING_
656+ ReorderPicturesInDisplay (ppDst, pDstInfo);
657+#endif
658+ return dsErrorFree;
659+}
660+
661+DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
662+ SBufferInfo* pDstInfo) {
663+ if (m_pDecContext->bEndOfStreamFlag && m_iNumOfPicts > 0) {
664+ m_iMinPOC = -1;
665+ for (int32_t i = 0; i < 10; ++i) {
666+ if (m_iMinPOC == -1 && m_sPictInfoList[i].iPOC >= 0) {
667+ m_iMinPOC = m_sPictInfoList[i].iPOC;
668+ m_iPictInfoIndex = i;
669+ }
670+ if (m_sPictInfoList[i].iPOC >= 0 && m_sPictInfoList[i].iPOC < m_iMinPOC) {
671+ m_iMinPOC = m_sPictInfoList[i].iPOC;
672+ m_iPictInfoIndex = i;
673+ }
674+ }
675+ }
676+ if (m_iMinPOC >= 0) {
677+ m_LastWrittenPOC = m_iMinPOC;
678+#if defined (_DEBUG)
679+#ifdef _MOTION_VECTOR_DUMP_
680+ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
681+#endif
682+#endif
683+ memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
684+ ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
685+ ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
686+ ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
687+ m_sPictInfoList[m_iPictInfoIndex].iPOC = -1;
688+ m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
689+ m_iMinPOC = -1;
690+ --m_iNumOfPicts;
691+ }
692+ return dsErrorFree;
693+}
694+
695+void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
696+ if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
697+ && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
698+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
699+ "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
700+ uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
701+ uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
702+ uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
703+ iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
704+ uiProfile=%d, uiLevel=%d, \
705+ iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
706+ sDecoderStatistics.uiWidth,
707+ sDecoderStatistics.uiHeight,
708+ sDecoderStatistics.fAverageFrameSpeedInMs,
709+ sDecoderStatistics.fActualAverageFrameSpeedInMs,
710+
711+ sDecoderStatistics.uiDecodedFrameCount,
712+ sDecoderStatistics.uiResolutionChangeTimes,
713+ sDecoderStatistics.uiIDRCorrectNum,
714+
715+ sDecoderStatistics.uiAvgEcRatio,
716+ sDecoderStatistics.uiAvgEcPropRatio,
717+ sDecoderStatistics.uiEcIDRNum,
718+ sDecoderStatistics.uiEcFrameNum,
719+
720+ sDecoderStatistics.uiIDRLostNum,
721+ sDecoderStatistics.uiFreezingIDRNum,
722+ sDecoderStatistics.uiFreezingNonIDRNum,
723+ sDecoderStatistics.iAvgLumaQp,
724+
725+ sDecoderStatistics.iSpsReportErrorNum,
726+ sDecoderStatistics.iSubSpsReportErrorNum,
727+ sDecoderStatistics.iPpsReportErrorNum,
728+ sDecoderStatistics.iSpsNoExistNalNum,
729+ sDecoderStatistics.iSubSpsNoExistNalNum,
730+ sDecoderStatistics.iPpsNoExistNalNum,
731+
732+ sDecoderStatistics.uiProfile,
733+ sDecoderStatistics.uiLevel,
734+
735+ sDecoderStatistics.iCurrentActiveSpsId,
736+ sDecoderStatistics.iCurrentActivePpsId);
737+ }
738+}
739+
740+DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo) {
741+ if (pDstInfo->iBufferStatus == 1 && m_pDecContext->pSps->uiProfileIdc != 66
742+ && m_pDecContext->pPps->bEntropyCodingModeFlag) {
743+ if (m_pDecContext->pSliceHeader->iPicOrderCntLsb == 0) {
744+ if (m_iNumOfPicts > 0) {
745+ m_iLastGOPRemainPicts = m_iNumOfPicts;
746+ for (int32_t i = 0; i < 10; ++i) {
747+ if (m_sPictInfoList[i].iPOC >= 0) {
748+ m_sPictInfoList[i].bLastGOP = true;
749+ }
750+ }
751+ }
752+ }
753+ for (int32_t i = 0; i < 10; ++i) {
754+ if (m_sPictInfoList[i].iPOC == -1) {
755+ memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
756+ m_sPictInfoList[i].pData[0] = ppDst[0];
757+ m_sPictInfoList[i].pData[1] = ppDst[1];
758+ m_sPictInfoList[i].pData[2] = ppDst[2];
759+ m_sPictInfoList[i].iPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb;
760+ m_sPictInfoList[i].iFrameNum = m_pDecContext->pSliceHeader->iFrameNum;
761+ m_sPictInfoList[i].bLastGOP = false;
762+ pDstInfo->iBufferStatus = 0;
763+ ++m_iNumOfPicts;
764+ break;
765+ }
766+ }
767+ if (m_iLastGOPRemainPicts > 0) {
768+ m_iMinPOC = -1;
769+ for (int32_t i = 0; i < 10; ++i) {
770+ if (m_iMinPOC == -1 && m_sPictInfoList[i].iPOC >= 0 && m_sPictInfoList[i].bLastGOP) {
771+ m_iMinPOC = m_sPictInfoList[i].iPOC;
772+ m_iPictInfoIndex = i;
773+ }
774+ if (m_sPictInfoList[i].iPOC >= 0 && m_sPictInfoList[i].iPOC < m_iMinPOC && m_sPictInfoList[i].bLastGOP) {
775+ m_iMinPOC = m_sPictInfoList[i].iPOC;
776+ m_iPictInfoIndex = i;
777+ }
778+ }
779+ m_LastWrittenPOC = m_iMinPOC;
780+#if defined (_DEBUG)
781+#ifdef _MOTION_VECTOR_DUMP_
782+ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
783+#endif
784+#endif
785+ memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
786+ ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
787+ ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
788+ ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
789+ m_sPictInfoList[m_iPictInfoIndex].iPOC = -1;
790+ m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
791+ m_iMinPOC = -1;
792+ --m_iNumOfPicts;
793+ --m_iLastGOPRemainPicts;
794+ if (m_iLastGOPRemainPicts == 0) {
795+ m_LastWrittenPOC = 0;
796+ }
797+ return dsErrorFree;
798+ }
799+ if (m_iNumOfPicts > 0) {
800+ m_iMinPOC = -1;
801+ for (int32_t i = 0; i < 10; ++i) {
802+ if (m_iMinPOC == -1 && m_sPictInfoList[i].iPOC >= 0) {
803+ m_iMinPOC = m_sPictInfoList[i].iPOC;
804+ m_iPictInfoIndex = i;
805+ }
806+ if (m_sPictInfoList[i].iPOC >= 0 && m_sPictInfoList[i].iPOC < m_iMinPOC) {
807+ m_iMinPOC = m_sPictInfoList[i].iPOC;
808+ m_iPictInfoIndex = i;
809+ }
810+ }
811+ }
812+ if (m_iMinPOC >= 0) {
813+ if (m_iMinPOC - m_LastWrittenPOC <= 1 || m_iMinPOC < m_pDecContext->pSliceHeader->iPicOrderCntLsb) {
814+ m_LastWrittenPOC = m_iMinPOC;
815+#if defined (_DEBUG)
816+#ifdef _MOTION_VECTOR_DUMP_
817+ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
818+#endif
819+#endif
820+ memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
821+ ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
822+ ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
823+ ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
824+ m_sPictInfoList[m_iPictInfoIndex].iPOC = -1;
825+ m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
826+ m_iMinPOC = -1;
827+ --m_iNumOfPicts;
828+ return dsErrorFree;
829+ }
830+ }
831+ }
832+
833+ return dsErrorFree;
834+}
835+
836+DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
837+ const int kiSrcLen,
838+ SParserBsInfo* pDstInfo) {
839+ if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
840+ if (m_pWelsTrace != NULL) {
841+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
842+ }
843+ return dsInitialOptExpected;
844+ }
845+
846+ if (!m_pDecContext->pParam->bParseOnly) {
847+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
848+ m_pDecContext->iErrorCode |= dsInvalidArgument;
849+ return dsInvalidArgument;
850+ }
851+ int64_t iEnd, iStart = WelsTime();
852+ if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
853+ if (ResetDecoder())
854+ return dsOutOfMemory;
855+
856+ return dsErrorFree;
857+ }
858+ if (kiSrcLen > 0 && kpSrc != NULL) {
859+#ifdef OUTPUT_BITSTREAM
860+ if (m_pFBS) {
861+ WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
862+ WelsFflush (m_pFBS);
863+ }
864+#endif//OUTPUT_BIT_STREAM
865+ m_pDecContext->bEndOfStreamFlag = false;
866+ } else {
867+ //For application MODE, the error detection should be added for safe.
868+ //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
869+ m_pDecContext->bEndOfStreamFlag = true;
870+ m_pDecContext->bInstantDecFlag = true;
871+ }
872+
873+ m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
874+ m_pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
875+ m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
876+ if (!m_pDecContext->bFramePending) { //frame complete
877+ m_pDecContext->pParserBsInfo->iNalNum = 0;
878+ memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
879+ }
880+ pDstInfo->iNalNum = 0;
881+ pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
882+ if (pDstInfo) {
883+ m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
884+ pDstInfo->uiOutBsTimeStamp = 0;
885+ } else {
886+ m_pDecContext->uiTimeStamp = 0;
887+ }
888+ WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
889+ if (m_pDecContext->iErrorCode & dsOutOfMemory) {
890+ if (ResetDecoder())
891+ return dsOutOfMemory;
892+ return dsErrorFree;
893+ }
894+
895+ if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) {
896+ memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
897+
898+ if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
899+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
900+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
901+ ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
902+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
903+ }
904+ }
905+ }
906+
907+ m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
908+
909+ if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) {
910+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode);
911+ m_pDecContext->bPrintFrameErrorTraceFlag = false;
912+ }
913+ iEnd = WelsTime();
914+ m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
915+
916+ return (DECODING_STATE) m_pDecContext->iErrorCode;
917+}
918+
919+DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
920+ const int kiSrcLen,
921+ unsigned char** ppDst,
922+ int* pStride,
923+ int& iWidth,
924+ int& iHeight) {
925+ DECODING_STATE eDecState = dsErrorFree;
926+ SBufferInfo DstInfo;
927+
928+ memset (&DstInfo, 0, sizeof (SBufferInfo));
929+ DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
930+ DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
931+ DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
932+ DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
933+
934+ eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
935+ if (eDecState == dsErrorFree) {
936+ pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
937+ pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
938+ iWidth = DstInfo.UsrData.sSystemBuffer.iWidth;
939+ iHeight = DstInfo.UsrData.sSystemBuffer.iHeight;
940+ }
941+
942+ return eDecState;
943+}
944+
945+DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
946+ const int kiSrcLen,
947+ unsigned char* pDst,
948+ int iDstStride,
949+ int& iDstLen,
950+ int& iWidth,
951+ int& iHeight,
952+ int& iColorFormat) {
953+ DECODING_STATE state = dsErrorFree;
954+
955+ return state;
956+}
957+
958+
959+} // namespace WelsDec
960+
961+
962+using namespace WelsDec;
963+/*
964+* WelsGetDecoderCapability
965+* @return: DecCapability information
966+*/
967+int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
968+ memset (pDecCapability, 0, sizeof (SDecoderCapability));
969+ pDecCapability->iProfileIdc = 66; //Baseline
970+ pDecCapability->iProfileIop = 0xE0; //11100000b
971+ pDecCapability->iLevelIdc = 32; //level_idc = 3.2
972+ pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
973+ pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
974+ pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
975+ pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
976+ pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
977+ pDecCapability->bRedPicCap = 0; //not support redundant pic
978+
979+ return ERR_NONE;
980+}
981+/* WINAPI is indeed in prefix due to sync to application layer callings!! */
982+
983+/*
984+* WelsCreateDecoder
985+* @return: success in return 0, otherwise failed.
986+*/
987+long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
988+
989+ if (NULL == ppDecoder) {
990+ return ERR_INVALID_PARAMETERS;
991+ }
992+
993+ *ppDecoder = new CWelsDecoder();
994+
995+ if (NULL == *ppDecoder) {
996+ return ERR_MALLOC_FAILED;
997+ }
998+
999+ return ERR_NONE;
1000+}
1001+
1002+/*
1003+* WelsDestroyDecoder
1004+*/
1005+void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1006+ if (NULL != pDecoder) {
1007+ delete (CWelsDecoder*)pDecoder;
1008+ }
1009+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t