disp-kms: Add support for dual capture
authorNikhil Devshatwar <nikhil.nd@ti.com>
Thu, 5 Dec 2013 22:15:32 +0000 (03:45 +0530)
committerAmarinder Bindra <a-bindra@ti.com>
Wed, 11 Dec 2013 06:30:05 +0000 (12:00 +0530)
Using '--dual' option, two different video nodes can be openeed
Running the loopback in a thred with common display.
One thread runs in full screen while other is overlayed on top of it.

Signed-off-by: Nikhil Devshatwar <nikhil.nd@ti.com>
Makefile.am
dmabuftest.c
util/v4l2.c

index 19cfa05ca8064295c24a3816f45ed96c61104897..5521dbfbf32830126b77ac6d74d1b9214d84313a 100644 (file)
@@ -38,7 +38,7 @@ v4l2capturedisplay_LDADD = $(LDADD_COMMON)
 
 if ENABLE_V4L2_DMABUF
 dmabuftest_SOURCES = dmabuftest.c
-dmabuftest_LDADD = $(LDADD_COMMON)
+dmabuftest_LDADD = $(LDADD_COMMON) -lpthread
 endif
 
 if ENABLE_DCE
index 016acdcd2da04457903df8f3b3959df821a5c6fd..a8329eb723e7330b0381d23f4d9c37f7f2e895e6 100644 (file)
  */
 
 
+#include <pthread.h>
 #include "util.h"
 
 #define NBUF 3
 #define CNT  500
 
+enum display_area {
+       FULL,
+       OVERLAY
+};
+
+struct thr_data {
+       struct display *disp;
+       struct v4l2 *v4l2;
+       uint32_t fourcc, width, height;
+       enum display_area area;
+};
+
 static void
 usage(char *name)
 {
@@ -31,15 +44,68 @@ usage(char *name)
        v4l2_usage();
 }
 
+void *
+capture_loop(void *arg)
+{
+       struct thr_data *data = (struct thr_data *)arg;
+       struct display *disp = data->disp;
+       struct v4l2 *v4l2 = data->v4l2;
+       uint32_t fourcc = data->fourcc;
+       uint32_t width = data->width, height = data->height;
+
+       struct buffer **buffers;
+       int ret, i;
+
+       buffers = disp_get_vid_buffers(disp, NBUF, fourcc, width, height);
+       if (!buffers) {
+               return NULL;
+       }
+
+       ret = v4l2_reqbufs(v4l2, buffers, NBUF);
+       if (ret) {
+               return NULL;
+       }
+
+       if(data->area == OVERLAY) {
+               for (i = 0; i < NBUF; i++) {
+                       buffers[i]->noScale = true;
+                       get_overlay_plane(disp, buffers[i]);
+               }
+       }
+       v4l2_qbuf(v4l2, buffers[0]);
+       v4l2_streamon(v4l2);
+       for (i = 1; i < CNT; i++) {
+               v4l2_qbuf(v4l2, buffers[i % NBUF]);
+
+               switch(data->area) {
+               case FULL:
+                       ret = disp_post_vid_buffer(disp, v4l2_dqbuf(v4l2),
+                               0, 0, width, height);
+               break;
+               case OVERLAY:
+                       ret = disp_post_vid_buffer(disp, v4l2_dqbuf(v4l2),
+                               0, 0, width, height);
+               break;
+               }
+               if (ret) {
+                       return NULL;
+               }
+       }
+       v4l2_streamoff(v4l2);
+
+       MSG("Ok!");
+       return disp;
+}
+
 int
 main(int argc, char **argv)
 {
        struct display *disp;
        struct v4l2 *v4l2;
-       struct buffer *framebuf;
-       struct buffer **buffers;
-       uint32_t fourcc, width, height;
-       int ret, i;
+       pthread_t threads[2];
+       struct thr_data tdata[2];
+       void *result = NULL;
+       int ret = 0, i, dual = 0;
 
        MSG("Opening Display..");
        disp = disp_open(argc, argv);
@@ -48,12 +114,39 @@ main(int argc, char **argv)
                return 1;
        }
 
+       for (i = 1; i < argc; i++) {
+               if (!argv[i])
+                       continue;
+
+               if (!strcmp("--dual", argv[i])) {
+                       dual = 1;
+                       argv[i] = NULL;
+               }
+       }
+
        MSG("Opening V4L2..");
-       v4l2 = v4l2_open(argc, argv, &fourcc, &width, &height);
+       v4l2 = v4l2_open(argc, argv, &tdata[0].fourcc,
+               &tdata[0].width, &tdata[0].height);
        if (!v4l2) {
                usage(argv[0]);
                return 1;
        }
+       tdata[0].disp = disp;
+       tdata[0].v4l2 = v4l2;
+       tdata[0].area = FULL;
+
+       if(dual) {
+               MSG("Opening second V4L2..");
+               v4l2 = v4l2_open(argc, argv, &tdata[1].fourcc,
+                       &tdata[1].width, &tdata[1].height);
+               if (!v4l2) {
+                       usage(argv[0]);
+                       return 1;
+               }
+               tdata[1].disp = disp;
+               tdata[1].v4l2 = v4l2;
+               tdata[1].area = OVERLAY;
+       }
 
        if (check_args(argc, argv)) {
                /* remaining args.. print usage msg */
@@ -61,32 +154,22 @@ main(int argc, char **argv)
                return 0;
        }
 
