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
22void 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------------------------------------------------------------------------------*/
38int 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
204end:
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------------------------------------------------------------------------------*/
261void 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------------------------------------------------------------------------------*/
276void 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------------------------------------------------------------------------------*/
301void* 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------------------------------------------------------------------------------*/
319void 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------------------------------------------------------------------------------*/
334void 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------------------------------------------------------------------------------*/
349void H264SwDecMemset(void *ptr, i32 value, u32 count)
350{
351    memset(ptr, value, count);
352}
353
354