1 /*
2 * Copyright (C) 2011 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 */
19 #include <pthread.h>
20 #include "util.h"
22 #define NBUF 3
23 #define CNT 500
25 enum display_area {
26 FULL,
27 OVERLAY
28 };
30 struct thr_data {
31 struct display *disp;
32 struct v4l2 *v4l2;
33 uint32_t fourcc, width, height;
34 enum display_area area;
35 };
37 static void
38 usage(char *name)
39 {
40 MSG("Usage: %s [OPTION]...", name);
41 MSG("Test of buffer passing between v4l2 camera and display.");
42 MSG("");
43 disp_usage();
44 v4l2_usage();
45 }
47 void *
48 capture_loop(void *arg)
49 {
50 struct thr_data *data = (struct thr_data *)arg;
51 struct display *disp = data->disp;
52 struct v4l2 *v4l2 = data->v4l2;
53 uint32_t fourcc = data->fourcc;
54 uint32_t width = data->width, height = data->height;
56 struct buffer **buffers;
57 int ret, i;
59 buffers = disp_get_vid_buffers(disp, NBUF, fourcc, width, height);
60 if (!buffers) {
61 return NULL;
62 }
64 ret = v4l2_reqbufs(v4l2, buffers, NBUF);
65 if (ret) {
66 return NULL;
67 }
69 if(data->area == OVERLAY) {
70 for (i = 0; i < NBUF; i++) {
71 buffers[i]->noScale = true;
72 get_overlay_plane(disp, buffers[i]);
73 }
74 }
75 v4l2_qbuf(v4l2, buffers[0]);
76 v4l2_streamon(v4l2);
77 for (i = 1; i < CNT; i++) {
78 v4l2_qbuf(v4l2, buffers[i % NBUF]);
80 switch(data->area) {
81 case FULL:
82 ret = disp_post_vid_buffer(disp, v4l2_dqbuf(v4l2),
83 0, 0, width, height);
84 break;
85 case OVERLAY:
86 ret = disp_post_vid_buffer(disp, v4l2_dqbuf(v4l2),
87 0, 0, width, height);
88 break;
89 }
90 if (ret) {
91 return NULL;
92 }
93 }
94 v4l2_streamoff(v4l2);
96 MSG("Ok!");
97 return disp;
98 }
100 int
101 main(int argc, char **argv)
102 {
103 struct display *disp;
104 struct v4l2 *v4l2;
105 pthread_t threads[2];
106 struct thr_data tdata[2];
107 void *result = NULL;
108 int ret = 0, i, dual = 0;
110 MSG("Opening Display..");
111 disp = disp_open(argc, argv);
112 if (!disp) {
113 usage(argv[0]);
114 return 1;
115 }
117 for (i = 1; i < argc; i++) {
118 if (!argv[i])
119 continue;
121 if (!strcmp("--dual", argv[i])) {
122 dual = 1;
123 argv[i] = NULL;
124 }
125 }
127 MSG("Opening V4L2..");
128 v4l2 = v4l2_open(argc, argv, &tdata[0].fourcc,
129 &tdata[0].width, &tdata[0].height);
130 if (!v4l2) {
131 usage(argv[0]);
132 return 1;
133 }
134 tdata[0].disp = disp;
135 tdata[0].v4l2 = v4l2;
136 tdata[0].area = FULL;
138 if(dual) {
139 MSG("Opening second V4L2..");
140 v4l2 = v4l2_open(argc, argv, &tdata[1].fourcc,
141 &tdata[1].width, &tdata[1].height);
142 if (!v4l2) {
143 usage(argv[0]);
144 return 1;
145 }
146 tdata[1].disp = disp;
147 tdata[1].v4l2 = v4l2;
148 tdata[1].area = OVERLAY;
149 }
151 if (check_args(argc, argv)) {
152 /* remaining args.. print usage msg */
153 usage(argv[0]);
154 return 0;
155 }
157 if(dual) {
158 ret = pthread_create(&threads[0], NULL, capture_loop, &tdata[0]);
159 if(ret) {
160 MSG("Failed creating thread");
161 }
162 ret = pthread_create(&threads[1], NULL, capture_loop, &tdata[1]);
163 if(ret) {
164 MSG("Failed creating thread");
165 }
166 } else {
167 capture_loop(&tdata[0]);
168 }
170 pthread_join(threads[0], &result);
171 pthread_join(threads[1], &result);
173 disp_close(disp);
175 return ret;
176 }