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 /* CVS tag name for identification */
     18 const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $";
     19 
     20 #include "H264SwDecApi.h"
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 
     25 #define DEBUG(argv) printf argv
     26 
     27 /* _NO_OUT disables output file writing */
     28 #ifdef __arm
     29 #define _NO_OUT
     30 #endif
     31 
     32 /*------------------------------------------------------------------------------
     33 
     34 ------------------------------------------------------------------------------*/
     35 void WriteOutput(FILE *fid, u8 *data, u32 picSize);
     36 
     37 u32 CropPicture(u8 *pOutImage, u8 *pInImage,
     38     u32 picWidth, u32 picHeight, CropParams *pCropParams);
     39 
     40 void CropWriteOutput(FILE *fid, u8 *imageData, u32 cropDisplay,
     41         H264SwDecInfo *decInfo);
     42 
     43 typedef struct
     44 {
     45     H264SwDecInst decInst;
     46     H264SwDecInput decInput;
     47     H264SwDecOutput decOutput;
     48     H264SwDecPicture decPicture;
     49     H264SwDecInfo decInfo;
     50     FILE *foutput;
     51     char outFileName[256];
     52     u8 *byteStrmStart;
     53     u32 picNumber;
     54 } Decoder;
     55 
     56 
     57 /*------------------------------------------------------------------------------
     58 
     59 ------------------------------------------------------------------------------*/
     60 int main(int argc, char **argv)
     61 {
     62 
     63     i32 instCount, instRunning;
     64     i32 i;
     65     u32 maxNumPics;
     66     u32 strmLen;
     67     H264SwDecRet ret;
     68     u32 numErrors = 0;
     69     u32 cropDisplay = 0;
     70     u32 disableOutputReordering = 0;
     71     FILE *finput;
     72     Decoder **decoder;
     73     char outFileName[256] = "out.yuv";
     74 
     75 
     76     if ( argc > 1 && strcmp(argv[1], "-T") == 0 )
     77     {
     78         fprintf(stderr, "%s\n", tagName);
     79         return 0;
     80     }
     81 
     82     if (argc < 2)
     83     {
     84         DEBUG((
     85             "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file1.264 [file2.264] .. [fileN.264]\n",
     86             argv[0]));
     87         DEBUG(("\t-Nn forces decoding to stop after n pictures\n"));
     88 #if defined(_NO_OUT)
     89         DEBUG(("\t-Ooutfile output writing disabled at compile time\n"));
     90 #else
     91         DEBUG(("\t-Ooutfile write output to \"outfile\" (default out.yuv)\n"));
     92         DEBUG(("\t-Onone does not write output\n"));
     93 #endif
     94         DEBUG(("\t-C display cropped image (default decoded image)\n"));
     95         DEBUG(("\t-R disable DPB output reordering\n"));
     96         DEBUG(("\t-T to print tag name and exit\n"));
     97         exit(100);
     98     }
     99 
    100     instCount = argc - 1;
    101 
    102     /* read command line arguments */
    103     maxNumPics = 0;
    104     for (i = 1; i < (argc-1); i++)
    105     {
    106         if ( strncmp(argv[i], "-N", 2) == 0 )
    107         {
    108             maxNumPics = (u32)atoi(argv[i]+2);
    109             instCount--;
    110         }
    111         else if ( strncmp(argv[i], "-O", 2) == 0 )
    112         {
    113             strcpy(outFileName, argv[i]+2);
    114             instCount--;
    115         }
    116         else if ( strcmp(argv[i], "-C") == 0 )
    117         {
    118             cropDisplay = 1;
    119             instCount--;
    120         }
    121         else if ( strcmp(argv[i], "-R") == 0 )
    122         {
    123             disableOutputReordering = 1;
    124             instCount--;
    125         }
    126     }
    127 
    128     if (instCount < 1)
    129     {
    130         DEBUG(("No input files\n"));
    131         exit(100);
    132     }
    133 
    134     /* allocate memory for multiple decoder instances
    135      * one instance for every stream file */
    136     decoder = (Decoder **)malloc(sizeof(Decoder*)*(u32)instCount);
    137     if (decoder == NULL)
    138     {
    139         DEBUG(("Unable to allocate memory\n"));
    140         exit(100);
    141     }
    142 
    143     /* prepare each decoder instance */
    144     for (i = 0; i < instCount; i++)
    145     {
    146         decoder[i] = (Decoder *)calloc(1, sizeof(Decoder));
    147 
    148         /* open input file */
    149         finput = fopen(argv[argc-instCount+i],"rb");
    150         if (finput == NULL)
    151         {
    152             DEBUG(("Unable to open input file <%s>\n", argv[argc-instCount+i]));
    153             exit(100);
    154         }
    155 
    156         DEBUG(("Reading input file[%d] %s\n", i, argv[argc-instCount+i]));
    157 
    158         /* read input stream to buffer */
    159         fseek(finput,0L,SEEK_END);
    160         strmLen = (u32)ftell(finput);
    161         rewind(finput);
    162         decoder[i]->byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen);
    163         if (decoder[i]->byteStrmStart == NULL)
    164         {
    165             DEBUG(("Unable to allocate memory\n"));
    166             exit(100);
    167         }
    168         fread(decoder[i]->byteStrmStart, sizeof(u8), strmLen, finput);
    169         fclose(finput);
    170 
    171         /* open output file */
    172         if (strcmp(outFileName, "none") != 0)
    173         {
    174 #if defined(_NO_OUT)
    175             decoder[i]->foutput = NULL;
    176 #else
    177             sprintf(decoder[i]->outFileName, "%s%i", outFileName, i);
    178             decoder[i]->foutput = fopen(decoder[i]->outFileName, "wb");
    179             if (decoder[i]->foutput == NULL)
    180             {
    181                 DEBUG(("Unable to open output file\n"));
    182                 exit(100);
    183             }
    184 #endif
    185         }
    186 
    187         ret = H264SwDecInit(&(decoder[i]->decInst), disableOutputReordering);
    188 
    189         if (ret != H264SWDEC_OK)
    190         {
    191             DEBUG(("Init failed %d\n", ret));
    192             exit(100);
    193         }
    194 
    195         decoder[i]->decInput.pStream = decoder[i]->byteStrmStart;
    196         decoder[i]->decInput.dataLen = strmLen;
    197         decoder[i]->decInput.intraConcealmentMethod = 0;
    198 
    199     }
    200 
    201     /* main decoding loop */
    202     do
    203     {
    204         /* decode once using each instance */
    205         for (i = 0; i < instCount; i++)
    206         {
    207             ret = H264SwDecDecode(decoder[i]->decInst,
    208                                 &(decoder[i]->decInput),
    209                                 &(decoder[i]->decOutput));
    210 
    211             switch(ret)
    212             {
    213 
    214                 case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
    215 
    216                     ret = H264SwDecGetInfo(decoder[i]->decInst,
    217                             &(decoder[i]->decInfo));
    218                     if (ret != H264SWDEC_OK)
    219                         exit(1);
    220 
    221                     if (cropDisplay && decoder[i]->decInfo.croppingFlag)
    222                     {
    223                         DEBUG(("Decoder[%d] Cropping params: (%d, %d) %dx%d\n",
    224                             i,
    225                             decoder[i]->decInfo.cropParams.cropLeftOffset,
    226                             decoder[i]->decInfo.cropParams.cropTopOffset,
    227                             decoder[i]->decInfo.cropParams.cropOutWidth,
    228                             decoder[i]->decInfo.cropParams.cropOutHeight));
    229                     }
    230 
    231                     DEBUG(("Decoder[%d] Width %d Height %d\n", i,
    232                         decoder[i]->decInfo.picWidth,
    233                         decoder[i]->decInfo.picHeight));
    234 
    235                     DEBUG(("Decoder[%d] videoRange %d, matricCoefficients %d\n",
    236                         i, decoder[i]->decInfo.videoRange,
    237                         decoder[i]->decInfo.matrixCoefficients));
    238                     decoder[i]->decInput.dataLen -=
    239                         (u32)(decoder[i]->decOutput.pStrmCurrPos -
    240                               decoder[i]->decInput.pStream);
    241                     decoder[i]->decInput.pStream =
    242                         decoder[i]->decOutput.pStrmCurrPos;
    243                     break;
    244 
    245                 case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
    246                     decoder[i]->decInput.dataLen -=
    247                         (u32)(decoder[i]->decOutput.pStrmCurrPos -
    248                               decoder[i]->decInput.pStream);
    249                     decoder[i]->decInput.pStream =
    250                         decoder[i]->decOutput.pStrmCurrPos;
    251                     /* fall through */
    252                 case H264SWDEC_PIC_RDY:
    253                     if (ret == H264SWDEC_PIC_RDY)
    254                         decoder[i]->decInput.dataLen = 0;
    255 
    256                     ret = H264SwDecGetInfo(decoder[i]->decInst,
    257                             &(decoder[i]->decInfo));
    258                     if (ret != H264SWDEC_OK)
    259                         exit(1);
    260 
    261                     while (H264SwDecNextPicture(decoder[i]->decInst,
    262                             &(decoder[i]->decPicture), 0) == H264SWDEC_PIC_RDY)
    263                     {
    264                         decoder[i]->picNumber++;
    265 
    266                         numErrors += decoder[i]->decPicture.nbrOfErrMBs;
    267 
    268                         DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
    269                             i, decoder[i]->picNumber,
    270                             decoder[i]->decPicture.isIdrPicture
    271                                 ? "IDR" : "NON-IDR",
    272                             decoder[i]->decPicture.nbrOfErrMBs));
    273                         fflush(stdout);
    274 
    275                         CropWriteOutput(decoder[i]->foutput,
    276                                 (u8*)decoder[i]->decPicture.pOutputPicture,
    277                                 cropDisplay, &(decoder[i]->decInfo));
    278                     }
    279 
    280                     if (maxNumPics && decoder[i]->picNumber == maxNumPics)
    281                         decoder[i]->decInput.dataLen = 0;
    282                     break;
    283 
    284                 case H264SWDEC_STRM_PROCESSED:
    285                 case H264SWDEC_STRM_ERR:
    286                 case H264SWDEC_PARAM_ERR:
    287                     decoder[i]->decInput.dataLen = 0;
    288                     break;
    289 
    290                 default:
    291                     DEBUG(("Decoder[%d] FATAL ERROR\n", i));
    292                     exit(10);
    293                     break;
    294 
    295             }
    296         }
    297 
    298         /* check if any of the instances is still running (=has more data) */
    299         instRunning = instCount;
    300         for (i = 0; i < instCount; i++)
    301         {
    302             if (decoder[i]->decInput.dataLen == 0)
    303                 instRunning--;
    304         }
    305 
    306     } while (instRunning);
    307 
    308 
    309     /* get last frames and close each instance */
    310     for (i = 0; i < instCount; i++)
    311     {
    312         while (H264SwDecNextPicture(decoder[i]->decInst,
    313                 &(decoder[i]->decPicture), 1) == H264SWDEC_PIC_RDY)
    314         {
    315             decoder[i]->picNumber++;
    316 
    317             DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
    318                 i, decoder[i]->picNumber,
    319                 decoder[i]->decPicture.isIdrPicture
    320                     ? "IDR" : "NON-IDR",
    321                 decoder[i]->decPicture.nbrOfErrMBs));
    322             fflush(stdout);
    323 
    324             CropWriteOutput(decoder[i]->foutput,
    325                     (u8*)decoder[i]->decPicture.pOutputPicture,
    326                     cropDisplay, &(decoder[i]->decInfo));
    327         }
    328 
    329         H264SwDecRelease(decoder[i]->decInst);
    330 
    331         if (decoder[i]->foutput)
    332             fclose(decoder[i]->foutput);
    333 
    334         free(decoder[i]->byteStrmStart);
    335 
    336         free(decoder[i]);
    337     }
    338 
    339     free(decoder);
    340 
    341     if (numErrors)
    342         return 1;
    343     else
    344         return 0;
    345 
    346 }
    347 
    348 /*------------------------------------------------------------------------------
    349 
    350 ------------------------------------------------------------------------------*/
    351 void CropWriteOutput(FILE *foutput, u8 *imageData, u32 cropDisplay,
    352         H264SwDecInfo *decInfo)
    353 {
    354     u8 *tmpImage = NULL;
    355     u32 tmp, picSize;
    356 
    357     if (cropDisplay && decInfo->croppingFlag)
    358     {
    359         picSize = decInfo->cropParams.cropOutWidth *
    360                   decInfo->cropParams.cropOutHeight;
    361         picSize = (3 * picSize)/2;
    362         tmpImage = malloc(picSize);
    363         if (tmpImage == NULL)
    364             exit(1);
    365         tmp = CropPicture(tmpImage, imageData,
    366             decInfo->picWidth, decInfo->picHeight,
    367             &(decInfo->cropParams));
    368         if (tmp)
    369             exit(1);
    370         WriteOutput(foutput, tmpImage, picSize);
    371         free(tmpImage);
    372     }
    373     else
    374     {
    375         picSize = decInfo->picWidth * decInfo->picHeight;
    376         picSize = (3 * picSize)/2;
    377         WriteOutput(foutput, imageData, picSize);
    378     }
    379 
    380 }
    381 
    382 /*------------------------------------------------------------------------------
    383 
    384 ------------------------------------------------------------------------------*/
    385 void WriteOutput(FILE *fid, u8 *data, u32 picSize)
    386 {
    387     if (fid)
    388         fwrite(data, 1, picSize, fid);
    389 }
    390 
    391 /*------------------------------------------------------------------------------
    392 
    393     Function name:  H264SwDecTrace
    394 
    395 ------------------------------------------------------------------------------*/
    396 void H264SwDecTrace(char *string)
    397 {
    398     FILE *fp;
    399 
    400     fp = fopen("dec_api.trc", "at");
    401 
    402     if (!fp)
    403         return;
    404 
    405     fwrite(string, 1, strlen(string), fp);
    406     fwrite("\n", 1,1, fp);
    407 
    408     fclose(fp);
    409 }
    410 
    411 /*------------------------------------------------------------------------------
    412 
    413     Function name:  H264SwDecmalloc
    414 
    415 ------------------------------------------------------------------------------*/
    416 void* H264SwDecMalloc(u32 size)
    417 {
    418     return malloc(size);
    419 }
    420 
    421 /*------------------------------------------------------------------------------
    422 
    423     Function name:  H264SwDecFree
    424 
    425 ------------------------------------------------------------------------------*/
    426 void H264SwDecFree(void *ptr)
    427 {
    428     free(ptr);
    429 }
    430 
    431 /*------------------------------------------------------------------------------
    432 
    433     Function name:  H264SwDecMemcpy
    434 
    435 ------------------------------------------------------------------------------*/
    436 void H264SwDecMemcpy(void *dest, void *src, u32 count)
    437 {
    438     memcpy(dest, src, count);
    439 }
    440 
    441 /*------------------------------------------------------------------------------
    442 
    443     Function name:  H264SwDecMemset
    444 
    445 ------------------------------------------------------------------------------*/
    446 void H264SwDecMemset(void *ptr, i32 value, u32 count)
    447 {
    448     memset(ptr, value, count);
    449 }
    450 
    451 /*------------------------------------------------------------------------------
    452 
    453     Function name: CropPicture
    454 
    455 ------------------------------------------------------------------------------*/
    456 u32 CropPicture(u8 *pOutImage, u8 *pInImage,
    457     u32 picWidth, u32 picHeight, CropParams *pCropParams)
    458 {
    459 
    460     u32 i, j;
    461     u32 outWidth, outHeight;
    462     u8 *pOut, *pIn;
    463 
    464     if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL ||
    465         !picWidth || !picHeight)
    466     {
    467         /* due to lint warning */
    468         free(pOutImage);
    469         return(1);
    470     }
    471 
    472     if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) >
    473            picWidth ) ||
    474          ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) >
    475            picHeight ) )
    476     {
    477         /* due to lint warning */
    478         free(pOutImage);
    479         return(1);
    480     }
    481 
    482     outWidth = pCropParams->cropOutWidth;
    483     outHeight = pCropParams->cropOutHeight;
    484 
    485     pIn = pInImage + pCropParams->cropTopOffset*picWidth +
    486         pCropParams->cropLeftOffset;
    487     pOut = pOutImage;
    488 
    489     /* luma */
    490     for (i = outHeight; i; i--)
    491     {
    492         for (j = outWidth; j; j--)
    493         {
    494             *pOut++ = *pIn++;
    495         }
    496         pIn += picWidth - outWidth;
    497     }
    498 
    499     outWidth >>= 1;
    500     outHeight >>= 1;
    501 
    502     pIn = pInImage + picWidth*picHeight +
    503         pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
    504 
    505     /* cb */
    506     for (i = outHeight; i; i--)
    507     {
    508         for (j = outWidth; j; j--)
    509         {
    510             *pOut++ = *pIn++;
    511         }
    512         pIn += picWidth/2 - outWidth;
    513     }
    514 
    515     pIn = pInImage + 5*picWidth*picHeight/4 +
    516         pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
    517 
    518     /* cr */
    519     for (i = outHeight; i; i--)
    520     {
    521         for (j = outWidth; j; j--)
    522         {
    523             *pOut++ = *pIn++;
    524         }
    525         pIn += picWidth/2 - outWidth;
    526     }
    527 
    528     return (0);
    529 
    530 }
    531 
    532