1 /*!
2 * \copy
3 * Copyright (c) 2004-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 * h264dec.cpp: Wels Decoder Console Implementation file
32 */
33
34 #if defined (_WIN32)
35 #define _CRT_SECURE_NO_WARNINGS
36 #include <windows.h>
37 #include <tchar.h>
38 #else
39 #include <string.h>
40 #endif
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <stdarg.h>
44 #if defined (ANDROID_NDK)
45 #include <android/log.h>
46 #endif
47 #include "codec_def.h"
48 #include "codec_app_def.h"
49 #include "codec_api.h"
50 #include "read_config.h"
51 #include "typedefs.h"
52 #include "measure_time.h"
53 #include "d3d9_utils.h"
54
55 using namespace std;
56
57 #if defined (WINDOWS_PHONE)
58 double g_dDecTime = 0.0;
59 float g_fDecFPS = 0.0;
60 int g_iDecodedFrameNum = 0;
61 #endif
62
63 #if defined(ANDROID_NDK)
64 #define LOG_TAG "welsdec"
65 #define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
66 #define printf LOGI
67 #define fprintf(a, ...) LOGI(__VA_ARGS__)
68 #endif
69 //using namespace WelsDec;
70
readBit(uint8_t * pBufPtr,int32_t & curBit)71 int32_t readBit (uint8_t* pBufPtr, int32_t& curBit) {
72 int nIndex = curBit / 8;
73 int nOffset = curBit % 8 + 1;
74
75 curBit++;
76 return (pBufPtr[nIndex] >> (8 - nOffset)) & 0x01;
77 }
78
readBits(uint8_t * pBufPtr,int32_t & n,int32_t & curBit)79 int32_t readBits (uint8_t* pBufPtr, int32_t& n, int32_t& curBit) {
80 int r = 0;
81 int i;
82 for (i = 0; i < n; i++) {
83 r |= (readBit (pBufPtr, curBit) << (n - i - 1));
84 }
85 return r;
86 }
87
bsGetUe(uint8_t * pBufPtr,int32_t & curBit)88 int32_t bsGetUe (uint8_t* pBufPtr, int32_t& curBit) {
89 int r = 0;
90 int i = 0;
91 while ((readBit (pBufPtr, curBit) == 0) && (i < 32)) {
92 i++;
93 }
94 r = readBits (pBufPtr, i, curBit);
95 r += (1 << i) - 1;
96 return r;
97 }
98
readFirstMbInSlice(uint8_t * pSliceNalPtr)99 int32_t readFirstMbInSlice (uint8_t* pSliceNalPtr) {
100 int32_t curBit = 0;
101 int32_t firstMBInSlice = bsGetUe (pSliceNalPtr + 1, curBit);
102 return firstMBInSlice;
103 }
104
readPicture(uint8_t * pBuf,const int32_t & iFileSize,const int32_t & bufPos,uint8_t * & pSpsBuf,int32_t & sps_byte_count)105 int32_t readPicture (uint8_t* pBuf, const int32_t& iFileSize, const int32_t& bufPos, uint8_t*& pSpsBuf,
106 int32_t& sps_byte_count) {
107 int32_t bytes_available = iFileSize - bufPos;
108 if (bytes_available < 4) {
109 return bytes_available;
110 }
111 uint8_t* ptr = pBuf + bufPos;
112 int32_t read_bytes = 0;
113 int32_t sps_count = 0;
114 int32_t pps_count = 0;
115 int32_t non_idr_pict_count = 0;
116 int32_t idr_pict_count = 0;
117 int32_t nal_deliminator = 0;
118 pSpsBuf = NULL;
119 sps_byte_count = 0;
120 while (read_bytes < bytes_available - 4) {
121 bool has4ByteStartCode = ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 1;
122 bool has3ByteStartCode = false;
123 if (!has4ByteStartCode) {
124 has3ByteStartCode = ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 1;
125 }
126 if (has4ByteStartCode || has3ByteStartCode) {
127 int32_t byteOffset = has4ByteStartCode ? 4 : 3;
128 uint8_t nal_unit_type = has4ByteStartCode ? (ptr[4] & 0x1F) : (ptr[3] & 0x1F);
129 if (nal_unit_type == 1) {
130 int32_t firstMBInSlice = readFirstMbInSlice (ptr + byteOffset);
131 if (++non_idr_pict_count >= 1 && idr_pict_count >= 1 && firstMBInSlice == 0) {
132 return read_bytes;
133 }
134 if (non_idr_pict_count >= 2 && firstMBInSlice == 0) {
135 return read_bytes;
136 }
137 } else if (nal_unit_type == 5) {
138 int32_t firstMBInSlice = readFirstMbInSlice (ptr + byteOffset);
139 if (++idr_pict_count >= 1 && non_idr_pict_count >= 1 && firstMBInSlice == 0) {
140 return read_bytes;
141 }
142 if (idr_pict_count >= 2 && firstMBInSlice == 0) {
143 return read_bytes;
144 }
145 } else if (nal_unit_type == 7) {
146 pSpsBuf = ptr + (has4ByteStartCode ? 4 : 3);
147 if ((++sps_count >= 1) && (non_idr_pict_count >= 1 || idr_pict_count >= 1)) {
148 return read_bytes;
149 }
150 if (sps_count == 2) {
151 return read_bytes;
152 }
153 } else if (nal_unit_type == 8) {
154 if (++pps_count == 1 && sps_count == 1) {
155 sps_byte_count = int32_t (ptr - pSpsBuf);
156 }
157 if (pps_count >= 1 && (non_idr_pict_count >= 1 || idr_pict_count >= 1)) {
158 return read_bytes;
159 }
160 } else if (nal_unit_type == 9) {
161 if (++nal_deliminator == 2) {
162 return read_bytes;
163 }
164 }
165 if (read_bytes >= bytes_available - 4) {
166 return bytes_available;
167 }
168 read_bytes += 4;
169 ptr += 4;
170 } else {
171 ++ptr;
172 ++read_bytes;
173 }
174 }
175 return bytes_available;
176 }
177
FlushFrames(ISVCDecoder * pDecoder,int64_t & iTotal,FILE * pYuvFile,FILE * pOptionFile,int32_t & iFrameCount,unsigned long long & uiTimeStamp,int32_t & iWidth,int32_t & iHeight,int32_t & iLastWidth,int32_t iLastHeight)178 void FlushFrames (ISVCDecoder* pDecoder, int64_t& iTotal, FILE* pYuvFile, FILE* pOptionFile, int32_t& iFrameCount,
179 unsigned long long& uiTimeStamp, int32_t& iWidth, int32_t& iHeight, int32_t& iLastWidth, int32_t iLastHeight) {
180 uint8_t* pData[3] = { NULL };
181 uint8_t* pDst[3] = { NULL };
182 SBufferInfo sDstBufInfo;
183 int32_t num_of_frames_in_buffer = 0;
184 CUtils cOutputModule;
185 pDecoder->GetOption (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, &num_of_frames_in_buffer);
186 for (int32_t i = 0; i < num_of_frames_in_buffer; ++i) {
187 int64_t iStart = WelsTime();
188 pData[0] = NULL;
189 pData[1] = NULL;
190 pData[2] = NULL;
191 memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
192 sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
193 pDecoder->FlushFrame (pData, &sDstBufInfo);
194 if (sDstBufInfo.iBufferStatus == 1) {
195 pDst[0] = sDstBufInfo.pDst[0];
196 pDst[1] = sDstBufInfo.pDst[1];
197 pDst[2] = sDstBufInfo.pDst[2];
198 }
199 int64_t iEnd = WelsTime();
200 iTotal += iEnd - iStart;
201 if (sDstBufInfo.iBufferStatus == 1) {
202 cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
203 iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
204 iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
205 if (pOptionFile != NULL) {
206 if (iWidth != iLastWidth && iHeight != iLastHeight) {
207 fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
208 fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
209 fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
210 iLastWidth = iWidth;
211 iLastHeight = iHeight;
212 }
213 }
214 ++iFrameCount;
215 }
216 }
217 }
H264DecodeInstance(ISVCDecoder * pDecoder,const char * kpH264FileName,const char * kpOuputFileName,int32_t & iWidth,int32_t & iHeight,const char * pOptionFileName,const char * pLengthFileName,int32_t iErrorConMethod,bool bLegacyCalling)218 void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, const char* kpOuputFileName,
219 int32_t& iWidth, int32_t& iHeight, const char* pOptionFileName, const char* pLengthFileName,
220 int32_t iErrorConMethod,
221 bool bLegacyCalling) {
222 FILE* pH264File = NULL;
223 FILE* pYuvFile = NULL;
224 FILE* pOptionFile = NULL;
225 // Lenght input mode support
226 FILE* fpTrack = NULL;
227
228 if (pDecoder == NULL) return;
229
230 int32_t pInfo[4];
231 unsigned long long uiTimeStamp = 0;
232 int64_t iStart = 0, iEnd = 0, iTotal = 0;
233 int32_t iSliceSize;
234 int32_t iSliceIndex = 0;
235 uint8_t* pBuf = NULL;
236 uint8_t uiStartCode[4] = {0, 0, 0, 1};
237
238 uint8_t* pData[3] = {NULL};
239 uint8_t* pDst[3] = {NULL};
240 SBufferInfo sDstBufInfo;
241
242 int32_t iBufPos = 0;
243 int32_t iFileSize;
244 int32_t iLastWidth = 0, iLastHeight = 0;
245 int32_t iFrameCount = 0;
246 int32_t iEndOfStreamFlag = 0;
247 pDecoder->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iErrorConMethod);
248 CUtils cOutputModule;
249 double dElapsed = 0;
250 uint8_t uLastSpsBuf[32];
251 int32_t iLastSpsByteCount = 0;
252
253 int32_t iThreadCount = 1;
254 pDecoder->GetOption (DECODER_OPTION_NUM_OF_THREADS, &iThreadCount);
255
256 if (kpH264FileName) {
257 pH264File = fopen (kpH264FileName, "rb");
258 if (pH264File == NULL) {
259 fprintf (stderr, "Can not open h264 source file, check its legal path related please..\n");
260 return;
261 }
262 fprintf (stderr, "H264 source file name: %s..\n", kpH264FileName);
263 } else {
264 fprintf (stderr, "Can not find any h264 bitstream file to read..\n");
265 fprintf (stderr, "----------------decoder return------------------------\n");
266 return;
267 }
268
269 if (kpOuputFileName) {
270 pYuvFile = fopen (kpOuputFileName, "wb");
271 if (pYuvFile == NULL) {
272 fprintf (stderr, "Can not open yuv file to output result of decoding..\n");
273 // any options
274 //return; // can let decoder work in quiet mode, no writing any output
275 } else
276 fprintf (stderr, "Sequence output file name: %s..\n", kpOuputFileName);
277 } else {
278 fprintf (stderr, "Can not find any output file to write..\n");
279 // any options
280 }
281
282 if (pOptionFileName) {
283 pOptionFile = fopen (pOptionFileName, "wb");
284 if (pOptionFile == NULL) {
285 fprintf (stderr, "Can not open optional file for write..\n");
286 } else
287 fprintf (stderr, "Extra optional file: %s..\n", pOptionFileName);
288 }
289
290 if (pLengthFileName != NULL) {
291 fpTrack = fopen (pLengthFileName, "rb");
292 if (fpTrack == NULL)
293 printf ("Length file open ERROR!\n");
294 }
295
296 printf ("------------------------------------------------------\n");
297
298 fseek (pH264File, 0L, SEEK_END);
299 iFileSize = (int32_t) ftell (pH264File);
300 if (iFileSize <= 4) {
301 fprintf (stderr, "Current Bit Stream File is too small, read error!!!!\n");
302 goto label_exit;
303 }
304 fseek (pH264File, 0L, SEEK_SET);
305
306 pBuf = new uint8_t[iFileSize + 4];
307 if (pBuf == NULL) {
308 fprintf (stderr, "new buffer failed!\n");
309 goto label_exit;
310 }
311
312 if (fread (pBuf, 1, iFileSize, pH264File) != (uint32_t)iFileSize) {
313 fprintf (stderr, "Unable to read whole file\n");
314 goto label_exit;
315 }
316
317 memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
318
319 while (true) {
320
321 if (iBufPos >= iFileSize) {
322 iEndOfStreamFlag = true;
323 if (iEndOfStreamFlag)
324 pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
325 break;
326 }
327 // Read length from file if needed
328 if (fpTrack) {
329 if (fread (pInfo, 4, sizeof (int32_t), fpTrack) < 4)
330 goto label_exit;
331 iSliceSize = static_cast<int32_t> (pInfo[2]);
332 } else {
333 if (iThreadCount >= 1) {
334 uint8_t* uSpsPtr = NULL;
335 int32_t iSpsByteCount = 0;
336 iSliceSize = readPicture (pBuf, iFileSize, iBufPos, uSpsPtr, iSpsByteCount);
337 if (iLastSpsByteCount > 0 && iSpsByteCount > 0) {
338 if (iSpsByteCount != iLastSpsByteCount || memcmp (uSpsPtr, uLastSpsBuf, iLastSpsByteCount) != 0) {
339 //whenever new sequence is different from preceding sequence. All pending frames must be flushed out before the new sequence can start to decode.
340 FlushFrames (pDecoder, iTotal, pYuvFile, pOptionFile, iFrameCount, uiTimeStamp, iWidth, iHeight, iLastWidth,
341 iLastHeight);
342 }
343 }
344 if (iSpsByteCount > 0 && uSpsPtr != NULL) {
345 if (iSpsByteCount > 32) iSpsByteCount = 32;
346 iLastSpsByteCount = iSpsByteCount;
347 memcpy (uLastSpsBuf, uSpsPtr, iSpsByteCount);
348 }
349 } else {
350 int i = 0;
351 for (i = 0; i < iFileSize; i++) {
352 if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
353 && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
354 break;
355 }
356 }
357 iSliceSize = i;
358 }
359 }
360 if (iSliceSize < 4) { //too small size, no effective data, ignore
361 iBufPos += iSliceSize;
362 continue;
363 }
364
365 //for coverage test purpose
366 int32_t iEndOfStreamFlag;
367 pDecoder->GetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
368 int32_t iCurIdrPicId;
369 pDecoder->GetOption (DECODER_OPTION_IDR_PIC_ID, &iCurIdrPicId);
370 int32_t iFrameNum;
371 pDecoder->GetOption (DECODER_OPTION_FRAME_NUM, &iFrameNum);
372 int32_t bCurAuContainLtrMarkSeFlag;
373 pDecoder->GetOption (DECODER_OPTION_LTR_MARKING_FLAG, &bCurAuContainLtrMarkSeFlag);
374 int32_t iFrameNumOfAuMarkedLtr;
375 pDecoder->GetOption (DECODER_OPTION_LTR_MARKED_FRAME_NUM, &iFrameNumOfAuMarkedLtr);
376 int32_t iFeedbackVclNalInAu;
377 pDecoder->GetOption (DECODER_OPTION_VCL_NAL, &iFeedbackVclNalInAu);
378 int32_t iFeedbackTidInAu;
379 pDecoder->GetOption (DECODER_OPTION_TEMPORAL_ID, &iFeedbackTidInAu);
380 //~end for
381
382 iStart = WelsTime();
383 pData[0] = NULL;
384 pData[1] = NULL;
385 pData[2] = NULL;
386 uiTimeStamp ++;
387 memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
388 sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
389 if (!bLegacyCalling) {
390 pDecoder->DecodeFrameNoDelay (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
391 } else {
392 pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
393 }
394
395 if (sDstBufInfo.iBufferStatus == 1) {
396 pDst[0] = sDstBufInfo.pDst[0];
397 pDst[1] = sDstBufInfo.pDst[1];
398 pDst[2] = sDstBufInfo.pDst[2];
399 }
400 iEnd = WelsTime();
401 iTotal += iEnd - iStart;
402 if (sDstBufInfo.iBufferStatus == 1) {
403 cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
404 iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
405 iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
406
407 if (pOptionFile != NULL) {
408 if (iWidth != iLastWidth && iHeight != iLastHeight) {
409 fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
410 fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
411 fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
412 iLastWidth = iWidth;
413 iLastHeight = iHeight;
414 }
415 }
416 ++ iFrameCount;
417 }
418
419 if (bLegacyCalling) {
420 iStart = WelsTime();
421 pData[0] = NULL;
422 pData[1] = NULL;
423 pData[2] = NULL;
424 memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
425 sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
426 pDecoder->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
427 if (sDstBufInfo.iBufferStatus == 1) {
428 pDst[0] = sDstBufInfo.pDst[0];
429 pDst[1] = sDstBufInfo.pDst[1];
430 pDst[2] = sDstBufInfo.pDst[2];
431 }
432 iEnd = WelsTime();
433 iTotal += iEnd - iStart;
434 if (sDstBufInfo.iBufferStatus == 1) {
435 cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
436 iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
437 iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
438
439 if (pOptionFile != NULL) {
440 if (iWidth != iLastWidth && iHeight != iLastHeight) {
441 fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
442 fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
443 fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
444 iLastWidth = iWidth;
445 iLastHeight = iHeight;
446 }
447 }
448 ++ iFrameCount;
449 }
450 }
451 iBufPos += iSliceSize;
452 ++ iSliceIndex;
453 }
454 FlushFrames (pDecoder, iTotal, pYuvFile, pOptionFile, iFrameCount, uiTimeStamp, iWidth, iHeight, iLastWidth,
455 iLastHeight);
456 dElapsed = iTotal / 1e6;
457 fprintf (stderr, "-------------------------------------------------------\n");
458 fprintf (stderr, "iWidth:\t\t%d\nheight:\t\t%d\nFrames:\t\t%d\ndecode time:\t%f sec\nFPS:\t\t%f fps\n",
459 iWidth, iHeight, iFrameCount, dElapsed, (iFrameCount * 1.0) / dElapsed);
460 fprintf (stderr, "-------------------------------------------------------\n");
461
462 #if defined (WINDOWS_PHONE)
463 g_dDecTime = dElapsed;
464 g_fDecFPS = (iFrameCount * 1.0f) / (float) dElapsed;
465 g_iDecodedFrameNum = iFrameCount;
466 #endif
467
468 // coverity scan uninitial
469 label_exit:
470 if (pBuf) {
471 delete[] pBuf;
472 pBuf = NULL;
473 }
474 if (pH264File) {
475 fclose (pH264File);
476 pH264File = NULL;
477 }
478 if (pYuvFile) {
479 fclose (pYuvFile);
480 pYuvFile = NULL;
481 }
482 if (pOptionFile) {
483 fclose (pOptionFile);
484 pOptionFile = NULL;
485 }
486 if (fpTrack) {
487 fclose (fpTrack);
488 fpTrack = NULL;
489 }
490
491 }
492
493 #if (defined(ANDROID_NDK)||defined(APPLE_IOS) || defined (WINDOWS_PHONE))
DecMain(int32_t iArgC,char * pArgV[])494 int32_t DecMain (int32_t iArgC, char* pArgV[]) {
495 #else
496 int32_t main (int32_t iArgC, char* pArgV[]) {
497 #endif
498 ISVCDecoder* pDecoder = NULL;
499
500 SDecodingParam sDecParam = {0};
501 string strInputFile (""), strOutputFile (""), strOptionFile (""), strLengthFile ("");
502 int iLevelSetting = (int) WELS_LOG_WARNING;
503 bool bLegacyCalling = false;
504
505 sDecParam.sVideoProperty.size = sizeof (sDecParam.sVideoProperty);
506 sDecParam.eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
507
508 if (iArgC < 2) {
509 printf ("usage 1: h264dec.exe welsdec.cfg\n");
510 printf ("usage 2: h264dec.exe welsdec.264 out.yuv\n");
511 printf ("usage 3: h264dec.exe welsdec.264\n");
512 return 1;
513 } else if (iArgC == 2) {
514 if (strstr (pArgV[1], ".cfg")) { // read config file //confirmed_safe_unsafe_usage
515 CReadConfig cReadCfg (pArgV[1]);
516 string strTag[4];
517 string strReconFile ("");
518
519 if (!cReadCfg.ExistFile()) {
520 printf ("Specified file: %s not exist, maybe invalid path or parameter settting.\n", cReadCfg.GetFileName().c_str());
521 return 1;
522 }
523
524 while (!cReadCfg.EndOfFile()) {
525 long nRd = cReadCfg.ReadLine (&strTag[0]);
526 if (nRd > 0) {
527 if (strTag[0].compare ("InputFile") == 0) {
528 strInputFile = strTag[1];
529 } else if (strTag[0].compare ("OutputFile") == 0) {
530 strOutputFile = strTag[1];
531 } else if (strTag[0].compare ("RestructionFile") == 0) {
532 strReconFile = strTag[1];
533 int32_t iLen = (int32_t)strReconFile.length();
534 sDecParam.pFileNameRestructed = new char[iLen + 1];
535 if (sDecParam.pFileNameRestructed != NULL) {
536 sDecParam.pFileNameRestructed[iLen] = 0;
537 }
538
539 strncpy (sDecParam.pFileNameRestructed, strReconFile.c_str(), iLen); //confirmed_safe_unsafe_usage
540 } else if (strTag[0].compare ("TargetDQID") == 0) {
541 sDecParam.uiTargetDqLayer = (uint8_t)atol (strTag[1].c_str());
542 } else if (strTag[0].compare ("ErrorConcealmentIdc") == 0) {
543 sDecParam.eEcActiveIdc = (ERROR_CON_IDC)atol (strTag[1].c_str());
544 } else if (strTag[0].compare ("CPULoad") == 0) {
545 sDecParam.uiCpuLoad = (uint32_t)atol (strTag[1].c_str());
546 } else if (strTag[0].compare ("VideoBitstreamType") == 0) {
547 sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE)atol (strTag[1].c_str());
548 }
549 }
550 }
551 if (strOutputFile.empty()) {
552 printf ("No output file specified in configuration file.\n");
553 return 1;
554 }
555 } else if (strstr (pArgV[1],
556 ".264")) { // no output dump yuv file, just try to render the decoded pictures //confirmed_safe_unsafe_usage
557 strInputFile = pArgV[1];
558 sDecParam.uiTargetDqLayer = (uint8_t) - 1;
559 sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
560 sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
561 }
562 } else { //iArgC > 2
563 strInputFile = pArgV[1];
564 strOutputFile = pArgV[2];
565 sDecParam.uiTargetDqLayer = (uint8_t) - 1;
566 sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
567 sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
568 if (iArgC > 3) {
569 for (int i = 3; i < iArgC; i++) {
570 char* cmd = pArgV[i];
571
572 if (!strcmp (cmd, "-options")) {
573 if (i + 1 < iArgC)
574 strOptionFile = pArgV[++i];
575 else {
576 printf ("options file not specified.\n");
577 return 1;
578 }
579 } else if (!strcmp (cmd, "-trace")) {
580 if (i + 1 < iArgC)
581 iLevelSetting = atoi (pArgV[++i]);
582 else {
583 printf ("trace level not specified.\n");
584 return 1;
585 }
586 } else if (!strcmp (cmd, "-length")) {
587 if (i + 1 < iArgC)
588 strLengthFile = pArgV[++i];
589 else {
590 printf ("lenght file not specified.\n");
591 return 1;
592 }
593 } else if (!strcmp (cmd, "-ec")) {
594 if (i + 1 < iArgC) {
595 int iEcActiveIdc = atoi (pArgV[++i]);
596 sDecParam.eEcActiveIdc = (ERROR_CON_IDC)iEcActiveIdc;
597 printf ("ERROR_CON(cealment) is set to %d.\n", iEcActiveIdc);
598 }
599 } else if (!strcmp (cmd, "-legacy")) {
600 bLegacyCalling = true;
601 }
602 }
603 }
604
605 if (strOutputFile.empty()) {
606 printf ("No output file specified in configuration file.\n");
607 return 1;
608 }
609 }
610
611 if (strInputFile.empty()) {
612 printf ("No input file specified in configuration file.\n");
613 return 1;
614 }
615
616
617
618
619 if (WelsCreateDecoder (&pDecoder) || (NULL == pDecoder)) {
620 printf ("Create Decoder failed.\n");
621 return 1;
622 }
623 if (iLevelSetting >= 0) {
624 pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);
625 }
626
627 int32_t iThreadCount = 0;
628 pDecoder->SetOption (DECODER_OPTION_NUM_OF_THREADS, &iThreadCount);
629
630 if (pDecoder->Initialize (&sDecParam)) {
631 printf ("Decoder initialization failed.\n");
632 return 1;
633 }
634
635
636 int32_t iWidth = 0;
637 int32_t iHeight = 0;
638
639
640 H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth,
641 iHeight,
642 (!strOptionFile.empty() ? strOptionFile.c_str() : NULL), (!strLengthFile.empty() ? strLengthFile.c_str() : NULL),
643 (int32_t)sDecParam.eEcActiveIdc,
644 bLegacyCalling);
645
646 if (sDecParam.pFileNameRestructed != NULL) {
647 delete []sDecParam.pFileNameRestructed;
648 sDecParam.pFileNameRestructed = NULL;
649 }
650
651 if (pDecoder) {
652 pDecoder->Uninitialize();
653
654 WelsDestroyDecoder (pDecoder);
655 }
656
657 return 0;
658 }
659