1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <getopt.h>
6
7 #include <string>
8
9 #include "media_v4l2_device.h"
10
ExerciseControl(V4L2Device * v4l2_dev,uint32_t id,const char * control)11 void ExerciseControl(V4L2Device* v4l2_dev, uint32_t id, const char* control) {
12 v4l2_queryctrl query_ctrl;
13 if (v4l2_dev->QueryControl(id, &query_ctrl)) {
14 if (!v4l2_dev->SetControl(id, query_ctrl.maximum))
15 printf("[Warning] Can not set %s to maximum value\n", control);
16 if (!v4l2_dev->SetControl(id, query_ctrl.minimum))
17 printf("[Warning] Can not set %s to minimum value\n", control);
18 if (!v4l2_dev->SetControl(id, query_ctrl.default_value))
19 printf("[Warning] Can not set %s to default value\n", control);
20 } else {
21 printf("[Warning] Can not query control name :%s\n", control);
22 }
23 }
24
TestMultipleOpen(const char * dev_name,V4L2Device::IOMethod io)25 void TestMultipleOpen(const char* dev_name, V4L2Device::IOMethod io) {
26 V4L2Device v4l2_dev1(dev_name, io, 4);
27 V4L2Device v4l2_dev2(dev_name, io, 4);
28 if (!v4l2_dev1.OpenDevice()) {
29 printf("[Error] Can not open device '%s' for the first time\n", dev_name);
30 }
31 if (!v4l2_dev2.OpenDevice()) {
32 printf("[Error] Can not open device '%s' for the second time\n", dev_name);
33 exit(EXIT_FAILURE);
34 }
35 v4l2_dev1.CloseDevice();
36 v4l2_dev2.CloseDevice();
37 printf("[OK ] V4L2DeviceTest.MultipleOpen\n");
38 }
39
TestMultipleInit(const char * dev_name,V4L2Device::IOMethod io)40 void TestMultipleInit(const char* dev_name, V4L2Device::IOMethod io) {
41 V4L2Device v4l2_dev1(dev_name, io, 4);
42 V4L2Device v4l2_dev2(dev_name, io, 4);
43 if (!v4l2_dev1.OpenDevice()) {
44 printf("[Error] Can not open device '%s' for the first time\n", dev_name);
45 }
46 if (!v4l2_dev2.OpenDevice()) {
47 printf("[Error] Can not open device '%s' for the second time\n", dev_name);
48 }
49
50 if (!v4l2_dev1.InitDevice(640, 480, V4L2_PIX_FMT_YUYV, 0)) {
51 printf("[Error] Can not init device '%s' for the first time\n", dev_name);
52 }
53
54 // multiple streaming request should fail.
55 if (v4l2_dev2.InitDevice(640, 480, V4L2_PIX_FMT_YUYV, 0)) {
56 printf("[Error] Multiple init device '%s' should fail\n", dev_name);
57 exit(EXIT_FAILURE);
58 }
59
60 v4l2_dev1.UninitDevice();
61 v4l2_dev2.UninitDevice();
62 v4l2_dev1.CloseDevice();
63 v4l2_dev2.CloseDevice();
64 printf("[OK ] V4L2DeviceTest.MultipleInit\n");
65 }
66
TestEnumInputAndStandard(const char * dev_name,V4L2Device::IOMethod io)67 void TestEnumInputAndStandard(const char* dev_name, V4L2Device::IOMethod io) {
68 V4L2Device v4l2_dev1(dev_name, io, 4);
69 if (!v4l2_dev1.OpenDevice()) {
70 printf("[Error] Can not open device '%s'\n", dev_name);
71 }
72 v4l2_dev1.EnumInput();
73 v4l2_dev1.EnumStandard();
74 v4l2_dev1.CloseDevice();
75 printf("[OK ] V4L2DeviceTest.EnumInputAndStandard\n");
76 }
77
TestEnumControl(const char * dev_name,V4L2Device::IOMethod io)78 void TestEnumControl(const char* dev_name, V4L2Device::IOMethod io) {
79 V4L2Device v4l2_dev(dev_name, io, 4);
80 if (!v4l2_dev.OpenDevice()) {
81 printf("[Error] Can not open device '%s'\n", dev_name);
82 }
83 v4l2_dev.EnumControl();
84 v4l2_dev.CloseDevice();
85 printf("[OK ] V4L2DeviceTest.EnumControl\n");
86 }
87
TestSetControl(const char * dev_name,V4L2Device::IOMethod io)88 void TestSetControl(const char* dev_name, V4L2Device::IOMethod io) {
89 V4L2Device v4l2_dev(dev_name, io, 4);
90 if (!v4l2_dev.OpenDevice()) {
91 printf("[Error] Can not open device '%s'\n", dev_name);
92 }
93 ExerciseControl(&v4l2_dev, V4L2_CID_BRIGHTNESS, "brightness");
94 ExerciseControl(&v4l2_dev, V4L2_CID_CONTRAST, "contrast");
95 ExerciseControl(&v4l2_dev, V4L2_CID_SATURATION, "saturation");
96 ExerciseControl(&v4l2_dev, V4L2_CID_GAMMA, "gamma");
97 ExerciseControl(&v4l2_dev, V4L2_CID_HUE, "hue");
98 ExerciseControl(&v4l2_dev, V4L2_CID_GAIN, "gain");
99 ExerciseControl(&v4l2_dev, V4L2_CID_SHARPNESS, "sharpness");
100 v4l2_dev.CloseDevice();
101 printf("[OK ] V4L2DeviceTest.SetControl\n");
102 }
103
TestSetCrop(const char * dev_name,V4L2Device::IOMethod io)104 void TestSetCrop(const char* dev_name, V4L2Device::IOMethod io) {
105 V4L2Device v4l2_dev(dev_name, io, 4);
106 if (!v4l2_dev.OpenDevice()) {
107 printf("[Error] Can not open device '%s'\n", dev_name);
108 }
109 v4l2_cropcap cropcap;
110 memset(&cropcap, 0, sizeof(cropcap));
111 if (v4l2_dev.GetCropCap(&cropcap)) {
112 v4l2_crop crop;
113 memset(&crop, 0, sizeof(crop));
114 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
115 crop.c = cropcap.defrect;
116 v4l2_dev.SetCrop(&crop);
117 }
118 v4l2_dev.CloseDevice();
119 printf("[OK ] V4L2DeviceTest.SetCrop\n");
120 }
121
TestGetCrop(const char * dev_name,V4L2Device::IOMethod io)122 void TestGetCrop(const char* dev_name, V4L2Device::IOMethod io) {
123 V4L2Device v4l2_dev(dev_name, io, 4);
124 if (!v4l2_dev.OpenDevice()) {
125 printf("[Error] Can not open device '%s'\n", dev_name);
126 }
127 v4l2_crop crop;
128 memset(&crop, 0, sizeof(crop));
129 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
130 v4l2_dev.GetCrop(&crop);
131 v4l2_dev.CloseDevice();
132 printf("[OK ] V4L2DeviceTest.GetCrop\n");
133 }
134
TestProbeCaps(const char * dev_name,V4L2Device::IOMethod io)135 void TestProbeCaps(const char* dev_name, V4L2Device::IOMethod io) {
136 V4L2Device v4l2_dev(dev_name, io, 4);
137 if (!v4l2_dev.OpenDevice()) {
138 printf("[Error] Can not open device '%s'\n", dev_name);
139 }
140 v4l2_capability caps;
141 if (!v4l2_dev.ProbeCaps(&caps, true)) {
142 printf("[Error] Can not probe caps on device '%s'\n", dev_name);
143 }
144 v4l2_dev.CloseDevice();
145 printf("[OK ] V4L2DeviceTest.ProbeCaps\n");
146 }
147
TestEnumFormats(const char * dev_name,V4L2Device::IOMethod io)148 void TestEnumFormats(const char* dev_name, V4L2Device::IOMethod io) {
149 V4L2Device v4l2_dev(dev_name, io, 4);
150 if (!v4l2_dev.OpenDevice()) {
151 printf("[Error] Can not open device '%s'\n", dev_name);
152 }
153 v4l2_dev.EnumFormat(NULL);
154 v4l2_dev.CloseDevice();
155 printf("[OK ] V4L2DeviceTest.EnumFormats\n");
156 }
157
TestEnumFrameSize(const char * dev_name,V4L2Device::IOMethod io)158 void TestEnumFrameSize(const char* dev_name, V4L2Device::IOMethod io) {
159 V4L2Device v4l2_dev(dev_name, io, 4);
160 if (!v4l2_dev.OpenDevice()) {
161 printf("[Error] Can not open device '%s'\n", dev_name);
162 }
163 uint32_t format_count = 0;
164 v4l2_dev.EnumFormat(&format_count);
165 for (uint32_t i = 0; i < format_count; ++i) {
166 uint32_t pixfmt = v4l2_dev.GetPixelFormat(i);
167 if (pixfmt == 0xFFFFFFFF) {
168 printf("[Error] Enumerate format error on device '%s'\n", dev_name);
169 exit(EXIT_FAILURE);
170 }
171 if (!v4l2_dev.EnumFrameSize(pixfmt)) {
172 printf("[Warning] Enumerate frame size error on device '%s'\n", dev_name);
173 };
174 }
175 v4l2_dev.CloseDevice();
176 printf("[OK ] V4L2DeviceTest.EnumFrameSize\n");
177 }
178
TestFrameRate(const char * dev_name,V4L2Device::IOMethod io)179 void TestFrameRate(const char* dev_name, V4L2Device::IOMethod io) {
180 V4L2Device v4l2_dev(dev_name, io, 4);
181 if (!v4l2_dev.OpenDevice()) {
182 printf("[Error] Can not open device '%s'\n", dev_name);
183 }
184 v4l2_capability caps;
185 if (!v4l2_dev.ProbeCaps(&caps, true)) {
186 printf("[Error] Can not probe caps on device '%s'\n", dev_name);
187 exit(EXIT_FAILURE);
188 }
189 // we only try to adjust frame rate when it claims can.
190 if (caps.capabilities & V4L2_CAP_TIMEPERFRAME) {
191 v4l2_streamparm param;
192 if (!v4l2_dev.GetParam(¶m)) {
193 printf("[Error] Can not get stream param on device '%s'\n", dev_name);
194 exit(EXIT_FAILURE);
195 }
196 if (!v4l2_dev.SetParam(¶m)) {
197 printf("[Error] Can not set stream param on device '%s'\n", dev_name);
198 exit(EXIT_FAILURE);
199 }
200
201 if (!v4l2_dev.SetFrameRate(15)) {
202 printf("[Error] SetFrameRate failed on '%s'\n", dev_name);
203 exit(EXIT_FAILURE);
204 }
205 if (!v4l2_dev.GetParam(¶m)) {
206 printf("[Error] Can not get stream param on device '%s'\n", dev_name);
207 exit(EXIT_FAILURE);
208 }
209 if (param.parm.capture.timeperframe.denominator !=
210 param.parm.capture.timeperframe.numerator * 15) {
211 printf("[Error] Can not set frame rate to 15 on '%s'\n", dev_name);
212 exit(EXIT_FAILURE);
213 }
214
215 if (!v4l2_dev.SetFrameRate(10)) {
216 printf("[Error] SetFrameRate failed on '%s'\n", dev_name);
217 exit(EXIT_FAILURE);
218 }
219 if (!v4l2_dev.GetParam(¶m)) {
220 printf("[Error] Can not get stream param on device '%s'\n", dev_name);
221 exit(EXIT_FAILURE);
222 }
223 if (param.parm.capture.timeperframe.denominator !=
224 param.parm.capture.timeperframe.numerator * 10) {
225 printf("[Error] Can not set frame rate to 10 on '%s'\n", dev_name);
226 exit(EXIT_FAILURE);
227 }
228 }
229
230 v4l2_dev.CloseDevice();
231 printf("[OK ] V4L2DeviceTest.FrameRate\n");
232 }
233
PrintUsage()234 static void PrintUsage() {
235 printf("Usage: media_v4l2_unittest [options]\n\n"
236 "Options:\n"
237 "--device=DEVICE_NAME Video device name [/dev/video]\n"
238 "--help Print usage\n"
239 "--buffer-io=mmap Use memory mapped buffers\n"
240 "--buffer-io=read Use read() calls\n"
241 "--buffer-io=userp Use application allocated buffers\n");
242 }
243
244 static const char short_options[] = "d:?b";
245 static const struct option long_options[] = {
246 { "device", required_argument, NULL, 'd' },
247 { "help", no_argument, NULL, '?' },
248 { "buffer-io", required_argument, NULL, 'b' },
249 };
250
main(int argc,char ** argv)251 int main(int argc, char** argv) {
252 std::string dev_name = "/dev/video", io_name;
253 V4L2Device::IOMethod io = V4L2Device::IO_METHOD_MMAP;
254
255 // Parse the command line.
256 for (;;) {
257 int32_t index;
258 int32_t c = getopt_long(argc, argv, short_options, long_options, &index);
259 if (-1 == c)
260 break;
261 switch (c) {
262 case 0: // getopt_long() flag.
263 break;
264 case 'd':
265 // Initialize default v4l2 device name.
266 dev_name = strdup(optarg);
267 break;
268 case '?':
269 PrintUsage();
270 exit (EXIT_SUCCESS);
271 case 'b':
272 io_name = strdup(optarg);
273 if (io_name == "mmap") {
274 io = V4L2Device::IO_METHOD_MMAP;
275 } else if (io_name == "read") {
276 io = V4L2Device::IO_METHOD_READ;
277 } else if (io_name == "userp") {
278 io = V4L2Device::IO_METHOD_USERPTR;
279 } else {
280 PrintUsage();
281 exit(EXIT_FAILURE);
282 }
283 break;
284 default:
285 PrintUsage();
286 exit(EXIT_FAILURE);
287 }
288 }
289
290 TestMultipleOpen(dev_name.c_str(), io);
291 TestMultipleInit(dev_name.c_str(), io);
292 TestEnumInputAndStandard(dev_name.c_str(), io);
293 TestEnumControl(dev_name.c_str(), io);
294 TestSetControl(dev_name.c_str(), io);
295 TestSetCrop(dev_name.c_str(), io);
296 TestGetCrop(dev_name.c_str(), io);
297 TestProbeCaps(dev_name.c_str(), io);
298 TestEnumFormats(dev_name.c_str(), io);
299 TestEnumFrameSize(dev_name.c_str(), io);
300 TestFrameRate(dev_name.c_str(), io);
301 }
302
303