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