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, u32 num) 302 { 303 if (size > UINT32_MAX / num) { 304 return NULL; 305 } 306 return malloc(size * num); 307 } 308 309 /*------------------------------------------------------------------------------ 310 311 Function name: H264SwDecFree 312 313 Purpose: 314 Example implementation of H264SwDecFree function. Prototype of this 315 function is given in H264SwDecApi.h. This implementation uses 316 library function free for freeing of memory. 317 318 ------------------------------------------------------------------------------*/ 319 void H264SwDecFree(void *ptr) 320 { 321 free(ptr); 322 } 323 324 /*------------------------------------------------------------------------------ 325 326 Function name: H264SwDecMemcpy 327 328 Purpose: 329 Example implementation of H264SwDecMemcpy function. Prototype of this 330 function is given in H264SwDecApi.h. This implementation uses 331 library function memcpy to copy src to dest. 332 333 ------------------------------------------------------------------------------*/ 334 void H264SwDecMemcpy(void *dest, void *src, u32 count) 335 { 336 memcpy(dest, src, count); 337 } 338 339 /*------------------------------------------------------------------------------ 340 341 Function name: H264SwDecMemset 342 343 Purpose: 344 Example implementation of H264SwDecMemset function. Prototype of this 345 function is given in H264SwDecApi.h. This implementation uses 346 library function memset to set content of memory area pointed by ptr. 347 348 ------------------------------------------------------------------------------*/ 349 void H264SwDecMemset(void *ptr, i32 value, u32 count) 350 { 351 memset(ptr, value, count); 352 } 353 354