viddec3test: add profiling for render times
[gstreamer-omap:omapdrmtest.git] / viddec3test.c
1 /*
2  * Copyright (C) 2012 Texas Instruments
3  * Author: Rob Clark <rob.clark@linaro.org>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21
22 #include <dce.h>
23 #include <xdc/std.h>
24 #include <ti/xdais/xdas.h>
25 #include <ti/sdo/ce/Engine.h>
26 #include <ti/sdo/ce/video3/viddec3.h>
27
28 #include "util.h"
29 #include "demux.h"
30
31 /* Padding for width as per Codec Requirement (for h264) */
32 #define PADX  32
33 /* Padding for height as per Codec requirement (for h264)*/
34 #define PADY  24
35
36 static void
37 usage(char *name)
38 {
39         MSG("Usage: %s [OPTIONS] INFILE", name);
40         MSG("Test of viddec3 decoder.");
41         MSG("");
42         disp_usage();
43 }
44
45 int
46 main(int argc, char **argv)
47 {
48         struct display *disp;
49         struct demux *demux;
50         struct buffer *framebuf;
51         char *infile = NULL;
52         char *input = NULL;
53         struct omap_bo *input_bo = NULL;
54         int ret = 1, i, input_sz, num_buffers;
55         int width, height, padded_width, padded_height;
56         Engine_Error ec;
57         XDAS_Int32 err;
58         Engine_Handle engine;
59         VIDDEC3_Handle codec;
60         VIDDEC3_Params *params;
61         VIDDEC3_DynamicParams *dynParams;
62         VIDDEC3_Status *status;
63         XDM2_BufDesc *inBufs;
64         XDM2_BufDesc *outBufs;
65         VIDDEC3_InArgs *inArgs;
66         VIDDEC3_OutArgs *outArgs;
67         suseconds_t tdisp;
68
69         MSG("Opening Display..");
70         disp = disp_open(argc, argv);
71         if (!disp) {
72                 usage(argv[0]);
73                 return 1;
74         }
75
76         /* loop thru args, find input file.. */
77         for (i = 1; i < argc; i++) {
78                 int fd;
79                 if (!argv[i]) {
80                         continue;
81                 }
82                 fd = open(argv[i], 0);
83                 if (fd > 0) {
84                         infile = argv[i];
85                         argv[i] = NULL;
86                         close(fd);
87                         break;
88                 }
89                 break;
90         }
91
92         if (check_args(argc, argv) || !infile) {
93                 ERROR("invalid args");
94                 goto usage;
95         }
96
97         MSG("Opening Demuxer..");
98         demux = demux_init(infile, &width, &height);
99         if (!demux) {
100                 goto usage;
101         }
102
103         MSG("infile=%s, width=%d, height=%d", infile, width, height);
104
105         /* calculate output buffer parameters: */
106         width  = ALIGN2 (width, 4);        /* round up to macroblocks */
107         height = ALIGN2 (height, 4);       /* round up to macroblocks */
108         padded_width  = ALIGN2 (width + (2*PADX), 7);
109         padded_height = height + 4*PADY;
110         num_buffers   = MIN(16, 32768 / ((width/16) * (height/16))) + 3;
111
112         MSG("padded_width=%d, padded_height=%d, num_buffers=%d",
113                         padded_width, padded_height, num_buffers);
114
115         input_sz = width * height;
116         input_bo = omap_bo_new(disp->dev, input_sz, OMAP_BO_WC);
117         input = omap_bo_map(input_bo);
118
119         framebuf = disp_get_fb(disp);
120
121         if (! disp_get_vid_buffers(disp, num_buffers, FOURCC_STR("NV12"),
122                         padded_width, padded_height)) {
123                 goto out;
124         }
125
126         MSG("Opening Engine..");
127         dce_set_fd(disp->fd);
128         engine = Engine_open("ivahd_vidsvr", NULL, &ec);
129         if (!engine) {
130                 ERROR("fail");
131                 goto out;
132         }
133
134         params = dce_alloc(sizeof(IVIDDEC3_Params));
135         params->size = sizeof(IVIDDEC3_Params);
136
137         params->maxWidth         = width;
138         params->maxHeight        = height;
139         params->maxFrameRate     = 30000;
140         params->maxBitRate       = 10000000;
141         params->dataEndianness   = XDM_BYTE;
142         params->forceChromaFormat= XDM_YUV_420SP;
143         params->operatingMode    = IVIDEO_DECODE_ONLY;
144         params->displayDelay     = IVIDDEC3_DISPLAY_DELAY_AUTO;
145         params->displayBufsMode  = IVIDDEC3_DISPLAYBUFS_EMBEDDED;
146         params->inputDataMode    = IVIDEO_ENTIREFRAME;
147         params->metadataType[0]  = IVIDEO_METADATAPLANE_NONE;
148         params->metadataType[1]  = IVIDEO_METADATAPLANE_NONE;
149         params->metadataType[2]  = IVIDEO_METADATAPLANE_NONE;
150         params->numInputDataUnits= 0;
151         params->outputDataMode   = IVIDEO_ENTIREFRAME;
152         params->numOutputDataUnits = 0;
153         params->errorInfoMode    = IVIDEO_ERRORINFO_OFF;
154
155         codec = VIDDEC3_create(engine, "ivahd_h264dec", params);
156         if (!codec) {
157                 ERROR("fail");
158                 goto out;
159         }
160
161         dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
162         dynParams->size = sizeof(IVIDDEC3_DynamicParams);
163
164         dynParams->decodeHeader  = XDM_DECODE_AU;
165
166         /*Not Supported: Set default*/
167         dynParams->displayWidth  = 0;
168         dynParams->frameSkipMode = IVIDEO_NO_SKIP;
169         dynParams->newFrameFlag  = XDAS_TRUE;
170
171         status = dce_alloc(sizeof(IVIDDEC3_Status));
172         status->size = sizeof(IVIDDEC3_Status);
173
174         err = VIDDEC3_control(codec, XDM_SETPARAMS, dynParams, status);
175         if (err) {
176                 ERROR("fail: %d", err);
177                 goto out;
178         }
179
180         /* not entirely sure why we need to call this here.. just copying omx.. */
181         err = VIDDEC3_control(codec, XDM_GETBUFINFO, dynParams, status);
182         if (err) {
183                 ERROR("fail: %d", err);
184                 goto out;
185         }
186
187         inBufs = malloc(sizeof(XDM2_BufDesc));
188         inBufs->numBufs = 1;
189         inBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_handle(input_bo);
190         inBufs->descs[0].memType = XDM_MEMTYPE_BO;
191
192         outBufs = malloc(sizeof(XDM2_BufDesc));
193         outBufs->numBufs = 2;
194         outBufs->descs[0].memType = XDM_MEMTYPE_BO;
195         outBufs->descs[1].memType = XDM_MEMTYPE_BO;
196
197         inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
198         inArgs->size = sizeof(IVIDDEC3_InArgs);
199
200         outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
201         outArgs->size = sizeof(IVIDDEC3_OutArgs);
202
203         tdisp = mark(NULL);
204
205         while (inBufs->numBufs && outBufs->numBufs) {
206                 struct buffer *buf;
207                 int n;
208                 suseconds_t tproc;
209
210                 buf = disp_get_vid_buffer(disp);
211                 if (!buf) {
212                         ERROR("fail: out of buffers");
213                         goto shutdown;
214                 }
215
216                 n = demux_read(demux, input, input_sz);
217                 if (n) {
218                         inBufs->descs[0].bufSize.bytes = n;
219                         inArgs->numBytes = n;
220                         MSG("push: %d bytes (%p)", n, buf);
221                 } else {
222                         /* end of input.. do we need to flush? */
223                         MSG("end of input");
224                         inBufs->numBufs = 0;
225                         inArgs->inputID = 0;
226                 }
227
228                 inArgs->inputID = (XDAS_Int32)buf;
229                 outBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[0]);
230                 outBufs->descs[1].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[1]);
231
232                 tproc = mark(NULL);
233                 err = VIDDEC3_process(codec, inBufs, outBufs, inArgs, outArgs);
234                 MSG("processed returned in: %ldus", (long int)mark(&tproc));
235                 if (err) {
236                         ERROR("process returned error: %d", err);
237                         ERROR("extendedError: %08x", outArgs->extendedError);
238                         if (XDM_ISFATALERROR(outArgs->extendedError))
239                                 goto shutdown;
240                 }
241
242                 for (i = 0; outArgs->outputID[i]; i++) {
243                         /* calculate offset to region of interest */
244                         XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion);
245
246                         /* get the output buffer and write it to file */
247                         buf = (struct buffer *)outArgs->outputID[i];
248                         MSG("post buffer: %p %d,%d %d,%d", buf,
249                                         r->topLeft.x, r->topLeft.y,
250                                         r->bottomRight.x, r->bottomRight.y);
251                         disp_post_vid_buffer(disp, buf, r->topLeft.x, r->topLeft.y,
252                                         r->bottomRight.x - r->topLeft.x,
253                                         r->bottomRight.y - r->topLeft.y);
254                         MSG("display in: %ldus", (long int)mark(&tdisp));
255                 }
256
257                 for (i = 0; outArgs->freeBufID[i]; i++) {
258                         buf = (struct buffer *)outArgs->freeBufID[i];
259                         disp_put_vid_buffer(disp, buf);
260                 }
261
262                 if (outArgs->outBufsInUseFlag) {
263                         MSG("TODO... outBufsInUseFlag"); // XXX
264                 }
265         }
266
267         MSG("Ok!");
268         ret = 0;
269
270 shutdown:
271         VIDDEC3_delete(codec);
272
273 out:
274         if (engine)         Engine_close(engine);
275         if (params)         dce_free(params);
276         if (dynParams)      dce_free(dynParams);
277         if (status)         dce_free(status);
278         if (inBufs)         free(inBufs);
279         if (outBufs)        free(outBufs);
280         if (inArgs)         dce_free(inArgs);
281         if (outArgs)        dce_free(outArgs);
282         if (input_bo)       omap_bo_del(input_bo);
283         if (demux)          demux_deinit(demux);
284
285         return ret;
286
287 usage:
288         usage(argv[0]);
289         return ret;
290 }