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 /*------------------------------------------------------------------------------
     23     Module defines
     24 ------------------------------------------------------------------------------*/
     25 
     26 /* CHECK_MEMORY_USAGE prints and sums the memory allocated in calls to
     27  * H264SwDecMalloc() */
     28 /* #define CHECK_MEMORY_USAGE */
     29 
     30 /* _NO_OUT disables output file writing */
     31 /* #define _NO_OUT */
     32 
     33 /* Debug prints */
     34 #define DEBUG(argv) printf argv
     35 
     36 /* CVS tag name for identification */
     37 const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $";
     38 
     39 void WriteOutput(char *filename, u8 *data, u32 picSize);
     40 u32 NextPacket(u8 **pStrm);
     41 u32 CropPicture(u8 *pOutImage, u8 *pInImage,
     42     u32 picWidth, u32 picHeight, CropParams *pCropParams);
     43 
     44 /* Global variables for stream handling */
     45 u8 *streamStop = NULL;
     46 u32 packetize = 0;
     47 u32 nalUnitStream = 0;
     48 FILE *foutput = NULL;
     49 
     50 #ifdef SOC_DESIGNER
     51 
     52 // Initialisation function defined in InitCache.s
     53 extern void cache_init(void);
     54 
     55 /*------------------------------------------------------------------------------
     56 
     57     Function name:  $Sub$$main
     58 
     59     Purpose:
     60         This function is called at the end of the C library initialisation and
     61         before main. Its purpose is to do any further initialisation before the
     62         application start.
     63 
     64 ------------------------------------------------------------------------------*/
     65 int $Sub$$main(char argc, char * argv[])
     66 {
     67   cache_init();                    // does some extra setup work setting up caches
     68   return $Super$$main(argc, argv); // calls the original function
     69 }
     70 #endif
     71 
     72 /*------------------------------------------------------------------------------
     73 
     74     Function name:  main
     75 
     76     Purpose:
     77         main function of decoder testbench. Provides command line interface
     78         with file I/O for H.264 decoder. Prints out the usage information
     79         when executed without arguments.
     80 
     81 ------------------------------------------------------------------------------*/
     82 
     83 int main(int argc, char **argv)
     84 {
     85 
     86     u32 i, tmp;
     87     u32 maxNumPics = 0;
     88     u8 *byteStrmStart;
     89     u8 *imageData;
     90     u8 *tmpImage = NULL;
     91     u32 strmLen;
     92     u32 picSize;
     93     H264SwDecInst decInst;
     94     H264SwDecRet ret;
     95     H264SwDecInput decInput;
     96     H264SwDecOutput decOutput;
     97     H264SwDecPicture decPicture;
     98     H264SwDecInfo decInfo;
     99     H264SwDecApiVersion decVer;
    100     u32 picDecodeNumber;
    101     u32 picDisplayNumber;
    102     u32 numErrors = 0;
    103     u32 cropDisplay = 0;
    104     u32 disableOutputReordering = 0;
    105 
    106     FILE *finput;
    107 
    108     char outFileName[256] = "";
    109 
    110     /* Print API version number */
    111     decVer = H264SwDecGetAPIVersion();
    112     DEBUG(("H.264 Decoder API v%d.%d\n", decVer.major, decVer.minor));
    113 
    114     /* Print tag name if '-T' argument present */
    115     if ( argc > 1 && strcmp(argv[1], "-T") == 0 )
    116     {
    117         DEBUG(("%s\n", tagName));
    118         return 0;
    119     }
    120 
    121     /* Check that enough command line arguments given, if not -> print usage
    122      * information out */
    123     if (argc < 2)
    124     {
    125         DEBUG((
    126             "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file.h264\n",
    127             argv[0]));
    128         DEBUG(("\t-Nn forces decoding to stop after n pictures\n"));
    129 #if defined(_NO_OUT)
    130         DEBUG(("\t-Ooutfile output writing disabled at compile time\n"));
    131 #else
    132         DEBUG(("\t-Ooutfile write output to \"outfile\" (default out_wxxxhyyy.yuv)\n"));
    133         DEBUG(("\t-Onone does not write output\n"));
    134 #endif
    135         DEBUG(("\t-P packet-by-packet mode\n"));
    136         DEBUG(("\t-U NAL unit stream mode\n"));
    137         DEBUG(("\t-C display cropped image (default decoded image)\n"));
    138         DEBUG(("\t-R disable DPB output reordering\n"));
    139         DEBUG(("\t-T to print tag name and exit\n"));
    140         return 0;
    141     }
    142 
    143     /* read command line arguments */
    144     for (i = 1; i < (u32)(argc-1); i++)
    145     {
    146         if ( strncmp(argv[i], "-N", 2) == 0 )
    147         {
    148             maxNumPics = (u32)atoi(argv[i]+2);
    149         }
    150         else if ( strncmp(argv[i], "-O", 2) == 0 )
    151         {
    152             strcpy(outFileName, argv[i]+2);
    153         }
    154         else if ( strcmp(argv[i], "-P") == 0 )
    155         {
    156             packetize = 1;
    157         }
    158         else if ( strcmp(argv[i], "-U") == 0 )
    159         {
    160             nalUnitStream = 1;
    161         }
    162         else if ( strcmp(argv[i], "-C") == 0 )
    163         {
    164             cropDisplay = 1;
    165         }
    166         else if ( strcmp(argv[i], "-R") == 0 )
    167         {
    168             disableOutputReordering = 1;
    169         }
    170     }
    171 
    172     /* open input file for reading, file name given by user. If file open
    173      * fails -> exit */
    174     finput = fopen(argv[argc-1],"rb");
    175     if (finput == NULL)
    176     {
    177         DEBUG(("UNABLE TO OPEN INPUT FILE\n"));
    178         return -1;
    179     }
    180 
    181     /* check size of the input file -> length of the stream in bytes */
    182     fseek(finput,0L,SEEK_END);
    183     strmLen = (u32)ftell(finput);
    184     rewind(finput);
    185 
    186     /* allocate memory for stream buffer. if unsuccessful -> exit */
    187     byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen);
    188     if (byteStrmStart == NULL)
    189     {
    190         DEBUG(("UNABLE TO ALLOCATE MEMORY\n"));
    191         return -1;
    192     }
    193 
    194     /* read input stream from file to buffer and close input file */
    195     fread(byteStrmStart, sizeof(u8), strmLen, finput);
    196     fclose(finput);
    197 
    198     /* initialize decoder. If unsuccessful -> exit */
    199     ret = H264SwDecInit(&decInst, disableOutputReordering);
    200     if (ret != H264SWDEC_OK)
    201     {
    202         DEBUG(("DECODER INITIALIZATION FAILED\n"));
    203         free(byteStrmStart);
    204         return -1;
    205     }
    206 
    207     /* initialize H264SwDecDecode() input structure */
    208     streamStop = byteStrmStart + strmLen;
    209     decInput.pStream = byteStrmStart;
    210     decInput.dataLen = strmLen;
    211     decInput.intraConcealmentMethod = 0;
    212 
    213     /* get pointer to next packet and the size of packet
    214      * (for packetize or nalUnitStream modes) */
    215     if ( (tmp = NextPacket(&decInput.pStream)) != 0 )
    216         decInput.dataLen = tmp;
    217 
    218     picDecodeNumber = picDisplayNumber = 1;
    219     /* main decoding loop */
    220     do
    221     {
    222         /* Picture ID is the picture number in decoding order */
    223         decInput.picId = picDecodeNumber;
    224 
    225         /* call API function to perform decoding */
    226         ret = H264SwDecDecode(decInst, &decInput, &decOutput);
    227 
    228         switch(ret)
    229         {
    230 
    231             case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
    232                 /* Stream headers were successfully decoded
    233                  * -> stream information is available for query now */
    234 
    235                 ret = H264SwDecGetInfo(decInst, &decInfo);
    236                 if (ret != H264SWDEC_OK)
    237                     return -1;
    238 
    239                 DEBUG(("Profile %d\n", decInfo.profile));
    240 
    241                 DEBUG(("Width %d Height %d\n",
    242                     decInfo.picWidth, decInfo.picHeight));
    243 
    244                 if (cropDisplay && decInfo.croppingFlag)
    245                 {
    246                     DEBUG(("Cropping params: (%d, %d) %dx%d\n",
    247                         decInfo.cropParams.cropLeftOffset,
    248                         decInfo.cropParams.cropTopOffset,
    249                         decInfo.cropParams.cropOutWidth,
    250                         decInfo.cropParams.cropOutHeight));
    251 
    252                     /* Cropped frame size in planar YUV 4:2:0 */
    253                     picSize = decInfo.cropParams.cropOutWidth *
    254                               decInfo.cropParams.cropOutHeight;
    255                     picSize = (3 * picSize)/2;
    256                     tmpImage = malloc(picSize);
    257                     if (tmpImage == NULL)
    258                         return -1;
    259                 }
    260                 else
    261                 {
    262                     /* Decoder output frame size in planar YUV 4:2:0 */
    263                     picSize = decInfo.picWidth * decInfo.picHeight;
    264                     picSize = (3 * picSize)/2;
    265                 }
    266 
    267                 DEBUG(("videoRange %d, matrixCoefficients %d\n",
    268                     decInfo.videoRange, decInfo.matrixCoefficients));
    269 
    270                 /* update H264SwDecDecode() input structure, number of bytes
    271                  * "consumed" is computed as difference between the new stream
    272                  * pointer and old stream pointer */
    273                 decInput.dataLen -=
    274                     (u32)(decOutput.pStrmCurrPos - decInput.pStream);
    275                 decInput.pStream = decOutput.pStrmCurrPos;
    276 
    277                 /* If -O option not used, generate default file name */
    278                 if (outFileName[0] == 0)
    279                     sprintf(outFileName, "out_w%dh%d.yuv",
    280                             decInfo.picWidth, decInfo.picHeight);
    281                 break;
    282 
    283             case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
    284                 /* Picture is ready and more data remains in input buffer
    285                  * -> update H264SwDecDecode() input structure, number of bytes
    286                  * "consumed" is computed as difference between the new stream
    287                  * pointer and old stream pointer */
    288                 decInput.dataLen -=
    289                     (u32)(decOutput.pStrmCurrPos - decInput.pStream);
    290                 decInput.pStream = decOutput.pStrmCurrPos;
    291                 /* fall through */
    292 
    293             case H264SWDEC_PIC_RDY:
    294 
    295                 /*lint -esym(644,tmpImage,picSize) variable initialized at
    296                  * H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY case */
    297 
    298                 if (ret == H264SWDEC_PIC_RDY)
    299                     decInput.dataLen = NextPacket(&decInput.pStream);
    300 
    301                 /* If enough pictures decoded -> force decoding to end
    302                  * by setting that no more stream is available */
    303                 if (maxNumPics && picDecodeNumber == maxNumPics)
    304                     decInput.dataLen = 0;
    305 
    306                 /* Increment decoding number for every decoded picture */
    307                 picDecodeNumber++;
    308 
    309                 /* use function H264SwDecNextPicture() to obtain next picture
    310                  * in display order. Function is called until no more images
    311                  * are ready for display */
    312                 while ( H264SwDecNextPicture(decInst, &decPicture, 0) ==
    313                         H264SWDEC_PIC_RDY )
    314                 {
    315                     DEBUG(("PIC %d, type %s", picDisplayNumber,
    316                         decPicture.isIdrPicture ? "IDR" : "NON-IDR"));
    317                     if (picDisplayNumber != decPicture.picId)
    318                         DEBUG((", decoded pic %d", decPicture.picId));
    319                     if (decPicture.nbrOfErrMBs)
    320                     {
    321                         DEBUG((", concealed %d\n", decPicture.nbrOfErrMBs));
    322                     }
    323                     else
    324                         DEBUG(("\n"));
    325                     fflush(stdout);
    326 
    327                     numErrors += decPicture.nbrOfErrMBs;
    328 
    329                     /* Increment display number for every displayed picture */
    330                     picDisplayNumber++;
    331 
    332                     /*lint -esym(644,decInfo) always initialized if pictures
    333                      * available for display */
    334 
    335                     /* Write output picture to file */
    336                     imageData = (u8*)decPicture.pOutputPicture;
    337                     if (cropDisplay && decInfo.croppingFlag)
    338                     {
    339                         tmp = CropPicture(tmpImage, imageData,
    340                             decInfo.picWidth, decInfo.picHeight,
    341                             &decInfo.cropParams);
    342                         if (tmp)
    343                             return -1;
    344                         WriteOutput(outFileName, tmpImage, picSize);
    345                     }
    346                     else
    347                     {
    348                         WriteOutput(outFileName, imageData, picSize);
    349                     }
    350                 }
    351 
    352                 break;
    353 
    354             case H264SWDEC_STRM_PROCESSED:
    355             case H264SWDEC_STRM_ERR:
    356                 /* Input stream was decoded but no picture is ready
    357                  * -> Get more data */
    358                 decInput.dataLen = NextPacket(&decInput.pStream);
    359                 break;
    360 
    361             default:
    362                 DEBUG(("FATAL ERROR\n"));
    363                 return -1;
    364 
    365         }
    366     /* keep decoding until all data from input stream buffer consumed */
    367     } while (decInput.dataLen > 0);
    368 
    369     /* if output in display order is preferred, the decoder shall be forced
    370      * to output pictures remaining in decoded picture buffer. Use function
    371      * H264SwDecNextPicture() to obtain next picture in display order. Function
    372      * is called until no more images are ready for display. Second parameter
    373      * for the function is set to '1' to indicate that this is end of the
    374      * stream and all pictures shall be output */
    375     while (H264SwDecNextPicture(decInst, &decPicture, 1) == H264SWDEC_PIC_RDY)
    376     {
    377         DEBUG(("PIC %d, type %s", picDisplayNumber,
    378             decPicture.isIdrPicture ? "IDR" : "NON-IDR"));
    379         if (picDisplayNumber != decPicture.picId)
    380             DEBUG((", decoded pic %d", decPicture.picId));
    381         if (decPicture.nbrOfErrMBs)
    382         {
    383             DEBUG((", concealed %d\n", decPicture.nbrOfErrMBs));
    384         }
    385         else
    386             DEBUG(("\n"));
    387         fflush(stdout);
    388 
    389         numErrors += decPicture.nbrOfErrMBs;
    390 
    391         /* Increment display number for every displayed picture */
    392         picDisplayNumber++;
    393 
    394         /* Write output picture to file */
    395         imageData = (u8*)decPicture.pOutputPicture;
    396         if (cropDisplay && decInfo.croppingFlag)
    397         {
    398             tmp = CropPicture(tmpImage, imageData,
    399                 decInfo.picWidth, decInfo.picHeight,
    400                 &decInfo.cropParams);
    401             if (tmp)
    402                 return -1;
    403             WriteOutput(outFileName, tmpImage, picSize);
    404         }
    405         else
    406         {
    407             WriteOutput(outFileName, imageData, picSize);
    408         }
    409     }
    410 
    411     /* release decoder instance */
    412     H264SwDecRelease(decInst);
    413 
    414     if (foutput)
    415         fclose(foutput);
    416 
    417     /* free allocated buffers */
    418     free(byteStrmStart);
    419     free(tmpImage);
    420 
    421     DEBUG(("Output file: %s\n", outFileName));
    422 
    423     DEBUG(("DECODING DONE\n"));
    424     if (numErrors || picDecodeNumber == 1)
    425     {
    426         DEBUG(("ERRORS FOUND\n"));
    427         return 1;
    428     }
    429 
    430     return 0;
    431 }
    432 
    433 /*------------------------------------------------------------------------------
    434 
    435     Function name:  WriteOutput
    436 
    437     Purpose:
    438         Write picture pointed by data to file. Size of the
    439         picture in pixels is indicated by picSize.
    440 
    441 ------------------------------------------------------------------------------*/
    442 void WriteOutput(char *filename, u8 *data, u32 picSize)
    443 {
    444 
    445     /* foutput is global file pointer */
    446     if (foutput == NULL)
    447     {
    448         /* open output file for writing, can be disabled with define.
    449          * If file open fails -> exit */
    450         if (strcmp(filename, "none") != 0)
    451         {
    452 #if !defined(_NO_OUT)
    453             foutput = fopen(filename, "wb");
    454             if (foutput == NULL)
    455             {
    456                 DEBUG(("UNABLE TO OPEN OUTPUT FILE\n"));
    457                 exit(100);
    458             }
    459 #endif
    460         }
    461     }
    462 
    463     if (foutput && data)
    464         fwrite(data, 1, picSize, foutput);
    465 }
    466 
    467 /*------------------------------------------------------------------------------
    468 
    469     Function name: NextPacket
    470 
    471     Purpose:
    472         Get the pointer to start of next packet in input stream. Uses
    473         global variables 'packetize' and 'nalUnitStream' to determine the
    474         decoder input stream mode and 'streamStop' to determine the end
    475         of stream. There are three possible stream modes:
    476             default - the whole stream at once
    477             packetize - a single NAL-unit with start code prefix
    478             nalUnitStream - a single NAL-unit without start code prefix
    479 
    480         pStrm stores pointer to the start of previous decoder input and is
    481         replaced with pointer to the start of the next decoder input.
    482 
    483         Returns the packet size in bytes
    484 
    485 ------------------------------------------------------------------------------*/
    486 u32 NextPacket(u8 **pStrm)
    487 {
    488 
    489     u32 index;
    490     u32 maxIndex;
    491     u32 zeroCount;
    492     u8 *stream;
    493     u8 byte;
    494     static u32 prevIndex=0;
    495 
    496     /* For default stream mode all the stream is in first packet */
    497     if (!packetize && !nalUnitStream)
    498         return 0;
    499 
    500     index = 0;
    501     stream = *pStrm + prevIndex;
    502     maxIndex = (u32)(streamStop - stream);
    503 
    504     if (maxIndex == 0)
    505         return(0);
    506 
    507     /* leading zeros of first NAL unit */
    508     do
    509     {
    510         byte = stream[index++];
    511     } while (byte != 1 && index < maxIndex);
    512 
    513     /* invalid start code prefix */
    514     if (index == maxIndex || index < 3)
    515     {
    516         DEBUG(("INVALID BYTE STREAM\n"));
    517         exit(100);
    518     }
    519 
    520     /* nalUnitStream is without start code prefix */
    521     if (nalUnitStream)
    522     {
    523         stream += index;
    524         maxIndex -= index;
    525         index = 0;
    526     }
    527 
    528     zeroCount = 0;
    529 
    530     /* Search stream for next start code prefix */
    531     /*lint -e(716) while(1) used consciously */
    532     while (1)
    533     {
    534         byte = stream[index++];
    535         if (!byte)
    536             zeroCount++;
    537 
    538         if ( (byte == 0x01) && (zeroCount >= 2) )
    539         {
    540             /* Start code prefix has two zeros
    541              * Third zero is assumed to be leading zero of next packet
    542              * Fourth and more zeros are assumed to be trailing zeros of this
    543              * packet */
    544             if (zeroCount > 3)
    545             {
    546                 index -= 4;
    547                 zeroCount -= 3;
    548             }
    549             else
    550             {
    551                 index -= zeroCount+1;
    552                 zeroCount = 0;
    553             }
    554             break;
    555         }
    556         else if (byte)
    557             zeroCount = 0;
    558 
    559         if (index == maxIndex)
    560         {
    561             break;
    562         }
    563 
    564     }
    565 
    566     /* Store pointer to the beginning of the packet */
    567     *pStrm = stream;
    568     prevIndex = index;
    569 
    570     /* nalUnitStream is without trailing zeros */
    571     if (nalUnitStream)
    572         index -= zeroCount;
    573 
    574     return(index);
    575 
    576 }
    577 
    578 /*------------------------------------------------------------------------------
    579 
    580     Function name: CropPicture
    581 
    582     Purpose:
    583         Perform cropping for picture. Input picture pInImage with dimensions
    584         picWidth x picHeight is cropped with pCropParams and the resulting
    585         picture is stored in pOutImage.
    586 
    587 ------------------------------------------------------------------------------*/
    588 u32 CropPicture(u8 *pOutImage, u8 *pInImage,
    589     u32 picWidth, u32 picHeight, CropParams *pCropParams)
    590 {
    591 
    592     u32 i, j;
    593     u32 outWidth, outHeight;
    594     u8 *pOut, *pIn;
    595 
    596     if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL ||
    597         !picWidth || !picHeight)
    598     {
    599         /* just to prevent lint warning, returning non-zero will result in
    600          * return without freeing the memory */
    601         free(pOutImage);
    602         return(1);
    603     }
    604 
    605     if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) >
    606            picWidth ) ||
    607          ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) >
    608            picHeight ) )
    609     {
    610         /* just to prevent lint warning, returning non-zero will result in
    611          * return without freeing the memory */
    612         free(pOutImage);
    613         return(1);
    614     }
    615 
    616     outWidth = pCropParams->cropOutWidth;
    617     outHeight = pCropParams->cropOutHeight;
    618 
    619     /* Calculate starting pointer for luma */
    620     pIn = pInImage + pCropParams->cropTopOffset*picWidth +
    621         pCropParams->cropLeftOffset;
    622     pOut = pOutImage;
    623 
    624     /* Copy luma pixel values */
    625     for (i = outHeight; i; i--)
    626     {
    627         for (j = outWidth; j; j--)
    628         {
    629             *pOut++ = *pIn++;
    630         }
    631         pIn += picWidth - outWidth;
    632     }
    633 
    634     outWidth >>= 1;
    635     outHeight >>= 1;
    636 
    637     /* Calculate starting pointer for cb */
    638     pIn = pInImage + picWidth*picHeight +
    639         pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
    640 
    641     /* Copy cb pixel values */
    642     for (i = outHeight; i; i--)
    643     {
    644         for (j = outWidth; j; j--)
    645         {
    646             *pOut++ = *pIn++;
    647         }
    648         pIn += picWidth/2 - outWidth;
    649     }
    650 
    651     /* Calculate starting pointer for cr */
    652     pIn = pInImage + 5*picWidth*picHeight/4 +
    653         pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
    654 
    655     /* Copy cr pixel values */
    656     for (i = outHeight; i; i--)
    657     {
    658         for (j = outWidth; j; j--)
    659         {
    660             *pOut++ = *pIn++;
    661         }
    662         pIn += picWidth/2 - outWidth;
    663     }
    664 
    665     return (0);
    666 }
    667 
    668 /*------------------------------------------------------------------------------
    669 
    670     Function name:  H264SwDecTrace
    671 
    672     Purpose:
    673         Example implementation of H264SwDecTrace function. Prototype of this
    674         function is given in H264SwDecApi.h. This implementation appends
    675         trace messages to file named 'dec_api.trc'.
    676 
    677 ------------------------------------------------------------------------------*/
    678 void H264SwDecTrace(char *string)
    679 {
    680     FILE *fp;
    681 
    682     fp = fopen("dec_api.trc", "at");
    683 
    684     if (!fp)
    685         return;
    686 
    687     fwrite(string, 1, strlen(string), fp);
    688     fwrite("\n", 1,1, fp);
    689 
    690     fclose(fp);
    691 }
    692 
    693 /*------------------------------------------------------------------------------
    694 
    695     Function name:  H264SwDecMalloc
    696 
    697     Purpose:
    698         Example implementation of H264SwDecMalloc function. Prototype of this
    699         function is given in H264SwDecApi.h. This implementation uses
    700         library function malloc for allocation of memory.
    701 
    702 ------------------------------------------------------------------------------*/
    703 void* H264SwDecMalloc(u32 size, u32 num)
    704 {
    705     if (size > UINT32_MAX / num) {
    706         return NULL;
    707     }
    708 
    709 #if defined(CHECK_MEMORY_USAGE)
    710     /* Note that if the decoder has to free and reallocate some of the buffers
    711      * the total value will be invalid */
    712     static u32 numBytes = 0;
    713     numBytes += size * num;
    714     DEBUG(("Allocated %d bytes, total %d\n", size, numBytes));
    715 #endif
    716 
    717     return malloc(size * num);
    718 }
    719 
    720 /*------------------------------------------------------------------------------
    721 
    722     Function name:  H264SwDecFree
    723 
    724     Purpose:
    725         Example implementation of H264SwDecFree function. Prototype of this
    726         function is given in H264SwDecApi.h. This implementation uses
    727         library function free for freeing of memory.
    728 
    729 ------------------------------------------------------------------------------*/
    730 void H264SwDecFree(void *ptr)
    731 {
    732     free(ptr);
    733 }
    734 
    735 /*------------------------------------------------------------------------------
    736 
    737     Function name:  H264SwDecMemcpy
    738 
    739     Purpose:
    740         Example implementation of H264SwDecMemcpy function. Prototype of this
    741         function is given in H264SwDecApi.h. This implementation uses
    742         library function memcpy to copy src to dest.
    743 
    744 ------------------------------------------------------------------------------*/
    745 void H264SwDecMemcpy(void *dest, void *src, u32 count)
    746 {
    747     memcpy(dest, src, count);
    748 }
    749 
    750 /*------------------------------------------------------------------------------
    751 
    752     Function name:  H264SwDecMemset
    753 
    754     Purpose:
    755         Example implementation of H264SwDecMemset function. Prototype of this
    756         function is given in H264SwDecApi.h. This implementation uses
    757         library function memset to set content of memory area pointed by ptr.
    758 
    759 ------------------------------------------------------------------------------*/
    760 void H264SwDecMemset(void *ptr, i32 value, u32 count)
    761 {
    762     memset(ptr, value, count);
    763 }
    764 
    765