9e0fa0476e9368195039df81d0b58f1cb6f17098
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 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 }
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;
69 MSG("Opening Display..");
70 disp = disp_open(argc, argv);
71 if (!disp) {
72 usage(argv[0]);
73 return 1;
74 }
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 }
92 if (check_args(argc, argv) || !infile) {
93 ERROR("invalid args");
94 goto usage;
95 }
97 MSG("Opening Demuxer..");
98 demux = demux_init(infile, &width, &height);
99 if (!demux) {
100 goto usage;
101 }
103 MSG("infile=%s, width=%d, height=%d", infile, width, height);
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;
112 MSG("padded_width=%d, padded_height=%d, num_buffers=%d",
113 padded_width, padded_height, num_buffers);
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);
119 framebuf = disp_get_fb(disp);
121 if (! disp_get_vid_buffers(disp, num_buffers, FOURCC_STR("NV12"),
122 padded_width, padded_height)) {
123 goto out;
124 }
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 }
134 params = dce_alloc(sizeof(IVIDDEC3_Params));
135 params->size = sizeof(IVIDDEC3_Params);
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;
155 codec = VIDDEC3_create(engine, "ivahd_h264dec", params);
156 if (!codec) {
157 ERROR("fail");
158 goto out;
159 }
161 dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
162 dynParams->size = sizeof(IVIDDEC3_DynamicParams);
164 dynParams->decodeHeader = XDM_DECODE_AU;
166 /*Not Supported: Set default*/
167 dynParams->displayWidth = 0;
168 dynParams->frameSkipMode = IVIDEO_NO_SKIP;
169 dynParams->newFrameFlag = XDAS_TRUE;
171 status = dce_alloc(sizeof(IVIDDEC3_Status));
172 status->size = sizeof(IVIDDEC3_Status);
174 err = VIDDEC3_control(codec, XDM_SETPARAMS, dynParams, status);
175 if (err) {
176 ERROR("fail: %d", err);
177 goto out;
178 }
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 }
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;
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;
197 inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
198 inArgs->size = sizeof(IVIDDEC3_InArgs);
200 outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
201 outArgs->size = sizeof(IVIDDEC3_OutArgs);
203 tdisp = mark(NULL);
205 while (inBufs->numBufs && outBufs->numBufs) {
206 struct buffer *buf;
207 int n;
208 suseconds_t tproc;
210 buf = disp_get_vid_buffer(disp);
211 if (!buf) {
212 ERROR("fail: out of buffers");
213 goto shutdown;
214 }
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 }
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]);
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 }
242 for (i = 0; outArgs->outputID[i]; i++) {
243 /* calculate offset to region of interest */
244 XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion);
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 }
257 for (i = 0; outArgs->freeBufID[i]; i++) {
258 buf = (struct buffer *)outArgs->freeBufID[i];
259 disp_put_vid_buffer(disp, buf);
260 }
262 if (outArgs->outBufsInUseFlag) {
263 MSG("TODO... outBufsInUseFlag"); // XXX
264 }
265 }
267 MSG("Ok!");
268 ret = 0;
270 shutdown:
271 VIDDEC3_delete(codec);
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);
285 return ret;
287 usage:
288 usage(argv[0]);
289 return ret;
290 }