1 /*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Ramprasad <x0038811@ti.com>
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"
27 #define MAX_IO_BUFS 8
28 /* Used for mpeg4 esds data copy */
30 /* omap drm device handle */
31 struct omap_device *dev = NULL;
33 struct decoder {
34 struct display *disp;
35 struct buffer *framebuf;
36 Engine_Handle engine;
37 VIDDEC2_Handle codec;
38 VIDDEC2_Params *params;
39 VIDDEC2_DynamicParams *dynParams;
40 VIDDEC2_Status *status;
41 XDM1_BufDesc *inBufs;
42 XDM_BufDesc *outBufs;
43 VIDDEC2_InArgs *inArgs;
44 VIDDEC2_OutArgs *outArgs;
45 XDAS_Int8 **outBuffer;
46 XDAS_Int32 *outBufSizes;
47 char *input;
48 struct omap_bo *input_bo;
49 int input_sz, uv_offset;
50 int padded_width;
51 int padded_height;
52 int num_outBuf;
54 };
56 static void
57 usage(char *name)
58 {
59 MSG("Usage: %s -s <connector_id>:<mode> INFILE -w width -h height", name);
60 MSG("example: %s -s 4:800x480 file.yuv -w 176 -h 144", name);
61 MSG("Test of universalCopy .");
62 MSG("");
63 MSG("yuvcopytest options:");
64 MSG("\t --help: Print this help and exit.");
65 MSG("");
66 disp_usage();
67 }
69 static void
70 decoder_close(struct decoder *decoder)
71 {
72 if(!decoder) goto bailout;
73 /* free output buffers allocated by display */
74 disp_free_buffers(decoder->disp,decoder->num_outBuf);
76 if (decoder->params) dsp_dce_free(decoder->params);
77 if (decoder->dynParams) dsp_dce_free(decoder->dynParams);
78 if (decoder->status) dsp_dce_free(decoder->status);
79 if (decoder->inBufs)
80 {
81 dsp_dce_buf_unlock(1, &(decoder->inBufs->descs[0].buf));
82 close(decoder->inBufs->descs[0].buf);
83 dsp_dce_free(decoder->inBufs);
84 }
85 if (decoder->outBufs) dsp_dce_free(decoder->outBufs);
86 if (decoder->inArgs) dsp_dce_free(decoder->inArgs);
87 if (decoder->outArgs) dsp_dce_free(decoder->outArgs);
88 if (decoder->outBuffer) dsp_dce_free(decoder->outBuffer);
89 if (decoder->outBufSizes) dsp_dce_free(decoder->outBufSizes);
90 if (decoder->input_bo) omap_bo_del(decoder->input_bo);
91 if (decoder->codec) VIDDEC2_delete(decoder->codec);
92 if (decoder->engine) Engine_close(decoder->engine);
93 if (decoder->disp) disp_close(decoder->disp);
94 free(decoder);
95 bailout:
96 if (dev) dce_deinit(dev);
98 }
100 static struct decoder *
101 decoder_open(int argc, char** argv)
102 {
103 struct decoder *decoder;
104 char *infile = NULL;
105 int i;
106 int width , height ,padded_width, padded_height;
107 Engine_Error ec;
108 XDAS_Int32 err;
110 decoder = calloc(1, sizeof(*decoder));
111 if (!decoder)
112 return NULL;
114 MSG("%p: Opening Display..", decoder);
115 decoder->disp = disp_open(argc, argv);
116 if (!decoder->disp)
117 goto usage;
119 /* loop thru args, find input file.. */
120 for (i = 1; i < argc; i++) {
121 int fd;
122 if (!argv[i]) {
123 continue;
124 }
125 fd = open(argv[i], 0);
126 if (fd > 0) {
127 infile = argv[i];
128 argv[i] = NULL;
129 close(fd);
130 break;
131 }
132 break;
133 }
134 for(i = 1; i < argc; i++){
135 if(!argv[i])
136 continue;
138 if(!strcmp(argv[i],"-w")){
139 argv[i] = NULL;
140 width = atoi(argv[i+1]);
141 argv[i+1] = NULL;
142 continue;
143 }
144 if(!strcmp(argv[i], "-h")){
145 argv[i] = NULL;
146 height = atoi(argv[i+1]);
147 argv[i+1] = NULL;
148 }
149 }
151 MSG("width = %d, height = %d\n", width, height);
152 if (check_args(argc, argv) || !infile)
153 goto usage;
155 /* calculate output buffer parameters: */
156 width = ALIGN2 (width, 4); /* round up to macroblocks */
157 height = ALIGN2 (height, 4); /* round up to macroblocks */
159 padded_width = width;
160 padded_height= height;
162 decoder->num_outBuf = 2;
163 decoder->padded_width = padded_width;
164 decoder->padded_height = padded_height;
166 decoder->input_sz = width * height;
167 decoder->input_bo = omap_bo_new(decoder->disp->dev,
168 decoder->input_sz, OMAP_BO_WC);
169 decoder->input = omap_bo_map(decoder->input_bo);
170 decoder->framebuf = disp_get_fb(decoder->disp);
172 MSG("Fill input buffer with yuv luma data\n");
173 {
174 FILE *fd;
175 fd = fopen(infile, "rb");
176 fread(decoder->input, width*height, sizeof(char), fd);
177 fclose(fd);
178 }
180 if (! disp_get_vid_buffers(decoder->disp, decoder->num_outBuf,
181 FOURCC_STR("NV12"), padded_width, padded_height)) {
182 ERROR("%p: could not allocate buffers", decoder);
183 goto fail;
184 }
186 MSG("%p: Opening Engine..", decoder);
187 dce_set_fd(decoder->disp->fd);
188 dev = dce_init();
189 if(dev == NULL) {
190 ERROR("%p: dce init failed", dev);
191 goto fail;
192 }
193 decoder->engine = Engine_open("dsp_vidsvr", NULL, &ec);
194 if (!decoder->engine) {
195 ERROR("%p: could not open engine", decoder);
196 goto fail;
197 }
199 decoder->params = dsp_dce_alloc(sizeof(IVIDDEC2_Params));
200 decoder->params->size = sizeof(IVIDDEC2_Params);
202 decoder->codec = VIDDEC2_create(decoder->engine,
203 "dsp_universalCopy", decoder->params);
204 if (!decoder->codec) {
205 ERROR("%p: could not create codec", decoder);
206 goto fail;
207 }
209 decoder->dynParams = dsp_dce_alloc(sizeof(IVIDDEC2_DynamicParams));
210 decoder->dynParams->size = sizeof(IVIDDEC2_DynamicParams);
212 decoder->status = dsp_dce_alloc(sizeof(IVIDDEC2_Status));
213 decoder->status->size = sizeof(IVIDDEC2_Status);
215 err = VIDDEC2_control(decoder->codec, XDM_SETPARAMS,
216 decoder->dynParams, decoder->status);
217 if (err) {
218 ERROR("%p: fail: %d", decoder, err);
219 goto fail;
220 }
222 /* not entirely sure why we need to call this here.. just copying omx.. */
223 err = VIDDEC2_control(decoder->codec, XDM_GETBUFINFO,
224 decoder->dynParams, decoder->status);
225 if (err) {
226 ERROR("%p: fail: %d", decoder, err);
227 goto fail;
228 }
230 decoder->outBuffer = dsp_dce_alloc(sizeof(XDAS_Int8*) * MAX_IO_BUFS);
231 decoder->outBufSizes = dsp_dce_alloc(sizeof(XDAS_Int32)* MAX_IO_BUFS);
233 decoder->inBufs = dsp_dce_alloc(sizeof(XDM1_BufDesc));
234 decoder->inBufs->numBufs = 1;
235 decoder->inBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_dmabuf(decoder->input_bo);
236 decoder->inBufs->descs[0].bufSize = omap_bo_size(decoder->input_bo);
237 dsp_dce_buf_lock(1, &(decoder->inBufs->descs[0].buf));
239 decoder->outBufs = dsp_dce_alloc(sizeof(XDM_BufDesc));
240 decoder->outBufs->numBufs = 2;
241 decoder->outBufs->bufs = (XDAS_Int8**)decoder->outBuffer;
242 decoder->outBufs->bufSizes = &decoder->outBufSizes[0];
244 decoder->inArgs = dsp_dce_alloc(sizeof(IVIDDEC2_InArgs));
245 decoder->inArgs->size = sizeof(IVIDDEC2_InArgs);
247 decoder->outArgs = dsp_dce_alloc(sizeof(IVIDDEC2_OutArgs));
248 decoder->outArgs->size = sizeof(IVIDDEC2_OutArgs);
250 return decoder;
252 usage:
253 usage(argv[0]);
254 fail:
255 if (decoder)
256 decoder_close(decoder);
257 return NULL;
258 }
260 static int
261 decoder_process(struct decoder *decoder)
262 {
263 XDM1_BufDesc *inBufs = decoder->inBufs;
264 XDM_BufDesc *outBufs = decoder->outBufs;
265 VIDDEC2_InArgs *inArgs = decoder->inArgs;
266 VIDDEC2_OutArgs *outArgs = decoder->outArgs;
267 struct buffer *buf;
268 XDAS_Int32 width = decoder->padded_width;
269 XDAS_Int32 height = decoder->padded_height;
270 XDAS_Int32 err;
271 char *src,*dst;
272 XDAS_Int32 i, success = XDAS_TRUE;
274 buf = disp_get_vid_buffer(decoder->disp);
275 if (!buf) {
276 ERROR("%p: fail: out of buffers", decoder);
277 return -1;
278 }
280 decoder->outBuffer[0] = buf->fd[0];
281 decoder->outBuffer[1] = (buf->multiplanar) ? buf->fd[1]:(XDAS_Int8 *)((decoder->outBuffer[0]));
282 dsp_dce_buf_lock(2,&decoder->outBuffer[0]);
284 decoder->outBufSizes[0] = decoder->padded_width * decoder->padded_height;
285 decoder->outBufSizes[1] = decoder->padded_width * (decoder->padded_height/2);
287 err = VIDDEC2_process(decoder->codec, inBufs, outBufs, inArgs, outArgs);
289 if (err) {
290 ERROR("%p: process returned error: %d", decoder, err);
291 return -1;
292 }
293 dsp_dce_buf_unlock(2, &decoder->outBuffer[0]);
295 disp_post_vid_buffer(decoder->disp, buf, 0, 0, width, height);
296 /* Display the output buffer for 10 seconds */
297 sleep(10);
299 disp_put_vid_buffer(decoder->disp, buf);
301 src = (char*)decoder->input;
302 dst = (char*)omap_bo_map(buf->bo[0]);
304 MSG("Comparing output buffer with input buffer\n");
306 for(i = 0; i < decoder->input_sz; i++){
307 if(*src != *dst){
308 MSG("yuvcopytest failed at %d, 0x%x, 0x%x\n", i, *src, *dst);
309 success = XDAS_FALSE;
310 break;
311 }
312 src++;
313 dst++;
314 }
316 if(success ==XDAS_TRUE)
317 MSG("yuvcopytest executed successfully\n");
319 return 0;
320 }
322 int
323 main(int argc, char **argv)
324 {
325 struct decoder *decoder = NULL;
326 int i;
327 for (i = 1; i < argc; i++)
328 if ( !strcmp(argv[i], "--help")) {
329 usage(argv[0]);
330 exit(0);
331 }
332 decoder = decoder_open(argc,argv);
334 if(decoder)
335 decoder_process(decoder);
337 if(decoder)
338 decoder_close(decoder);
340 decoder = NULL;
342 return 0;
343 }