Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "H264SwDecApi.h"
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 void WriteOutput(FILE *fid, u8 *data, u32 picSize);
     23 
     24 /*------------------------------------------------------------------------------
     25 
     26     Function name:  main
     27 
     28     Purpose:
     29         main function. Assuming that executable is named 'decoder' the usage
     30         is as follows
     31 
     32             decoder inputFileName
     33 
     34         , where inputFileName shall be name of file containing h264 stream
     35         data.
     36 
     37 ------------------------------------------------------------------------------*/
     38 int main(int argc, char **argv)
     39 {
     40 
     41     u8 *byteStrmStart;
     42     u8 *byteStrm;
     43     u32 strmLen;
     44     u32 picSize;
     45     H264SwDecInst decInst;
     46     H264SwDecRet ret;
     47     H264SwDecInput decInput;
     48     H264SwDecOutput decOutput;
     49     H264SwDecPicture decPicture;
     50     H264SwDecInfo decInfo;
     51     u32 picNumber;
     52 
     53     FILE *finput;
     54     FILE *foutput;
     55 
     56     /* Check that enough command line arguments given, if not -> print usage
     57      * information out */
     58     if (argc < 2)
     59     {
     60         printf( "Usage: %s file.h264\n", argv[0]);
     61         return -1;
     62     }
     63 
     64     /* open output file for writing, output file named out.yuv. If file open
     65      * fails -> exit */
     66     foutput = fopen("out.yuv", "wb");
     67     if (foutput == NULL)
     68     {
     69         printf("UNABLE TO OPEN OUTPUT FILE\n");
     70         return -1;
     71     }
     72 
     73     /* open input file for reading, file name given by user. If file open
     74      * fails -> exit */
     75     finput = fopen(argv[argc-1], "rb");
     76     if (finput == NULL)
     77     {
     78         printf("UNABLE TO OPEN INPUT FILE\n");
     79         return -1;
     80     }
     81 
     82     /* check size of the input file -> length of the stream in bytes */
     83     fseek(finput, 0L, SEEK_END);
     84     strmLen = (u32)ftell(finput);
     85     rewind(finput);
     86 
     87     /* allocate memory for stream buffer, exit if unsuccessful */
     88     byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8)*strmLen);
     89     if (byteStrm == NULL)
     90     {
     91         printf("UNABLE TO ALLOCATE MEMORY\n");
     92         return -1;
     93     }
     94 
     95     /* read input stream from file to buffer and close input file */
     96     fread(byteStrm, sizeof(u8), strmLen, finput);
     97     fclose(finput);
     98 
     99     /* initialize decoder. If unsuccessful -> exit */
    100     ret = H264SwDecInit(&decInst, 0);
    101     if (ret != H264SWDEC_OK)
    102     {
    103         printf("DECODER INITIALIZATION FAILED\n");
    104         return -1;
    105     }
    106 
    107     /* initialize H264SwDecDecode() input structure */
    108     decInput.pStream = byteStrmStart;
    109     decInput.dataLen = strmLen;
    110     decInput.intraConcealmentMethod = 0;
    111 
    112     picNumber = 0;
    113 
    114     /* For performance measurements, read the start time (in seconds) here.
    115      * The decoding time should be measured over several frames and after
    116      * that average fps (frames/second) can be calculated.
    117      *
    118      * startTime = GetTime();
    119      *
    120      * To prevent calculating file I/O latensies as a decoding time,
    121      * comment out WriteOutput function call. Also prints to stdout might
    122      * consume considerable amount of cycles during measurement */
    123 
    124     /* main decoding loop */
    125     do
    126     {
    127         /* call API function to perform decoding */
    128         ret = H264SwDecDecode(decInst, &decInput, &decOutput);
    129 
    130         switch(ret)
    131         {
    132 
    133             case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
    134 
    135                 /* picture dimensions are available for query now */
    136                 ret = H264SwDecGetInfo(decInst, &decInfo);
    137                 if (ret != H264SWDEC_OK)
    138                     return -1;
    139 
    140                 /* picture size in pixels */
    141                 picSize = decInfo.picWidth * decInfo.picHeight;
    142                 /* memory needed for YCbCr 4:2:0 picture in bytes */
    143                 picSize = (3 * picSize)/2;
    144                 /* memory needed for 16-bit RGB picture in bytes
    145                  * picSize = (decInfo.picWidth * decInfo.picHeight) * 2; */
    146 
    147                 printf("Width %d Height %d\n",
    148                     decInfo.picWidth, decInfo.picHeight);
    149 
    150                 /* update H264SwDecDecode() input structure, number of bytes
    151                  * "consumed" is computed as difference between the new stream
    152                  * pointer and old stream pointer */
    153                 decInput.dataLen -=
    154                     (u32)(decOutput.pStrmCurrPos - decInput.pStream);
    155                 decInput.pStream = decOutput.pStrmCurrPos;
    156                 break;
    157 
    158             case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
    159             case H264SWDEC_PIC_RDY:
    160 
    161                 /* update H264SwDecDecode() input structure, number of bytes
    162                  * "consumed" is computed as difference between the new stream
    163                  * pointer and old stream pointer */
    164                 decInput.dataLen -=
    165                     (u32)(decOutput.pStrmCurrPos - decInput.pStream);
    166                 decInput.pStream = decOutput.pStrmCurrPos;
    167 
    168                 /* use function H264SwDecNextPicture() to obtain next picture
    169                  * in display order. Function is called until no more images
    170                  * are ready for display */
    171                 while (H264SwDecNextPicture(decInst, &decPicture, 0) ==
    172                     H264SWDEC_PIC_RDY) { picNumber++;
    173 
    174                     printf("PIC %d, type %s, concealed %d\n", picNumber,
    175                         decPicture.isIdrPicture ? "IDR" : "NON-IDR",
    176                         decPicture.nbrOfErrMBs);
    177                     fflush(stdout);
    178 
    179                     /* Do color conversion if needed to get display image
    180                      * in RGB-format
    181                      *
    182                      * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */
    183 
    184                     /* write next display image to output file */
    185                     WriteOutput(foutput, (u8*)decPicture.pOutputPicture,
    186                         picSize);
    187                 }
    188 
    189                 break;
    190 
    191             case H264SWDEC_EVALUATION_LIMIT_EXCEEDED:
    192                 /* evaluation version of the decoder has limited decoding
    193                  * capabilities */
    194                 printf("EVALUATION LIMIT REACHED\n");
    195                 goto end;
    196 
    197             default:
    198                 printf("UNRECOVERABLE ERROR\n");
    199                 return -1;
    200         }
    201     /* keep decoding until all data from input stream buffer consumed */
    202     } while (decInput.dataLen > 0);
    203 
    204 end:
    205 
    206     /* if output in display order is preferred, the decoder shall be forced
    207      * to output pictures remaining in decoded picture buffer. Use function
    208      * H264SwDecNextPicture() to obtain next picture in display order. Function
    209      * is called until no more images are ready for display. Second parameter
    210      * for the function is set to '1' to indicate that this is end of the
    211      * stream and all pictures shall be output */
    212     while (H264SwDecNextPicture(decInst, &decPicture, 1) ==
    213         H264SWDEC_PIC_RDY) {
    214 
    215         picNumber++;
    216 
    217         printf("PIC %d, type %s, concealed %d\n", picNumber,
    218             decPicture.isIdrPicture ? "IDR" : "NON-IDR",
    219             decPicture.nbrOfErrMBs);
    220         fflush(stdout);
    221 
    222         /* Do color conversion if needed to get display image
    223          * in RGB-format
    224          *
    225          * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */
    226 
    227         /* write next display image to output file */
    228         WriteOutput(foutput, (u8*)decPicture.pOutputPicture, picSize);
    229     }
    230 
    231     /* For performance measurements, read the end time (in seconds) here.
    232      *
    233      * endTime = GetTime();
    234      *
    235      * Now the performance can be calculated as frames per second:
    236      * fps = picNumber / (endTime - startTime); */
    237 
    238 
    239     /* release decoder instance */
    240     H264SwDecRelease(decInst);
    241 
    242     /* close output file */
    243     fclose(foutput);
    244 
    245     /* free byte stream buffer */
    246     free(byteStrmStart);
    247 
    248     return 0;
    249 
    250 }
    251 
    252 /*------------------------------------------------------------------------------
    253 
    254     Function name:  WriteOutput
    255 
    256     Purpose:
    257         Write picture pointed by data to file pointed by fid. Size of the
    258         picture in pixels is indicated by picSize.
    259 
    260 ------------------------------------------------------------------------------*/
    261 void WriteOutput(FILE *fid, u8 *data, u32 picSize)
    262 {
    263     fwrite(data, 1, picSize, fid);
    264 }
    265 
    266 /*------------------------------------------------------------------------------
    267 
    268     Function name:  H264SwDecTrace
    269 
    270     Purpose:
    271         Example implementation of H264SwDecTrace function. Prototype of this
    272         function is given in H264SwDecApi.h. This implementation appends
    273         trace messages to file named 'dec_api.trc'.
    274 
    275 ------------------------------------------------------------------------------*/
    276 void H264SwDecTrace(char *string)
    277 {
    278     FILE *fp;
    279 
    280     fp = fopen("dec_api.trc", "at");
    281 
    282     if (!fp)
    283         return;
    284 
    285     fwrite(string, 1, strlen(string), fp);
    286     fwrite("\n", 1,1, fp);
    287 
    288     fclose(fp);
    289 }
    290 
    291 /*------------------------------------------------------------------------------
    292 
    293     Function name:  H264SwDecmalloc
    294 
    295     Purpose:
    296         Example implementation of H264SwDecMalloc function. Prototype of this
    297         function is given in H264SwDecApi.h. This implementation uses
    298         library function malloc for allocation of memory.
    299 
    300 ------------------------------------------------------------------------------*/
    301 void* H264SwDecMalloc(u32 size)
    302 {
    303     return malloc(size);
    304 }
    305 
    306 /*------------------------------------------------------------------------------
    307 
    308     Function name:  H264SwDecFree
    309 
    310     Purpose:
    311         Example implementation of H264SwDecFree function. Prototype of this
    312         function is given in H264SwDecApi.h. This implementation uses
    313         library function free for freeing of memory.
    314 
    315 ------------------------------------------------------------------------------*/
    316 void H264SwDecFree(void *ptr)
    317 {
    318     free(ptr);
    319 }
    320 
    321 /*------------------------------------------------------------------------------
    322 
    323     Function name:  H264SwDecMemcpy
    324 
    325     Purpose:
    326         Example implementation of H264SwDecMemcpy function. Prototype of this
    327         function is given in H264SwDecApi.h. This implementation uses
    328         library function memcpy to copy src to dest.
    329 
    330 ------------------------------------------------------------------------------*/
    331 void H264SwDecMemcpy(void *dest, void *src, u32 count)
    332 {
    333     memcpy(dest, src, count);
    334 }
    335 
    336 /*------------------------------------------------------------------------------
    337 
    338     Function name:  H264SwDecMemset
    339 
    340     Purpose:
    341         Example implementation of H264SwDecMemset function. Prototype of this
    342         function is given in H264SwDecApi.h. This implementation uses
    343         library function memset to set content of memory area pointed by ptr.
    344 
    345 ------------------------------------------------------------------------------*/
    346 void H264SwDecMemset(void *ptr, i32 value, u32 count)
    347 {
    348     memset(ptr, value, count);
    349 }
    350 
    351