util: vpe: vpe specific common functions
[glsdk/omapdrmtest.git] / util / vpe-common.c
1 /*
2  *  Copyright (c) 2013-2014, Texas Instruments Incorporated
3  *  Author: alaganraj <alaganraj.s@ti.com>
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *  *  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *
12  *  *  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  *  *  Neither the name of Texas Instruments Incorporated nor the names of
17  *     its contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *  Contact information for paper mail:
33  *  Texas Instruments
34  *  Post Office Box 655303
35  *  Dallas, Texas 75265
36  *  Contact information:
37  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
38  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
39  *  ============================================================================
40  *
41  */
43 /*
44  * @File        vpe-common.c
45  * @Brief       vpe specific common functions, used to integrate vpe 
46  *              with other modules.
47  *
48  *              Input buffer must be allocated in application, queue it to vpe 
49  *              by passing buffer index
50  *              
51  *              Output buffer allocated in vpe_output_init() as vpe output intended
52  *              to display on LCD.
53  */
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <fcntl.h>
57 #include <unistd.h>
58 #include <stdint.h>
59 #include <string.h>
60 #include <errno.h>
62 #include <linux/videodev2.h>
63 #include <linux/v4l2-controls.h>
65 #include <sys/mman.h>
66 #include <sys/ioctl.h>
68 #include <xf86drm.h>
69 #include <omap_drm.h>
70 #include <omap_drmif.h>
72 #include "util.h"
74 #define pexit(fmt, arg...) { \
75                 printf(fmt, ## arg); \
76                 exit(1); \
77 }
79 #define V4L2_CID_TRANS_NUM_BUFS         (V4L2_CID_PRIVATE_BASE)
80 #define NUMBUF                          6
82 //#define vpe_debug
84 #ifdef vpe_debug
85 #define dprintf(fmt, arg...) printf(fmt, ## arg)
86 #else
87 #define dprintf(fmt, arg...) do {} while(0)
88 #endif
90 struct image_params {
91         int width;
92         int height;
93         int fourcc;
94         int size;
95         int size_uv;
96         int coplanar;
97         enum v4l2_colorspace colorspace;
98         int numbuf;
99 };
101 struct vpe {
102         int fd;
103         int field;
104         int deint;
105         int translen;
106         struct image_params src;
107         struct image_params dst;
108         struct  v4l2_crop crop;
109         int input_buf_dmafd[NUMBUF];
110         int input_buf_dmafd_uv[NUMBUF];
111         int output_buf_dmafd[NUMBUF];
112         struct display *disp;
113         struct buffer **disp_bufs;
114 };
116 /**
117  *****************************************************************************
118  * @brief:  open the device
119  *
120  * @return: vpe  struct vpe pointer 
121  *****************************************************************************
122 */
123 struct vpe *vpe_open(void)
125         char devname[20] = "/dev/video0";
126         struct vpe *vpe;
128         vpe = calloc(1, sizeof(*vpe));
130         vpe->fd =  open(devname, O_RDWR);
131         if(vpe->fd < 0)
132                 pexit("Cant open %s\n", devname);
134         printf("vpe:%s open success!!!\n", devname);
136         return vpe;
139 /**
140  *****************************************************************************
141  * @brief:  close the device and free memory
142  *
143  * @param:  vpe  struct vpe pointer
144  *
145  * @return: 0 on success 
146  *****************************************************************************
147 */
148 int vpe_close(struct vpe *vpe)
150         close(vpe->fd);
151         free(vpe);
152         
153         return 0;
156 /**
157  *****************************************************************************
158  * @brief:  fills 4cc, size, coplanar, colorspace based on command line input 
159  *
160  * @param:  format  char pointer
161  * @param:  image  struct image_params pointer
162  *
163  * @return: 0 on success 
164  *****************************************************************************
165 */
166 int describeFormat (char *format, struct image_params *image)
168         image->size   = -1;
169         image->fourcc = -1;
170         if (strcmp (format, "rgb24") == 0) {
171                 image->fourcc = V4L2_PIX_FMT_RGB24;
172                 image->size = image->height * image->width * 3;
173                 image->coplanar = 0;
174                 image->colorspace = V4L2_COLORSPACE_SRGB;
176         } else if (strcmp (format, "bgr24") == 0) {
177                 image->fourcc = V4L2_PIX_FMT_BGR24;
178                 image->size = image->height * image->width * 3;
179                 image->coplanar = 0;
180                 image->colorspace = V4L2_COLORSPACE_SRGB;
182         } else if (strcmp (format, "argb32") == 0) {
183                 image->fourcc = V4L2_PIX_FMT_RGB32;
184                 image->size = image->height * image->width * 4;
185                 image->coplanar = 0;
186                 image->colorspace = V4L2_COLORSPACE_SRGB;
188         } else if (strcmp (format, "abgr32") == 0) {
189                 image->fourcc = V4L2_PIX_FMT_BGR32;
190                 image->size = image->height * image->width * 4;
191                 image->coplanar = 0;
192                 image->colorspace = V4L2_COLORSPACE_SRGB;
194         } else if (strcmp (format, "yuv444") == 0) {
195                 image->fourcc = V4L2_PIX_FMT_YUV444;
196                 image->size = image->height * image->width * 3;
197                 image->coplanar = 0;
198                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
200         } else if (strcmp (format, "yvyu") == 0) {
201                 image->fourcc = V4L2_PIX_FMT_YVYU;
202                 image->size = image->height * image->width * 2;
203                 image->coplanar = 0;
204                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
206         } else if (strcmp (format, "yuyv") == 0) {
207                 image->fourcc = V4L2_PIX_FMT_YUYV;
208                 image->size = image->height * image->width * 2;
209                 image->coplanar = 0;
210                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
212         } else if (strcmp (format, "uyvy") == 0) {
213                 image->fourcc = V4L2_PIX_FMT_UYVY;
214                 image->size = image->height * image->width * 2;
215                 image->coplanar = 0;
216                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
218         } else if (strcmp (format, "vyuy") == 0) {
219                 image->fourcc = V4L2_PIX_FMT_VYUY;
220                 image->size = image->height * image->width * 2;
221                 image->coplanar = 0;
222                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
224         } else if (strcmp (format, "nv16") == 0) {
225                 image->fourcc = V4L2_PIX_FMT_NV16;
226                 image->size = image->height * image->width * 2;
227                 image->coplanar = 0;
228                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
230         } else if (strcmp (format, "nv61") == 0) {
231                 image->fourcc = V4L2_PIX_FMT_NV61;
232                 image->size = image->height * image->width * 2;
233                 image->coplanar = 0;
234                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
236         } else if (strcmp (format, "nv12") == 0) {
237                 image->fourcc = V4L2_PIX_FMT_NV12;
238                 image->size = image->height * image->width * 1.5;
239                 image->coplanar = 1;
240                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
242         } else if (strcmp (format, "nv21") == 0) {
243                 image->fourcc = V4L2_PIX_FMT_NV21;
244                 image->size = image->height * image->width * 1.5;
245                 image->coplanar = 1;
246                 image->colorspace = V4L2_COLORSPACE_SMPTE170M;
248         } else {
249                 return 0;
251         }
253         return 1;
256 /**
257  *****************************************************************************
258  * @brief:  sets crop parameters 
259  *
260  * @param:  vpe  struct vpe pointer
261  *
262  * @return: 0 on success 
263  *****************************************************************************
264 */
265 static int set_crop(struct vpe *vpe)
267         int ret = 0;
268         
269         if ((vpe->crop.c.top == 0) && (vpe->crop.c.left == 0) &&
270             (vpe->crop.c.width == 0) && (vpe->crop.c.height == 0)) {
271                 dprintf("setting default crop params\n");
272                 vpe->crop.c.top = 0;
273                 vpe->crop.c.left = 0;
274                 vpe->crop.c.width = vpe->src.width;
275                 vpe->crop.c.height = vpe->src.height;
276                 vpe->crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
277         }
279         ret = ioctl(vpe->fd, VIDIOC_S_CROP, &vpe->crop);
280         if (ret < 0)
281                 pexit("error setting crop\n");
282         
283         return 0;
286 /**
287  *****************************************************************************
288  * @brief:  sets control, howmany jobs to be handled on multi instance 
289  *
290  * @param:  vpe  struct vpe pointer
291  *
292  * @return: 0 on success 
293  *****************************************************************************
294 */
295 static int set_ctrl(struct vpe *vpe)
297         int ret;
298         struct  v4l2_control ctrl;
300         memset(&ctrl, 0, sizeof(ctrl));
301         ctrl.id = V4L2_CID_TRANS_NUM_BUFS;
302         ctrl.value = vpe->translen;
303         ret = ioctl(vpe->fd, VIDIOC_S_CTRL, &ctrl);
304         if (ret < 0)
305                 pexit("vpe: S_CTRL failed\n");
306         
307         return 0;
310 /**
311  *****************************************************************************
312  * @brief:  Intialize the vpe input by calling set_control, set_format,
313  *          set_crop, refbuf ioctls
314  *
315  * @param:  vpe  struct vpe pointer
316  *
317  * @return: 0 on success 
318  *****************************************************************************
319 */
320 int vpe_input_init(struct vpe *vpe)
322         int ret;
323         struct v4l2_format fmt;
324         struct v4l2_requestbuffers rqbufs;
326         set_ctrl(vpe);
327                 
328         memset(&fmt, 0, sizeof fmt);
329         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
331         ret = ioctl(vpe->fd, VIDIOC_G_FMT, &fmt);
332         if (ret < 0)
333                 pexit( "vpe i/p: G_FMT_1 failed: %s\n", strerror(errno));
335         fmt.fmt.pix_mp.width = vpe->src.width;
336         fmt.fmt.pix_mp.height = vpe->src.height;
337         fmt.fmt.pix_mp.pixelformat = vpe->src.fourcc;
339         switch (vpe->deint) {
340         case 1:
341                 fmt.fmt.pix_mp.field = V4L2_FIELD_ALTERNATE;
342                 break;
343         case 2:
344                 fmt.fmt.pix_mp.field = V4L2_FIELD_SEQ_TB;
345                 break;
346         case 0:
347         default:
348                 fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
349                 break;
350         }
352         ret = ioctl(vpe->fd, VIDIOC_S_FMT, &fmt);
353         if (ret < 0) {
354                 pexit( "vpe i/p: S_FMT failed: %s\n", strerror(errno));
355         } else {
356                 vpe->src.size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
357                 vpe->src.size_uv = fmt.fmt.pix_mp.plane_fmt[1].sizeimage;
358         }
360         ret = ioctl(vpe->fd, VIDIOC_G_FMT, &fmt);
361         if (ret < 0)
362                 pexit( "vpe i/p: G_FMT_2 failed: %s\n", strerror(errno));
364         printf("vpe i/p: G_FMT: width = %u, height = %u, 4cc = %.4s\n",
365                         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
366                         (char*)&fmt.fmt.pix_mp.pixelformat);
368         set_crop(vpe);
370         memset(&rqbufs, 0, sizeof(rqbufs));
371         rqbufs.count = NUMBUF;
372         rqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
373         rqbufs.memory = V4L2_MEMORY_DMABUF;
375         ret = ioctl(vpe->fd, VIDIOC_REQBUFS, &rqbufs);
376         if (ret < 0)
377                 pexit( "vpe i/p: REQBUFS failed: %s\n", strerror(errno));
379         vpe->src.numbuf = rqbufs.count;
380         dprintf("vpe i/p: allocated buffers = %d\n", rqbufs.count);
381         
382         return 0;
386 /**
387  *****************************************************************************
388  * @brief:  Initialize vpe output by calling set_format, reqbuf ioctls.
389  *          Also allocates buffer to display the vpe output. 
390  *
391  * @param:  vpe  struct vpe pointer
392  *
393  * @return: 0 on success 
394  *****************************************************************************
395 */
396 int vpe_output_init(struct vpe *vpe)
398         int ret, i;
399         struct v4l2_format fmt;
400         struct v4l2_requestbuffers rqbufs;
402         memset(&fmt, 0, sizeof fmt);
403         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
405         ret = ioctl(vpe->fd, VIDIOC_G_FMT, &fmt);
406         if (ret < 0)
407                 pexit( "vpe o/p: G_FMT_1 failed: %s\n", strerror(errno));
409         fmt.fmt.pix_mp.width = vpe->dst.width;
410         fmt.fmt.pix_mp.height = vpe->dst.height;
411         fmt.fmt.pix_mp.pixelformat = vpe->dst.fourcc;
412         fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
414         ret = ioctl(vpe->fd, VIDIOC_S_FMT, &fmt);
415         if (ret < 0)
416                 pexit( "vpe o/p: S_FMT failed: %s\n", strerror(errno));
418         ret = ioctl(vpe->fd, VIDIOC_G_FMT, &fmt);
419         if (ret < 0)
420                 pexit( "vpe o/p: G_FMT_2 failed: %s\n", strerror(errno));
422         printf("vpe o/p: G_FMT: width = %u, height = %u, 4cc = %.4s\n",
423                         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
424                         (char*)&fmt.fmt.pix_mp.pixelformat);
426         memset(&rqbufs, 0, sizeof(rqbufs));
427         rqbufs.count = NUMBUF;
428         rqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
429         rqbufs.memory = V4L2_MEMORY_DMABUF;
431         ret = ioctl(vpe->fd, VIDIOC_REQBUFS, &rqbufs);
432         if (ret < 0)
433                 pexit( "vpe o/p: REQBUFS failed: %s\n", strerror(errno));
435         vpe->dst.numbuf = rqbufs.count;
436         dprintf("vpe o/p: allocated buffers = %d\n", rqbufs.count);
437         
438         vpe->disp_bufs = disp_get_vid_buffers(vpe->disp, NUMBUF, vpe->dst.fourcc, 
439                                               vpe->dst.width, vpe->dst.height);
440         if (!vpe->disp_bufs)
441                 pexit("allocating display buffer failed\n");
443         for (i = 0; i < NUMBUF; i++) {
444                 vpe->output_buf_dmafd[i] = omap_bo_dmabuf(vpe->disp_bufs[i]->bo[0]);
445                 vpe->disp_bufs[i]->fd[0] = vpe->output_buf_dmafd[i];
446                 /* display only image widthxheight, no full screen */
447                 vpe->disp_bufs[i]->noScale = true;
448                 dprintf("vpe->disp_bufs_fd[%d] = %d\n", i, vpe->output_buf_dmafd[i]);
449         }
451         dprintf("allocating display buffer success\n");
452         return 0;
455 /**
456  *****************************************************************************
457  * @brief:  queue buffer to vpe input 
458  *
459  * @param:  vpe  struct vpe pointer
460  * @param:  index  buffer index to queue
461  *
462  * @return: 0 on success 
463  *****************************************************************************
464 */
465 int vpe_input_qbuf(struct vpe *vpe, int index)
467         int ret, i;
468         struct v4l2_buffer buf;
469         struct v4l2_plane planes[2];
471         dprintf("vpe input buffer queue\n");
473         memset(&buf, 0, sizeof buf);
474         memset(&planes, 0, sizeof planes);
476         planes[0].length = planes[0].bytesused = vpe->src.size;
477         if(vpe->src.coplanar)
478                 planes[1].length = planes[1].bytesused = vpe->src.size_uv;
480         planes[0].data_offset = planes[1].data_offset = 0;
482         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
483         buf.memory = V4L2_MEMORY_DMABUF;
484         buf.index = index;
485         buf.m.planes = &planes;
486         buf.field = vpe->field;
487         if(vpe->src.coplanar)
488                 buf.length = 2;
489         else
490                 buf.length = 1;
492         buf.m.planes[0].m.fd = vpe->input_buf_dmafd[index];
493         if(vpe->src.coplanar)
494                 buf.m.planes[1].m.fd = vpe->input_buf_dmafd_uv[index];
496         ret = ioctl(vpe->fd, VIDIOC_QBUF, &buf);
497         if (ret < 0)
498                 pexit( "vpe i/p: QBUF failed: %s, index = %d\n",
499                         strerror(errno), index);
501         return 0;
504 /**
505  *****************************************************************************
506  * @brief:  queue buffer to vpe output 
507  *
508  * @param:  vpe  struct vpe pointer
509  * @param:  index  buffer index to queue
510  *
511  * @return: 0 on success 
512  *****************************************************************************
513 */
514 int vpe_output_qbuf(struct vpe *vpe, int index)
516         int ret, i;
517         struct v4l2_buffer buf;
518         struct v4l2_plane planes[2];
520         dprintf("vpe output buffer queue\n");
522         memset(&buf, 0, sizeof buf);
523         memset(&planes, 0, sizeof planes);
525         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
526         buf.memory = V4L2_MEMORY_DMABUF;
527         buf.index = index;
528         buf.m.planes = &planes;
529         buf.length = 2;
531         buf.m.planes[0].m.fd = vpe->output_buf_dmafd[index];
533         ret = ioctl(vpe->fd, VIDIOC_QBUF, &buf);
534         if (ret < 0)
535                 pexit( "vpe o/p: QBUF failed: %s, index = %d\n",
536                         strerror(errno), index);
538         return 0;
541 /**
542  *****************************************************************************
543  * @brief:  start stream 
544  *
545  * @param:  fd  device fd
546  * @param:  type  buffer type (CAPTURE or OUTPUT)
547  *
548  * @return: 0 on success 
549  *****************************************************************************
550 */
551 int stream_ON(int fd, int type)
553         int ret;
555         ret = ioctl(fd, VIDIOC_STREAMON, &type);
556         if (ret < 0)
557                 pexit("STREAMON failed,  %d: %s\n", type, strerror(errno));
559         dprintf("stream ON: done! fd = %d,  type = %d\n", fd, type);
561         return 0;
564 /**
565  *****************************************************************************
566  * @brief:  stop stream 
567  *
568  * @param:  fd  device fd
569  * @param:  type  buffer type (CAPTURE or OUTPUT)
570  *
571  * @return: 0 on success 
572  *****************************************************************************
573 */
574 int stream_OFF(int fd, int type)
576         int ret;
578         ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
579         if (ret < 0)
580                 pexit("STREAMOFF failed, %d: %s\n", type, strerror(errno));
582         dprintf("stream OFF: done! fd = %d,  type = %d\n", fd, type);
584         return 0;
587 /**
588  *****************************************************************************
589  * @brief:  dequeue vpe input buffer  
590  *
591  * @param:  vpe  struct vpe pointer
592  *
593  * @return: buf.index index of dequeued buffer
594  *****************************************************************************
595 */
596 int vpe_input_dqbuf(struct vpe *vpe)
598         int ret;
599         struct v4l2_buffer buf;
600         struct v4l2_plane planes[2];
601         
602         dprintf("vpe input dequeue buffer\n");
603         
604         memset(&buf, 0, sizeof buf);
605         memset(&planes, 0, sizeof planes);
607         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
608         buf.memory = V4L2_MEMORY_DMABUF;
609         buf.m.planes = &planes;
610         if(vpe->src.coplanar)
611                 buf.length = 2;
612         else 
613                 buf.length = 1;
614         ret = ioctl(vpe->fd, VIDIOC_DQBUF, &buf);
615         if (ret < 0)
616                 pexit("vpe i/p: DQBUF failed: %s\n", strerror(errno));
618         dprintf("vpe i/p: DQBUF index = %d\n", buf.index);
620         return buf.index;
623 /**
624  *****************************************************************************
625  * @brief:  dequeue vpe output buffer
626  *
627  * @param:  vpe  struct vpe pointer
628  *
629  * @return: buf.index index of dequeued buffer
630  *****************************************************************************
631 */
632 int vpe_output_dqbuf(struct vpe *vpe)
634         int ret;
635         struct v4l2_buffer buf;
636         struct v4l2_plane planes[2];
638         dprintf("vpe output dequeue buffer\n");
640         memset(&buf, 0, sizeof buf);
641         memset(&planes, 0, sizeof planes);
643         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
644         buf.memory = V4L2_MEMORY_DMABUF;
645         buf.m.planes = &planes;
646         buf.length = 1;
647         ret = ioctl(vpe->fd, VIDIOC_DQBUF, &buf);
648         if (ret < 0)
649                 pexit("vpe o/p: DQBUF failed: %s\n", strerror(errno));
651         dprintf("vpe o/p: DQBUF index = %d\n", buf.index);
653         return buf.index;
656 /**
657  *****************************************************************************
658  * @brief:  buffer retried by index and displays the contents
659  *
660  * @param:  vpe  struct vpe pointer
661  * @param: index index of dequeued output buffer
662  *
663  * @return: 0 on success 
664  *****************************************************************************
665 */
666 int display_buffer(struct vpe *vpe, int index)
668         int ret;
669         struct buffer *buf;
670         
671         buf = vpe->disp_bufs[index];
672         ret = disp_post_vid_buffer(vpe->disp, buf, 0, 0, vpe->dst.width,
673                                    vpe->dst.height);
674         if (ret)
675                 pexit("disp post vid buf failed\n");
677         return 0;