• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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