dmabuftest: Use 6 buffers instead of 3
[glsdk/omapdrmtest.git] / v4l2capturedisplay.c
1 /*
2  * Copyright (C) 2013 Texas Instruments
3  * Author: Nikhil Devshatwar <nikhil.nd@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  */
19 /*
20  * This is a drm test app to capture and display frames from a v4l2 device
21  * It uses standard single planar V4L2 API to capture progressive frames
22  * Displays the buffers via drm in fullscreen
23  * Currently only YUYV format is allowed
24  * This can be used to test VIP (Video Input Port) on DRA7xx SoC
25  * For this, vpdma firmware should be copied in /lib/firmware on target
26  */
28 #include "util.h"
30 #include <linux/videodev2.h>
31 #include <sys/ioctl.h>
32 #include <sys/mman.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
40 #define NBUF 6
42 int width = 640, height = 480;
44 void *buffer_addr[NBUF];
45 int size[NBUF];
47 static int xioctl(int fd, int request, void *arg)
48 {
49         int r;
51         do r = ioctl (fd, request, arg);
52         while (-1 == r && EINTR == errno);
54         return r;
55 }
57 int init_device(int fd)
58 {
59         char fourcc[5];
60         unsigned int i;
61         struct v4l2_format fmt;
62         struct v4l2_requestbuffers req;
63         struct v4l2_buffer buf;
64         struct v4l2_capability caps;
66         /* Check for capture device */
67         memset(&caps, 0, sizeof(caps));
69         if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)) {
70                 perror("Setting Pixel Format");
71                 return 1;
72         }
73         MSG("Driver: %s\ncaps: %8x", caps.driver, caps.capabilities);
74         if(~caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
75                 MSG("Not a capture device");
76                 return 1;
77         }
79         /* Set capture format to YUYV */
80         memset(&fmt, 0, sizeof(fmt));
81         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
82         fmt.fmt.pix.width = width;
83         fmt.fmt.pix.height = height;
84         fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
85         fmt.fmt.pix.field = V4L2_FIELD_NONE;
87         if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) {
88                 perror("Setting Pixel Format");
89                 return 1;
90         }
92         strncpy(fourcc, (char *)&fmt.fmt.pix.pixelformat, 4);
93         MSG( "Selected Camera Mode:\n"
94                 "  Width: %d\n"
95                 "  Height: %d\n"
96                 "  PixFmt: %s\n"
97                 "  Field: %d",
98                 fmt.fmt.pix.width,
99                 fmt.fmt.pix.height,
100                 fourcc,
101                 fmt.fmt.pix.field);
103         /* Currently driver supports only mmap buffers
104          * Request memory mapped buffers */
105         memset(&req, 0, sizeof(req));
106         req.count = 6;
107         req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
108         req.memory = V4L2_MEMORY_MMAP;
110         if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
111                 perror("Requesting Buffer");
112                 return 1;
113         }
115         for (i = 0; i < req.count; i++) {
116                 memset(&buf, 0, sizeof(buf));
117                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
118                 buf.memory = V4L2_MEMORY_MMAP;
119                 buf.index = i;
120                 if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) {
121                         perror("Querying Buffer");
122                         return 1;
123                 }
125                 /* Memory map all the buffers and save the addresses */
126                 buffer_addr[i] = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
127                 size[i] = buf.length;
128                 MSG("Length: %d\nAddress: %p", buf.length, buffer_addr[i]);
129                 MSG("Image Length: %d", buf.bytesused);
131                 /* Queue the buffer for capture */
132                 memset(&buf, 0, sizeof(buf));
133                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
134                 buf.memory = V4L2_MEMORY_MMAP;
135                 buf.index = i;
136                 if(-1 == xioctl(fd, VIDIOC_QBUF, &buf)) {
137                         perror("Queue Buffer");
138                         return 1;
139                 }
141         }
142         if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type)) {
143                 perror("Start Capture");
144                 return 1;
145         }
146         return 0;
149 void release_device(int fd)
151         int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
152         xioctl(fd, VIDIOC_STREAMOFF, &type);
153         close(fd);
156 static void usage(char *name) {
157         MSG("Usage: %s [OPTION]...", name);
158         MSG("V4L2 capture display test");
159         MSG("");
160         MSG("v4l2capturedisplay options:");
161         MSG("\t-h, --help: Print this help and exit.");
162         MSG("\t-n:\t Number of frames to capture (0 for infinite)");
163         MSG("\t-d:\t Device node to be used as capture device");
164         MSG("");
165         disp_usage();
168 void copy_buf(struct buffer *buf, void *deqbuf)
170         int i, height = buf->height, stride = buf->pitches[0];
171         int capStride = 2 * width;
172         uint8_t *dst, *src;
174         dst = omap_bo_map(buf->bo[0]);
175         src = deqbuf;
177         /* Call this before you start accessing display buffers */
178         for (i = 0; i < buf->nbo; i++)
179                 omap_bo_cpu_prep(buf->bo[i], OMAP_GEM_WRITE);
181         /* YUYV format - Only one bo expected
182          * TODO: Change this for all formats */
183         for(i=0; i<height; i++) {
184                 dst += stride;
185                 src += capStride;
186                 memcpy(dst, src, capStride);
187         }
189         /* Call this after you are done with accessing display buffers */
190         for (i = 0; i < buf->nbo; i++)
191                 omap_bo_cpu_fini(buf->bo[i], OMAP_GEM_WRITE);
195 int main(int argc, char **argv)
197         struct display *disp;
198         struct buffer **buffers;
199         int ret, i, idx, fd, count = 0;
200         char devnode[100] = "/dev/video1";
202         /* Parse command line arguments */
203         for (i = 1; i < argc; i++) {
204                 if (!strcmp(argv[i], "-h")) {
205                         argv[i++] = NULL;
206                         if(sscanf(argv[i], "%d", &height) != 1) {
207                                 ERROR("invalid height: %s", argv[i]);
208                                 return 1;
209                         }
210                         argv[i] = NULL;
211                 } else if (!strcmp(argv[i], "-w")) {
212                         argv[i++] = NULL;
213                         if(sscanf(argv[i], "%d", &width) != 1) {
214                                 ERROR("invalid width: %s", argv[i]);
215                                 return 1;
216                         }
217                         argv[i] = NULL;
218                 } else if (!strcmp(argv[i], "-n")) {
219                         argv[i++] = NULL;
220                         if(sscanf(argv[i], "%d", &count) != 1) {
221                                 ERROR("invalid count: %s", argv[i]);
222                                 return 1;
223                         }
224                         argv[i] = NULL;
225                 } else if (!strcmp(argv[i], "-d")) {
226                         argv[i++] = NULL;
227                         strncpy(devnode, argv[i],100);
228                         argv[i] = NULL;
229                 }
230         }
232         MSG("Opening Video device %s", devnode);
233         fd = open(devnode, O_RDWR);
234         if (fd == -1) {
235                 perror("Opening video device");
236                 return 1;
237         }
239         ret = init_device(fd);
240         if (0 != ret) {
241                 MSG("Exiting");
242                 return ret;
243         }
245         MSG("Opening Display..");
246         disp = disp_open(argc, argv);
247         if (NULL == disp) {
248                 usage(argv[0]);
249                 return 1;
250         }
252         if (check_args(argc, argv)) {
253                 /* remaining args.. print usage msg */
254                 usage(argv[0]);
255                 return 1;
256         }
258         /* Request drm to allocate some buffers */
259         buffers = disp_get_vid_buffers(disp, NBUF, FOURCC_STR("YUYV"), width, height);
260         if (!buffers) {
261                 return 1;
262         }
264         for (i = 1; i != count; i++) {
265                 struct buffer *dispbuf = buffers[i % NBUF];
266                 struct v4l2_buffer buf;
268                 /* Dequeue one buffer */
269                 memset(&buf, 0, sizeof(buf));
270                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
271                 buf.memory = V4L2_MEMORY_MMAP;
272                 if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
273                         perror("Queue Buffer");
274                         return 1;
275                 }
276                 idx = buf.index;
278                 /* Copy data from dequeued buffer into display buffer */
279                 copy_buf(dispbuf, buffer_addr[idx]);
280                 /* Give it to display */
281                 ret = disp_post_vid_buffer(disp, dispbuf, 0, 0, width, height);
282                 if (ret) {
283                         return ret;
284                 }
286                 /* Queue it back for next capture */
287                 memset(&buf, 0, sizeof(buf));
288                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
289                 buf.memory = V4L2_MEMORY_MMAP;
290                 buf.index = idx;
291                 if(-1 == xioctl(fd, VIDIOC_QBUF, &buf)) {
292                         perror("Queue Buffer");
293                         return 1;
294                 }
295         }
297         disp_free_buffers(disp, NBUF);
298         disp_close(disp);
299         release_device(fd);
301         return 0;