viddec: support for multiple decoder instances
[glsdk/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  */
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
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>
28 #include "util.h"
29 #include "demux.h"
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
36 struct decoder {
37         struct display *disp;
38         struct demux *demux;
39         struct buffer *framebuf;
41         Engine_Handle engine;
42         VIDDEC3_Handle codec;
43         VIDDEC3_Params *params;
44         VIDDEC3_DynamicParams *dynParams;
45         VIDDEC3_Status *status;
46         XDM2_BufDesc *inBufs;
47         XDM2_BufDesc *outBufs;
48         VIDDEC3_InArgs *inArgs;
49         VIDDEC3_OutArgs *outArgs;
51         char *input;
52         struct omap_bo *input_bo;
53         int input_sz;
55         suseconds_t tdisp;
57 };
59 static void
60 usage(char *name)
61 {
62         MSG("Usage: %s [OPTIONS] INFILE", name);
63         MSG("Test of viddec3 decoder.");
64         MSG("");
65         disp_usage();
66 }
68 static void
69 decoder_close(struct decoder *decoder)
70 {
71         if (decoder->codec)          VIDDEC3_delete(decoder->codec);
72         if (decoder->engine)         Engine_close(decoder->engine);
73         if (decoder->params)         dce_free(decoder->params);
74         if (decoder->dynParams)      dce_free(decoder->dynParams);
75         if (decoder->status)         dce_free(decoder->status);
76         if (decoder->inBufs)         free(decoder->inBufs);
77         if (decoder->outBufs)        free(decoder->outBufs);
78         if (decoder->inArgs)         dce_free(decoder->inArgs);
79         if (decoder->outArgs)        dce_free(decoder->outArgs);
80         if (decoder->input_bo)       omap_bo_del(decoder->input_bo);
81         if (decoder->demux)          demux_deinit(decoder->demux);
83         free(decoder);
84 }
86 static struct decoder *
87 decoder_open(int argc, char **argv)
88 {
89         struct decoder *decoder;
90         char *infile = NULL;
91         int i, num_buffers;
92         int width, height, padded_width, padded_height;
93         Engine_Error ec;
94         XDAS_Int32 err;
96         decoder = calloc(1, sizeof(*decoder));
97         if (!decoder)
98                 return NULL;
100         MSG("%p: Opening Display..", decoder);
101         decoder->disp = disp_open(argc, argv);
102         if (!decoder->disp)
103                 goto usage;
105         /* loop thru args, find input file.. */
106         for (i = 1; i < argc; i++) {
107                 int fd;
108                 if (!argv[i]) {
109                         continue;
110                 }
111                 fd = open(argv[i], 0);
112                 if (fd > 0) {
113                         infile = argv[i];
114                         argv[i] = NULL;
115                         close(fd);
116                         break;
117                 }
118                 break;
119         }
121         if (check_args(argc, argv) || !infile)
122                 goto usage;
124         MSG("%p: Opening Demuxer..", decoder);
125         decoder->demux = demux_init(infile, &width, &height);
126         if (!decoder->demux) {
127                 ERROR("%p: could not open demuxer", decoder);
128                 goto fail;
129         }
131         MSG("%p: infile=%s, width=%d, height=%d", decoder, infile, width, height);
133         /* calculate output buffer parameters: */
134         width  = ALIGN2 (width, 4);        /* round up to macroblocks */
135         height = ALIGN2 (height, 4);       /* round up to macroblocks */
136         padded_width  = ALIGN2 (width + (2*PADX), 7);
137         padded_height = height + 4*PADY;
138         num_buffers   = MIN(16, 32768 / ((width/16) * (height/16))) + 3;
140         MSG("%p: padded_width=%d, padded_height=%d, num_buffers=%d",
141                         decoder, padded_width, padded_height, num_buffers);
143         decoder->input_sz = width * height;
144         decoder->input_bo = omap_bo_new(decoder->disp->dev,
145                         decoder->input_sz, OMAP_BO_WC);
146         decoder->input = omap_bo_map(decoder->input_bo);
148         decoder->framebuf = disp_get_fb(decoder->disp);
150         if (! disp_get_vid_buffers(decoder->disp, num_buffers,
151                         FOURCC_STR("NV12"), padded_width, padded_height)) {
152                 ERROR("%p: could not allocate buffers", decoder);
153                 goto fail;
154         }
156         MSG("%p: Opening Engine..", decoder);
157         dce_set_fd(decoder->disp->fd);
158         decoder->engine = Engine_open("ivahd_vidsvr", NULL, &ec);
159         if (!decoder->engine) {
160                 ERROR("%p: could not open engine", decoder);
161                 goto fail;
162         }
164         decoder->params = dce_alloc(sizeof(IVIDDEC3_Params));
165         decoder->params->size = sizeof(IVIDDEC3_Params);
167         decoder->params->maxWidth         = width;
168         decoder->params->maxHeight        = height;
169         decoder->params->maxFrameRate     = 30000;
170         decoder->params->maxBitRate       = 10000000;
171         decoder->params->dataEndianness   = XDM_BYTE;
172         decoder->params->forceChromaFormat= XDM_YUV_420SP;
173         decoder->params->operatingMode    = IVIDEO_DECODE_ONLY;
174         decoder->params->displayDelay     = IVIDDEC3_DISPLAY_DELAY_AUTO;
175         decoder->params->displayBufsMode  = IVIDDEC3_DISPLAYBUFS_EMBEDDED;
176 MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
177         decoder->params->inputDataMode    = IVIDEO_ENTIREFRAME;
178         decoder->params->metadataType[0]  = IVIDEO_METADATAPLANE_NONE;
179         decoder->params->metadataType[1]  = IVIDEO_METADATAPLANE_NONE;
180         decoder->params->metadataType[2]  = IVIDEO_METADATAPLANE_NONE;
181         decoder->params->numInputDataUnits= 0;
182         decoder->params->outputDataMode   = IVIDEO_ENTIREFRAME;
183         decoder->params->numOutputDataUnits = 0;
184         decoder->params->errorInfoMode    = IVIDEO_ERRORINFO_OFF;
186         decoder->codec = VIDDEC3_create(decoder->engine,
187                         "ivahd_h264dec", decoder->params);
188         if (!decoder->codec) {
189                 ERROR("%p: could not create codec", decoder);
190                 goto fail;
191         }
193         decoder->dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
194         decoder->dynParams->size = sizeof(IVIDDEC3_DynamicParams);
196         decoder->dynParams->decodeHeader  = XDM_DECODE_AU;
198         /*Not Supported: Set default*/
199         decoder->dynParams->displayWidth  = 0;
200         decoder->dynParams->frameSkipMode = IVIDEO_NO_SKIP;
201         decoder->dynParams->newFrameFlag  = XDAS_TRUE;
203         decoder->status = dce_alloc(sizeof(IVIDDEC3_Status));
204         decoder->status->size = sizeof(IVIDDEC3_Status);
206         err = VIDDEC3_control(decoder->codec, XDM_SETPARAMS,
207                         decoder->dynParams, decoder->status);
208         if (err) {
209                 ERROR("%p: fail: %d", decoder, err);
210                 goto fail;
211         }
213         /* not entirely sure why we need to call this here.. just copying omx.. */
214         err = VIDDEC3_control(decoder->codec, XDM_GETBUFINFO,
215                         decoder->dynParams, decoder->status);
216         if (err) {
217                 ERROR("%p: fail: %d", decoder, err);
218                 goto fail;
219         }
221         decoder->inBufs = malloc(sizeof(XDM2_BufDesc));
222         decoder->inBufs->numBufs = 1;
223         decoder->inBufs->descs[0].buf =
224                         (XDAS_Int8 *)omap_bo_handle(decoder->input_bo);
225         decoder->inBufs->descs[0].memType = XDM_MEMTYPE_BO;
227         decoder->outBufs = malloc(sizeof(XDM2_BufDesc));
228         decoder->outBufs->numBufs = 2;
229         decoder->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
230         decoder->outBufs->descs[1].memType = XDM_MEMTYPE_BO;
232         decoder->inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
233         decoder->inArgs->size = sizeof(IVIDDEC3_InArgs);
235         decoder->outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
236         decoder->outArgs->size = sizeof(IVIDDEC3_OutArgs);
238         decoder->tdisp = mark(NULL);
240         return decoder;
242 usage:
243         usage(argv[0]);
244 fail:
245         if (decoder)
246                 decoder_close(decoder);
247         return NULL;
250 static int
251 decoder_process(struct decoder *decoder)
253         XDM2_BufDesc *inBufs = decoder->inBufs;
254         XDM2_BufDesc *outBufs = decoder->outBufs;
255         VIDDEC3_InArgs *inArgs = decoder->inArgs;
256         VIDDEC3_OutArgs *outArgs = decoder->outArgs;
257         XDAS_Int32 err;
258         struct buffer *buf;
259         int i, n;
260         suseconds_t tproc;
262         buf = disp_get_vid_buffer(decoder->disp);
263         if (!buf) {
264                 ERROR("%p: fail: out of buffers", decoder);
265                 return -1;
266         }
268         n = demux_read(decoder->demux, decoder->input, decoder->input_sz);
269         if (n) {
270                 inBufs->descs[0].bufSize.bytes = n;
271                 inArgs->numBytes = n;
272                 MSG("%p: push: %d bytes (%p)", decoder, n, buf);
273         } else {
274                 /* end of input.. do we need to flush? */
275                 MSG("%p: end of input", decoder);
276                 inBufs->numBufs = 0;
277                 inArgs->inputID = 0;
278         }
280         inArgs->inputID = (XDAS_Int32)buf;
281         outBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[0]);
282         outBufs->descs[1].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[1]);
284         tproc = mark(NULL);
285         err = VIDDEC3_process(decoder->codec, inBufs, outBufs, inArgs, outArgs);
286         MSG("%p: processed returned in: %ldus", decoder, (long int)mark(&tproc));
287         if (err) {
288                 ERROR("%p: process returned error: %d", decoder, err);
289                 ERROR("%p: extendedError: %08x", decoder, outArgs->extendedError);
290                 if (XDM_ISFATALERROR(outArgs->extendedError))
291                         return -1;
292         }
294         for (i = 0; outArgs->outputID[i]; i++) {
295                 /* calculate offset to region of interest */
296                 XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion);
298                 /* get the output buffer and write it to file */
299                 buf = (struct buffer *)outArgs->outputID[i];
300                 MSG("%p: post buffer: %p %d,%d %d,%d", decoder, buf,
301                                 r->topLeft.x, r->topLeft.y,
302                                 r->bottomRight.x, r->bottomRight.y);
303                 disp_post_vid_buffer(decoder->disp, buf,
304                                 r->topLeft.x, r->topLeft.y,
305                                 r->bottomRight.x - r->topLeft.x,
306                                 r->bottomRight.y - r->topLeft.y);
307                 MSG("%p: display in: %ldus", decoder, (long int)mark(&decoder->tdisp));
308         }
310         for (i = 0; outArgs->freeBufID[i]; i++) {
311                 buf = (struct buffer *)outArgs->freeBufID[i];
312                 disp_put_vid_buffer(decoder->disp, buf);
313         }
315         if (outArgs->outBufsInUseFlag) {
316                 MSG("%p: TODO... outBufsInUseFlag", decoder); // XXX
317         }
319         return (inBufs->numBufs > 0) ? 0 : -1;
322 int
323 main(int argc, char **argv)
325         struct decoder *decoders[8] = {};
326         int i, n, first = 0, ndecoders = 0;
328         for (i = 1; i < argc; i++) {
329                 if (!strcmp(argv[i], "--")) {
330                         argv[first] = argv[0];
331                         decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
332                         first = i;
333                 }
334         }
336         argv[first] = argv[0];
337         decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
339         do {
340                 for (i = 0, n = 0; i < ndecoders; i++) {
341                         if (decoders[i]) {
342                                 int ret = decoder_process(decoders[i]);
343                                 if (ret) {
344                                         decoder_close(decoders[i]);
345                                         decoders[i] = NULL;
346                                         continue;
347                                 }
348                                 n++;
349                         }
350                 }
351         } while(n > 0);
353         return 0;