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 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 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 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 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 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 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 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 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 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 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 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 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 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 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