-       framebuf = disp_get_fb(disp);
-
-       buffers = disp_get_vid_buffers(disp, NBUF, fourcc, width, height);
-       if (!buffers) {
-               return 1;
-       }
-
-       ret = v4l2_reqbufs(v4l2, buffers, NBUF);
-       if (ret) {
-               return 1;
-       }
-
-       v4l2_qbuf(v4l2, buffers[0]);
-       v4l2_streamon(v4l2);
-       for (i = 1; i < CNT; i++) {
-               v4l2_qbuf(v4l2, buffers[i % NBUF]);
-               ret = disp_post_vid_buffer(disp, v4l2_dqbuf(v4l2),
-                               0, 0, width, height);
-               if (ret) {
-                       return ret;
+       if(dual) {
+               ret = pthread_create(&threads[0], NULL, capture_loop, &tdata[0]);
+               if(ret) {
+                       MSG("Failed creating thread");
                }
+               ret = pthread_create(&threads[1], NULL, capture_loop, &tdata[1]);
+               if(ret) {
+                       MSG("Failed creating thread");
+               }
+       } else {
+               capture_loop(&tdata[0]);
        }
-       v4l2_streamoff(v4l2);
-       v4l2_dqbuf(v4l2);
 
-       MSG("Ok!");
+       pthread_join(threads[0], &result);
+       pthread_join(threads[1], &result);
+
        disp_close(disp);
 
        return ret;
index 1a5c905186a0a8d9e71a76704c3353800d591261..33293e2ef43a51f9b1c179339c4e1130dfb6682c 100644 (file)
@@ -229,16 +229,10 @@ v4l2_open(int argc, char **argv, uint32_t *fourcc,
        };
        struct v4l2 *v4l2;
        int i, ret;
-       bool mcf = false;
+       bool mcf = false, user_format = false, user_dev = false;
+       char devname[20] = "/dev/video1";
 
        v4l2 = calloc(1, sizeof(*v4l2));
-       v4l2->fd = open("/dev/video1", O_RDWR);
-
-       ret = ioctl(v4l2->fd, VIDIOC_G_FMT, &format);
-       if (ret < 0) {
-               ERROR("VIDIOC_G_FMT failed: %s (%d)", strerror(errno), ret);
-               goto fail;
-       }
 
        /* note: set args to NULL after we've parsed them so other modules know
         * that it is already parsed (since the arg parsing is decentralized)
@@ -247,17 +241,31 @@ v4l2_open(int argc, char **argv, uint32_t *fourcc,
                if (!argv[i]) {
                        continue;
                }
-               if (!strcmp("-c", argv[i])) {
+               if (!strcmp("-d", argv[i])) {
+                       if(user_dev)
+                               continue;
+
+                       argv[i++] = NULL;
+                       if (sscanf(argv[i], "%s", devname) != 1) {
+                               ERROR("invalid device node: %s", argv[i]);
+                               goto fail;
+                       }
+                       user_dev = true;
+               } else if (!strcmp("-c", argv[i])) {
+                       if(user_format)
+                               continue;
+
                        char fourccstr[5];
                        argv[i++] = NULL;
                        if (sscanf(argv[i], "%ux%u@%4s",
-                                       &format.fmt.pix.width,
-                                       &format.fmt.pix.height,
+                                       width,
+                                       height,
                                        fourccstr) != 3) {
                                ERROR("invalid arg: %s", argv[i]);
                                goto fail;
                        }
-                       format.fmt.pix.pixelformat = FOURCC_STR(fourccstr);
+                       *fourcc = FOURCC_STR(fourccstr);
+                       user_format = true;
                } else if (!strcmp(argv[i], "-m")) {
                        mcf = true;
                } else {
@@ -266,19 +274,29 @@ v4l2_open(int argc, char **argv, uint32_t *fourcc,
                argv[i] = NULL;
        }
 
-       if ((format.fmt.pix.width == 0) ||
-                       (format.fmt.pix.height == 0) ||
+       v4l2->fd = open(devname, O_RDWR);
+
+       ret = ioctl(v4l2->fd, VIDIOC_G_FMT, &format);
+       if (ret < 0) {
+               ERROR("VIDIOC_G_FMT failed: %s (%d)", strerror(errno), ret);
+               goto fail;
+       }
+
+       if (user_format) {
+               format.fmt.pix.pixelformat = *fourcc;
+               format.fmt.pix.width = *width;
+               format.fmt.pix.height = *height;
+       }
+
+       if ((format.fmt.pix.width == 0) || (format.fmt.pix.height == 0) ||
                        (format.fmt.pix.pixelformat == 0)) {
+
                ERROR("invalid capture settings '%dx%d@%4s' (did you not use '-c'?)",
-                               format.fmt.pix.width, format.fmt.pix.height,
-                               (char *)&format.fmt.pix.pixelformat);
+                       format.fmt.pix.width, format.fmt.pix.height,
+                       (char *)&format.fmt.pix.pixelformat);
                goto fail;
        }
 
-       *fourcc = format.fmt.pix.pixelformat;
-       *width  = format.fmt.pix.width;
-       *height = format.fmt.pix.height;
-
        if (mcf) {
                ret = media_setup(&format);
                if (ret < 0) {