]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/omapdrmtest.git/blob - viddec3test.c
Revert "dual display fix"
[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  */
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <libdce.h>
21 #include <xf86drm.h>
22 #include <omap_drm.h>
23 #include <omap_drmif.h>
25 #include "util.h"
26 #include "demux.h"
28 /* Used for mpeg4 esds data copy */
29 int first_in_buff = 0;
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 /* omap drm device handle */
36 struct omap_device *dev = NULL;
38 struct decoder {
39         struct display *disp;
40         struct demux *demux;
41         struct buffer *framebuf;
42         Engine_Handle engine;
43         VIDDEC3_Handle codec;
44         VIDDEC3_Params *params;
45         VIDDEC3_DynamicParams *dynParams;
46         VIDDEC3_Status *status;
47         XDM2_BufDesc *inBufs;
48         XDM2_BufDesc *outBufs;
49         VIDDEC3_InArgs *inArgs;
50         VIDDEC3_OutArgs *outArgs;
51         char *input;
52         struct omap_bo *input_bo;
53         int input_sz, uv_offset;
54         int padded_width;
55         int padded_height;
56         int num_outBuf;
57         size_t *outBuf_fd;
58         suseconds_t tdisp;
59 };
61 /* When true, do not actually call VIDDEC3_process. For benchmarking. */
62 static int no_process = 0;
64 /* When true, loop at end of playback. */
65 static int loop = 0;
67 static void
68 usage(char *name)
69 {
70         MSG("Usage: %s [OPTIONS] INFILE", name);
71         MSG("Test of viddec3 decoder.");
72         MSG("");
73         MSG("viddec3test options:");
74         MSG("\t-h, --help: Print this help and exit.");
75         MSG("\t--loop\tRestart playback at end of stream.");
76         MSG("\t--no-process\tDo not actually call VIDDEC3_process method. For benchmarking.");
77         MSG("");
78         disp_usage();
79 }
81 static void
82 decoder_close(struct decoder *decoder)
83 {
84         int i;
85         /* fix me: all the output buffers are not unlocked in process.So calling unlock
86          * for all the buffers */
87         for(i=0;i<decoder->num_outBuf;i++){
88                 dce_buf_unlock(1,&decoder->disp->buf[i]->fd[0]);
89                 if(decoder->disp->multiplanar)
90                         dce_buf_unlock(1,&decoder->disp->buf[i]->fd[1]);
91         }
92         /* free output buffers allocated by display */
93         disp_free_buffers(decoder->disp,decoder->num_outBuf);
95         if (decoder->codec)          VIDDEC3_delete(decoder->codec);
96         if (decoder->engine)         Engine_close(decoder->engine);
97         if (dev)                     dce_deinit(dev);
98         if (decoder->params)         dce_free(decoder->params);
99         if (decoder->dynParams)      dce_free(decoder->dynParams);
100         if (decoder->status)         dce_free(decoder->status);
101         if (decoder->inBufs)         dce_free(decoder->inBufs);
102         if (decoder->outBufs)        dce_free(decoder->outBufs);
103         if (decoder->inArgs)         dce_free(decoder->inArgs);
104         if (decoder->outArgs)        dce_free(decoder->outArgs);
105         if (decoder->input_bo)       omap_bo_del(decoder->input_bo);
106         if (decoder->demux)          demux_deinit(decoder->demux);
107         if (decoder->disp)           disp_close(decoder->disp);
108         if (decoder->outBuf_fd)      free(decoder->outBuf_fd);
109         free(decoder);
112 static struct decoder *
113 decoder_open(int argc, char **argv)
115         struct decoder *decoder;
116         char *infile = NULL;
117         int i;
118         int width, height, padded_width, padded_height;
119         Engine_Error ec;
120         XDAS_Int32 err;
122         decoder = calloc(1, sizeof(*decoder));
123         if (!decoder)
124                 return NULL;
126         MSG("%p: Opening Display..", decoder);
127         decoder->disp = disp_open(argc, argv);
128         if (!decoder->disp)
129                 goto usage;
131         /* loop thru args, find input file.. */
132         for (i = 1; i < argc; i++) {
133                 int fd;
134                 if (!argv[i]) {
135                         continue;
136                 }
137                 fd = open(argv[i], 0);
138                 if (fd > 0) {
139                         infile = argv[i];
140                         argv[i] = NULL;
141                         close(fd);
142                         break;
143                 }
144                 break;
145         }
147         if (check_args(argc, argv) || !infile)
148                 goto usage;
150         MSG("%p: Opening Demuxer..", decoder);
151         decoder->demux = demux_init(infile, &width, &height);
152         if (!decoder->demux) {
153                 ERROR("%p: could not open demuxer", decoder);
154                 goto fail;
155         }
157         MSG("%p: infile=%s, width=%d, height=%d", decoder, infile, width, height);
159         /* calculate output buffer parameters: */
160         width  = ALIGN2 (width, 4);        /* round up to macroblocks */
161         height = ALIGN2 (height, 4);       /* round up to macroblocks */
163        if (decoder->demux->cc->codec_id == CODEC_ID_MPEG2VIDEO) {
164                 padded_width = width;
165                 padded_height= height;
166         }
167         else {
168                 padded_width  = ALIGN2 (width + (2*PADX), 7);
169                 padded_height = height + 4*PADY;
170         }
172         decoder->num_outBuf   = MIN(16, 32768 / ((width/16) * (height/16))) + 3;
173         decoder->padded_width = padded_width;
174         decoder->padded_height = padded_height;
175         MSG("%p: padded_width=%d, padded_height=%d, num_buffers=%d",
176                         decoder, padded_width, padded_height, decoder->num_outBuf);
178         if (!decoder->disp->multiplanar) {
179                 decoder->uv_offset = padded_width * padded_height;
180                 decoder->outBuf_fd = malloc(sizeof(int)*decoder->num_outBuf);
181                 MSG("%p: uv_offset=%d", decoder, decoder->uv_offset);
182         }
183         else{
184                 decoder->outBuf_fd = malloc(sizeof(int)*(decoder->num_outBuf*2));
185         }
187         decoder->input_sz = width * height;
188         decoder->input_bo = omap_bo_new(decoder->disp->dev,
189                         decoder->input_sz, OMAP_BO_WC);
190         decoder->input = omap_bo_map(decoder->input_bo);
191         decoder->framebuf = disp_get_fb(decoder->disp);
193         if (! disp_get_vid_buffers(decoder->disp, decoder->num_outBuf,
194                         FOURCC_STR("NV12"), padded_width, padded_height)) {
195                 ERROR("%p: could not allocate buffers", decoder);
196                 goto fail;
197         }
199         MSG("%p: Opening Engine..", decoder);
200         dce_set_fd(decoder->disp->fd);
201         dev = dce_init();
202         if(dev == NULL) {
203                 ERROR("%p: dce init failed", dev);
204                 goto fail;
205         }
206         decoder->engine = Engine_open("ivahd_vidsvr", NULL, &ec);
207         if (!decoder->engine) {
208                 ERROR("%p: could not open engine", decoder);
209                 goto fail;
210         }
212         decoder->params = dce_alloc(sizeof(IVIDDEC3_Params));
213         decoder->params->size = sizeof(IVIDDEC3_Params);
215         decoder->params->maxWidth         = width;
216         decoder->params->maxHeight        = height;
217         decoder->params->maxFrameRate     = 30000;
218         decoder->params->maxBitRate       = 10000000;
219         decoder->params->dataEndianness   = XDM_BYTE;
220         decoder->params->forceChromaFormat= XDM_YUV_420SP;
221         decoder->params->operatingMode    = IVIDEO_DECODE_ONLY;
222         decoder->params->displayDelay     = IVIDDEC3_DISPLAY_DELAY_AUTO;
223         decoder->params->displayBufsMode  = IVIDDEC3_DISPLAYBUFS_EMBEDDED;
224         MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
225         decoder->params->inputDataMode    = IVIDEO_ENTIREFRAME;
226         decoder->params->metadataType[0]  = IVIDEO_METADATAPLANE_NONE;
227         decoder->params->metadataType[1]  = IVIDEO_METADATAPLANE_NONE;
228         decoder->params->metadataType[2]  = IVIDEO_METADATAPLANE_NONE;
229         decoder->params->numInputDataUnits= 0;
230         decoder->params->outputDataMode   = IVIDEO_ENTIREFRAME;
231         decoder->params->numOutputDataUnits = 0;
232         decoder->params->errorInfoMode    = IVIDEO_ERRORINFO_OFF;
234         if (decoder->demux->cc->codec_id == CODEC_ID_MPEG2VIDEO) {
235             decoder->codec = VIDDEC3_create(decoder->engine,
236                                         "ivahd_mpeg2vdec", decoder->params);
237         }
238         else if (decoder->demux->cc->codec_id == CODEC_ID_H264) {
239             decoder->codec = VIDDEC3_create(decoder->engine,
240                                         "ivahd_h264dec", decoder->params);
241         }
242         else if (decoder->demux->cc->codec_id == CODEC_ID_MPEG4) {
243                 first_in_buff = 1;
244                 decoder->codec = VIDDEC3_create(decoder->engine,
245                                         "ivahd_mpeg4dec", decoder->params);
246         }
248         if (!decoder->codec) {
249                 ERROR("%p: could not create codec", decoder);
250                 goto fail;
251         }
253         decoder->dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
254         decoder->dynParams->size = sizeof(IVIDDEC3_DynamicParams);
256         decoder->dynParams->decodeHeader  = XDM_DECODE_AU;
258         /*Not Supported: Set default*/
259         decoder->dynParams->displayWidth  = 0;
260         decoder->dynParams->frameSkipMode = IVIDEO_NO_SKIP;
261         decoder->dynParams->newFrameFlag  = XDAS_TRUE;
263         decoder->status = dce_alloc(sizeof(IVIDDEC3_Status));
264         decoder->status->size = sizeof(IVIDDEC3_Status);
266         err = VIDDEC3_control(decoder->codec, XDM_SETPARAMS,
267                         decoder->dynParams, decoder->status);
268         if (err) {
269                 ERROR("%p: fail: %d", decoder, err);
270                 goto fail;
271         }
273         /* not entirely sure why we need to call this here.. just copying omx.. */
274         err = VIDDEC3_control(decoder->codec, XDM_GETBUFINFO,
275                         decoder->dynParams, decoder->status);
276         if (err) {
277                 ERROR("%p: fail: %d", decoder, err);
278                 goto fail;
279         }
281         decoder->inBufs = dce_alloc(sizeof(XDM2_BufDesc));
282         decoder->inBufs->numBufs = 1;
283         decoder->inBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_dmabuf(decoder->input_bo);
284         decoder->inBufs->descs[0].bufSize.bytes = omap_bo_size(decoder->input_bo);
285         decoder->inBufs->descs[0].memType = XDM_MEMTYPE_RAW;
288         decoder->outBufs = dce_alloc(sizeof(XDM2_BufDesc));
289         decoder->outBufs->numBufs = 2;
290         decoder->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
291         decoder->outBufs->descs[1].memType = XDM_MEMTYPE_RAW;
293         decoder->inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
294         decoder->inArgs->size = sizeof(IVIDDEC3_InArgs);
296         decoder->outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
297         decoder->outArgs->size = sizeof(IVIDDEC3_OutArgs);
299         decoder->tdisp = mark(NULL);
301         return decoder;
303 usage:
304         usage(argv[0]);
305 fail:
306         if (decoder)
307                 decoder_close(decoder);
308         return NULL;
311 static int
312 decoder_process(struct decoder *decoder)
314         XDM2_BufDesc *inBufs = decoder->inBufs;
315         XDM2_BufDesc *outBufs = decoder->outBufs;
316         VIDDEC3_InArgs *inArgs = decoder->inArgs;
317         VIDDEC3_OutArgs *outArgs = decoder->outArgs;
318         struct buffer *buf;
319         int freeBufCount =0;
320         int i, n;
322         buf = disp_get_vid_buffer(decoder->disp);
323         if (!buf) {
324                 ERROR("%p: fail: out of buffers", decoder);
325                 return -1;
326         }
328         /* demux; in loop mode, we can do two tries at the end of the stream. */
329         for (i = 0; i < 2; i++) {
330                 n = demux_read(decoder->demux, decoder->input, decoder->input_sz);
331                 if (n) {
333                         inBufs->descs[0].bufSize.bytes = n;
334                         inArgs->numBytes = n;
335                         DBG("%p: push: %d bytes (%p)", decoder, n, buf);
336                 } else {
337                         /* end of input.. do we need to flush? */
338                         MSG("%p: end of input", decoder);
340                         /* In loop mode: rewind and retry once. */
341                         if (loop && i == 0) {
342                                 int err = demux_rewind(decoder->demux);
343                                 if (err < 0) {
344                                         ERROR("%p: demux_rewind returned error: %d", decoder, err);
345                                         return -1;
346                                 }
347                                 MSG("%p: rewound.", decoder);
348                                 continue;
349                         }
350                         inBufs->numBufs = 0;
351                         inArgs->inputID = 0;
352                         inArgs->numBytes =0;
354                 }
355                 break;
356         }
359         inArgs->inputID = (XDAS_Int32)buf;
360         outBufs->descs[0].buf = buf->fd[0];
361         outBufs->descs[1].buf = (buf->multiplanar) ?buf->fd[1]:(XDAS_Int8 *)((outBufs->descs[0].buf));
364         if(buf->multiplanar){
365                 decoder->outBuf_fd[0] = buf->fd[0];
366                 decoder->outBuf_fd[1] = buf->fd[1];
367                 dce_buf_lock(2,decoder->outBuf_fd);
368         }
369         else{
370                 decoder->outBuf_fd[0] = buf->fd[0];
371                 dce_buf_lock(1,decoder->outBuf_fd);
372         }
373         decoder->outBufs->descs[0].bufSize.bytes =decoder->padded_width*decoder->padded_height;
374         decoder->outBufs->descs[1].bufSize.bytes = decoder->padded_width* (decoder->padded_height/2);
377         if (no_process) {
378                 /* Do not process. This is for benchmarking. We need to "fake"
379                  * the outArgs. */
380                 outArgs->outputID[0] = buf;
381                 outArgs->outputID[1] = NULL;
382                 outArgs->freeBufID[0] = buf;
383                 outArgs->freeBufID[1] = NULL;
384                 outArgs->outBufsInUseFlag = 0;
386         } else {
387                 XDAS_Int32 err;
388                 suseconds_t tproc;
389                 tproc = mark(NULL);
390                 err = VIDDEC3_process(decoder->codec, inBufs, outBufs, inArgs, outArgs);
391                 DBG("%p: processed returned in: %ldus", decoder, (long int)mark(&tproc));
392                 if (err) {
393                         ERROR("%p: process returned error: %d", decoder, err);
394                         ERROR("%p: extendedError: %08x", decoder, outArgs->extendedError);
395                         if (XDM_ISFATALERROR(outArgs->extendedError))
396                                 return -1;
397                 }
398         }
400         for (i = 0; outArgs->outputID[i]; i++) {
401                 /* calculate offset to region of interest */
402                 XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion);
404                 /* get the output buffer and write it to file */
405                 buf = (struct buffer *)outArgs->outputID[i];
406                 disp_post_vid_buffer(decoder->disp, buf,
407                                 r->topLeft.x, r->topLeft.y,
408                                 r->bottomRight.x - r->topLeft.x,
409                                 r->bottomRight.y - r->topLeft.y);
410         }
412         for (i = 0; outArgs->freeBufID[i]; i++) {
413                 buf = (struct buffer *)outArgs->freeBufID[i];
414                 disp_put_vid_buffer(decoder->disp, buf);
416                 if(buf->multiplanar){
417                         decoder->outBuf_fd[freeBufCount++] = buf->fd[0];
418                         decoder->outBuf_fd[freeBufCount++] = buf->fd[1];
419                 }
420                 else{
421                         decoder->outBuf_fd[freeBufCount++] = buf->fd[0];
422                 }
423         }
425         if(freeBufCount){
426                 dce_buf_unlock(freeBufCount,decoder->outBuf_fd);
427                 freeBufCount =0;
428         }
429         if (outArgs->outBufsInUseFlag) {
430                 MSG("%p: TODO... outBufsInUseFlag", decoder); // XXX
431         }
433         return (inBufs->numBufs > 0) ? 0 : -1;
436 int
437 main(int argc, char **argv)
439         struct decoder *decoders[8] = {};
440         int i, n, first = 0, ndecoders = 0;
442         for (i = 1; i < argc; i++) {
443                 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
444                         usage(argv[0]);
445                         exit(0);
447                 } else if (!strcmp(argv[i], "--loop")) {
448                         loop = 1;
449                         argv[i] = NULL;
451                 } else if (!strcmp(argv[i], "--no-process")) {
452                         no_process = 1;
453                         argv[i] = NULL;
455                 } else if (!strcmp(argv[i], "--")) {
456                         argv[first] = argv[0];
457                         decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
458                         first = i;
459                 }
460         }
462         argv[first] = argv[0];
463         decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
465         do {
466                 for (i = 0, n = 0; i < ndecoders; i++) {
467                         if (decoders[i]) {
468                                 int ret = decoder_process(decoders[i]);
469                                 if (ret) {
470                                         decoder_close(decoders[i]);
471                                         decoders[i] = NULL;
472                                         continue;
473                                 }
474                                 n++;
475                         }
476                 }
477         } while(n > 0);
479         return 0;