00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdlib.h>
00025
00026 #include "v4l2uvc.h"
00027 #include "utils.h"
00028
00029 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
00030 #define FOURCC_FORMAT "%c%c%c%c"
00031 #define FOURCC_ARGS(c) (c) & 0xFF, ((c) >> 8) & 0xFF, ((c) >> 16) & 0xFF, ((c) >> 24) & 0xFF
00032
00033
00034 static int debug = 0;
00035
00036
00037
00038 static int init_v4l2(struct vdIn *vd);
00039
00040 int check_videoIn(struct vdIn *vd, char *device)
00041 {
00042 int ret;
00043 if (vd == NULL || device == NULL)
00044 return -1;
00045 vd->videodevice = (char *) calloc(1, 16 * sizeof(char));
00046 snprintf(vd->videodevice, 12, "%s", device);
00047 printf("Device information:\n");
00048 printf(" Device path: %s\n", vd->videodevice);
00049 if ((vd->fd = open(vd->videodevice, O_RDWR)) == -1) {
00050 perror("ERROR opening V4L interface");
00051 return -1;
00052 }
00053 memset(&vd->cap, 0, sizeof(struct v4l2_capability));
00054 ret = ioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap);
00055 if (ret < 0) {
00056 printf("Error opening device %s: unable to query device.\n",
00057 vd->videodevice);
00058 goto fatal;
00059 }
00060 if ((vd->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
00061 printf("Error opening device %s: video capture not supported.\n",
00062 vd->videodevice);
00063 }
00064 if (!(vd->cap.capabilities & V4L2_CAP_STREAMING)) {
00065 printf("%s does not support streaming i/o\n", vd->videodevice);
00066 }
00067 if (!(vd->cap.capabilities & V4L2_CAP_READWRITE)) {
00068 printf("%s does not support read i/o\n", vd->videodevice);
00069 }
00070 enum_frame_formats(vd->fd, NULL, 0);
00071 fatal:
00072 close(vd->fd);
00073 free(vd->videodevice);
00074 return 0;
00075 }
00076 int
00077 init_videoIn(struct vdIn *vd, char *device, int width, int height, int fps,
00078 int format, int grabmethod, char *avifilename)
00079 {
00080 int ret = -1;
00081 int i;
00082 if (vd == NULL || device == NULL)
00083 return -1;
00084 if (width == 0 || height == 0)
00085 return -1;
00086 if (grabmethod < 0 || grabmethod > 1)
00087 grabmethod = 1;
00088 vd->videodevice = NULL;
00089 vd->status = NULL;
00090 vd->pictName = NULL;
00091 vd->videodevice = (char *) calloc(1, 16 * sizeof(char));
00092 vd->status = (char *) calloc(1, 100 * sizeof(char));
00093 vd->pictName = (char *) calloc(1, 80 * sizeof(char));
00094 snprintf(vd->videodevice, 12, "%s", device);
00095 printf("Device information:\n");
00096 printf(" Device path: %s\n", vd->videodevice);
00097 vd->toggleAvi = 0;
00098 vd->avifile = NULL;
00099 vd->avifilename = avifilename;
00100 vd->recordtime = 0;
00101 vd->framecount = 0;
00102 vd->recordstart = 0;
00103 vd->getPict = 0;
00104 vd->signalquit = 1;
00105 vd->width = width;
00106 vd->height = height;
00107 vd->fps = fps;
00108 vd->formatIn = format;
00109 vd->grabmethod = grabmethod;
00110 vd->fileCounter = 0;
00111 vd->rawFrameCapture = 0;
00112 vd->rfsBytesWritten = 0;
00113 vd->rfsFramesWritten = 0;
00114 vd->captureFile = NULL;
00115 vd->bytesWritten = 0;
00116 vd->framesWritten = 0;
00117 if (init_v4l2(vd) < 0) {
00118 printf(" Init v4L2 failed !! exit fatal\n");
00119 goto error;;
00120 }
00121
00122 vd->framesizeIn = (vd->width * vd->height << 1);
00123 switch (vd->formatIn) {
00124 case V4L2_PIX_FMT_MJPEG:
00125 vd->tmpbuffer =
00126 (unsigned char *) calloc(1, (size_t) vd->framesizeIn);
00127 if (!vd->tmpbuffer)
00128 goto error;
00129 vd->framebuffer =
00130 (unsigned char *) calloc(1,
00131 (size_t) vd->width * (vd->height +
00132 8) * 2);
00133 break;
00134 case V4L2_PIX_FMT_YUYV:
00135 vd->framebuffer =
00136 (unsigned char *) calloc(1, (size_t) vd->framesizeIn);
00137 break;
00138 default:
00139 printf(" should never arrive exit fatal !!\n");
00140 goto error;
00141 break;
00142 }
00143 if (!vd->framebuffer)
00144 goto error;
00145 return 0;
00146 error:
00147 free(vd->videodevice);
00148 free(vd->status);
00149 free(vd->pictName);
00150 close(vd->fd);
00151 return -1;
00152 }
00153 int enum_controls(int vd)
00154 {
00155 struct v4l2_queryctrl queryctrl;
00156 struct v4l2_querymenu querymenu;
00157 struct v4l2_control control_s;
00158 struct v4l2_input* getinput;
00159
00160
00161 getinput=(struct v4l2_input *) calloc(1, sizeof(struct v4l2_input));
00162 memset(getinput, 0, sizeof(struct v4l2_input));
00163 getinput->index=0;
00164 ioctl(vd,VIDIOC_ENUMINPUT , getinput);
00165 printf ("Available controls of device '%s' (Type 1=Integer 2=Boolean 3=Menu 4=Button)\n", getinput->name);
00166
00167
00168 void enumerate_menu (void) {
00169 printf (" Menu items:\n");
00170 memset (&querymenu, 0, sizeof (querymenu));
00171 querymenu.id = queryctrl.id;
00172 for (querymenu.index = queryctrl.minimum;
00173 querymenu.index <= queryctrl.maximum;
00174 querymenu.index++) {
00175 if (0 == ioctl (vd, VIDIOC_QUERYMENU, &querymenu)) {
00176 printf (" index:%d name:%s\n", querymenu.index, querymenu.name);
00177
00178 } else {
00179 printf ("error getting control menu");
00180 break;
00181 }
00182 }
00183 }
00184
00185
00186 printf ("V4L2_CID_BASE (predefined controls):\n");
00187 memset (&queryctrl, 0, sizeof (queryctrl));
00188 for (queryctrl.id = V4L2_CID_BASE;
00189 queryctrl.id < V4L2_CID_LASTP1;
00190 queryctrl.id++) {
00191 if (0 == ioctl (vd, VIDIOC_QUERYCTRL, &queryctrl)) {
00192 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00193 continue;
00194 control_s.id=queryctrl.id;
00195 ioctl(vd, VIDIOC_G_CTRL, &control_s);
00196
00197 printf (" index:%-10d name:%-32s type:%d min:%-5d max:%-5d step:%-5d def:%-5d now:%d\n",
00198 queryctrl.id, queryctrl.name, queryctrl.type, queryctrl.minimum,
00199 queryctrl.maximum, queryctrl.step, queryctrl.default_value, control_s.value);
00200 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
00201 enumerate_menu ();
00202 } else {
00203 if (errno == EINVAL)
00204 continue;
00205 perror ("error getting base controls");
00206 goto fatal_controls;
00207 }
00208 }
00209
00210
00211 printf ("V4L2_CID_PRIVATE_BASE (driver specific controls):\n");
00212 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
00213 queryctrl.id++) {
00214 if (0 == ioctl (vd, VIDIOC_QUERYCTRL, &queryctrl)) {
00215 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00216 continue;
00217 control_s.id=queryctrl.id;
00218 ioctl(vd, VIDIOC_G_CTRL, &control_s);
00219
00220 printf (" index:%-10d name:%-32s type:%d min:%-5d max:%-5d step:%-5d def:%-5d now:%d\n",
00221 queryctrl.id, queryctrl.name, queryctrl.type, queryctrl.minimum,
00222 queryctrl.maximum, queryctrl.step, queryctrl.default_value, control_s.value);
00223 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
00224 enumerate_menu ();
00225 } else {
00226 if (errno == EINVAL)
00227 break;
00228 perror ("error getting private base controls");
00229 goto fatal_controls;
00230 }
00231 }
00232 return 0;
00233 fatal_controls:
00234 return -1;
00235 }
00236 int save_controls(int vd)
00237 {
00238 struct v4l2_queryctrl queryctrl;
00239 struct v4l2_control control_s;
00240 FILE *configfile;
00241 memset (&queryctrl, 0, sizeof (queryctrl));
00242 memset (&control_s, 0, sizeof (control_s));
00243 configfile = fopen("luvcview.cfg", "w");
00244 if ( configfile == NULL) {
00245 perror("saving configfile luvcview.cfg failed");
00246 }
00247 else {
00248 fprintf(configfile, "id value # luvcview control settings configuration file\n");
00249 for (queryctrl.id = V4L2_CID_BASE;
00250 queryctrl.id < V4L2_CID_LASTP1;
00251 queryctrl.id++) {
00252 if (0 == ioctl (vd, VIDIOC_QUERYCTRL, &queryctrl)) {
00253 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00254 continue;
00255 control_s.id=queryctrl.id;
00256 ioctl(vd, VIDIOC_G_CTRL, &control_s);
00257
00258 fprintf (configfile, "%-10d %-10d # name:%-32s type:%d min:%-5d max:%-5d step:%-5d def:%d\n",
00259 queryctrl.id, control_s.value, queryctrl.name, queryctrl.type, queryctrl.minimum,
00260 queryctrl.maximum, queryctrl.step, queryctrl.default_value);
00261 printf ("%-10d %-10d # name:%-32s type:%d min:%-5d max:%-5d step:%-5d def:%d\n",
00262 queryctrl.id, control_s.value, queryctrl.name, queryctrl.type, queryctrl.minimum,
00263 queryctrl.maximum, queryctrl.step, queryctrl.default_value);
00264
00265 }
00266 }
00267 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
00268 queryctrl.id++) {
00269 if (0 == ioctl (vd, VIDIOC_QUERYCTRL, &queryctrl)) {
00270 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00271 continue;
00272 if ((queryctrl.id==134217735) || (queryctrl.id==134217736))
00273 continue;
00274 control_s.id=queryctrl.id;
00275 ioctl(vd, VIDIOC_G_CTRL, &control_s);
00276
00277 fprintf (configfile, "%-10d %-10d # name:%-32s type:%d min:%-5d max:%-5d step:%-5d def:%d\n",
00278 queryctrl.id, control_s.value, queryctrl.name, queryctrl.type, queryctrl.minimum,
00279 queryctrl.maximum, queryctrl.step, queryctrl.default_value);
00280 printf ("%-10d %-10d # name:%-32s type:%d min:%-5d max:%-5d step:%-5d def:%d\n",
00281 queryctrl.id, control_s.value, queryctrl.name, queryctrl.type, queryctrl.minimum,
00282 queryctrl.maximum, queryctrl.step, queryctrl.default_value);
00283 } else {
00284 if (errno == EINVAL)
00285 break;
00286 }
00287 }
00288 fflush(configfile);
00289 fclose(configfile);
00290
00291 }
00292 }
00293
00294
00295 int load_controls(int vd)
00296 {
00297 struct v4l2_control control;
00298 FILE *configfile;
00299 memset (&control, 0, sizeof (control));
00300 configfile = fopen("luvcview.cfg", "r");
00301 if ( configfile == NULL) {
00302 perror("configfile luvcview.cfg open failed");
00303 }
00304 else {
00305 printf("loading controls from luvcview.cfg\n");
00306 char buffer[512];
00307 fgets(buffer, sizeof(buffer), configfile);
00308 while (NULL !=fgets(buffer, sizeof(buffer), configfile) )
00309 {
00310 sscanf(buffer, "%i%i", &control.id, &control.value);
00311 if (ioctl(vd, VIDIOC_S_CTRL, &control))
00312 printf("ERROR id:%d val:%d\n", control.id, control.value);
00313 else
00314 printf("OK id:%d val:%d\n", control.id, control.value);
00315
00316 }
00317 fclose(configfile);
00318 }
00319 }
00320
00321 static int init_v4l2(struct vdIn *vd)
00322 {
00323 int i;
00324 int ret = 0;
00325
00326 if ((vd->fd = open(vd->videodevice, O_RDWR)) == -1) {
00327 perror("ERROR opening V4L interface");
00328 return -1;
00329 }
00330 memset(&vd->cap, 0, sizeof(struct v4l2_capability));
00331 ret = ioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap);
00332 if (ret < 0) {
00333 printf("Error opening device %s: unable to query device.\n",
00334 vd->videodevice);
00335 goto fatal;
00336 }
00337
00338 if ((vd->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
00339 printf("Error opening device %s: video capture not supported.\n",
00340 vd->videodevice);
00341 goto fatal;;
00342 }
00343 if (vd->grabmethod) {
00344 if (!(vd->cap.capabilities & V4L2_CAP_STREAMING)) {
00345 printf("%s does not support streaming i/o\n", vd->videodevice);
00346 goto fatal;
00347 }
00348 } else {
00349 if (!(vd->cap.capabilities & V4L2_CAP_READWRITE)) {
00350 printf("%s does not support read i/o\n", vd->videodevice);
00351 goto fatal;
00352 }
00353 }
00354
00355 printf("Stream settings:\n");
00356
00357
00358
00359 unsigned int device_formats[16] = { 0 };
00360 int requested_format_found = 0, fallback_format = -1;
00361 if(enum_frame_formats(vd->fd, device_formats, ARRAY_SIZE(device_formats))) {
00362 printf("Unable to enumerate frame formats");
00363 goto fatal;
00364 }
00365 for(i = 0; i < ARRAY_SIZE(device_formats) && device_formats[i]; i++) {
00366 if(device_formats[i] == vd->formatIn) {
00367 requested_format_found = 1;
00368 break;
00369 }
00370 if(device_formats[i] == V4L2_PIX_FMT_MJPEG || device_formats[i] == V4L2_PIX_FMT_YUYV)
00371 fallback_format = i;
00372 }
00373 if(requested_format_found) {
00374
00375 printf(" Frame format: "FOURCC_FORMAT"\n", FOURCC_ARGS(vd->formatIn));
00376 }
00377 else if(fallback_format >= 0) {
00378
00379 printf(" Frame format: "FOURCC_FORMAT" ("FOURCC_FORMAT
00380 " is not supported by device)\n",
00381 FOURCC_ARGS(device_formats[0]), FOURCC_ARGS(vd->formatIn));
00382 vd->formatIn = device_formats[0];
00383 }
00384 else {
00385
00386 printf("ERROR: Requested frame format "FOURCC_FORMAT" is not available "
00387 "and no fallback format was found.\n", FOURCC_ARGS(vd->formatIn));
00388 goto fatal;
00389 }
00390
00391
00392 memset(&vd->fmt, 0, sizeof(struct v4l2_format));
00393 vd->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00394 vd->fmt.fmt.pix.width = vd->width;
00395 vd->fmt.fmt.pix.height = vd->height;
00396 vd->fmt.fmt.pix.pixelformat = vd->formatIn;
00397 vd->fmt.fmt.pix.field = V4L2_FIELD_ANY;
00398 ret = ioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt);
00399 if (ret < 0) {
00400 perror("Unable to set format");
00401 goto fatal;
00402 }
00403 if ((vd->fmt.fmt.pix.width != vd->width) ||
00404 (vd->fmt.fmt.pix.height != vd->height)) {
00405 printf(" Frame size: %ux%u (requested size %ux%u is not supported by device)\n",
00406 vd->fmt.fmt.pix.width, vd->fmt.fmt.pix.height, vd->width, vd->height);
00407 vd->width = vd->fmt.fmt.pix.width;
00408 vd->height = vd->fmt.fmt.pix.height;
00409
00410
00411 }
00412 else {
00413 printf(" Frame size: %dx%d\n", vd->width, vd->height);
00414 }
00415
00416
00417 struct v4l2_streamparm* setfps;
00418 setfps=(struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
00419 memset(setfps, 0, sizeof(struct v4l2_streamparm));
00420 setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00421 setfps->parm.capture.timeperframe.numerator=1;
00422 setfps->parm.capture.timeperframe.denominator=vd->fps;
00423 ret = ioctl(vd->fd, VIDIOC_S_PARM, setfps);
00424 if(ret == -1) {
00425 perror("Unable to set frame rate");
00426 goto fatal;
00427 }
00428 ret = ioctl(vd->fd, VIDIOC_G_PARM, setfps);
00429 if(ret == 0) {
00430 if (setfps->parm.capture.timeperframe.numerator != 1 ||
00431 setfps->parm.capture.timeperframe.denominator != vd->fps) {
00432 printf(" Frame rate: %u/%u fps (requested frame rate %u fps is "
00433 "not supported by device)\n",
00434 setfps->parm.capture.timeperframe.denominator,
00435 setfps->parm.capture.timeperframe.numerator,
00436 vd->fps);
00437 }
00438 else {
00439 printf(" Frame rate: %d fps\n", vd->fps);
00440 }
00441 }
00442 else {
00443 perror("Unable to read out current frame rate");
00444 goto fatal;
00445 }
00446
00447
00448 memset(&vd->rb, 0, sizeof(struct v4l2_requestbuffers));
00449 vd->rb.count = NB_BUFFER;
00450 vd->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00451 vd->rb.memory = V4L2_MEMORY_MMAP;
00452
00453 ret = ioctl(vd->fd, VIDIOC_REQBUFS, &vd->rb);
00454 if (ret < 0) {
00455 perror("Unable to allocate buffers");
00456 goto fatal;
00457 }
00458
00459 for (i = 0; i < NB_BUFFER; i++) {
00460 memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
00461 vd->buf.index = i;
00462 vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00463 vd->buf.memory = V4L2_MEMORY_MMAP;
00464 ret = ioctl(vd->fd, VIDIOC_QUERYBUF, &vd->buf);
00465 if (ret < 0) {
00466 perror("Unable to query buffer");
00467 goto fatal;
00468 }
00469 if (debug)
00470 printf("length: %u offset: %u\n", vd->buf.length,
00471 vd->buf.m.offset);
00472 vd->mem[i] = mmap(0 ,
00473 vd->buf.length, PROT_READ, MAP_SHARED, vd->fd,
00474 vd->buf.m.offset);
00475 if (vd->mem[i] == MAP_FAILED) {
00476 perror("Unable to map buffer");
00477 goto fatal;
00478 }
00479 if (debug)
00480 printf("Buffer mapped at address %p.\n", vd->mem[i]);
00481 }
00482
00483 for (i = 0; i < NB_BUFFER; ++i) {
00484 memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
00485 vd->buf.index = i;
00486 vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00487 vd->buf.memory = V4L2_MEMORY_MMAP;
00488 ret = ioctl(vd->fd, VIDIOC_QBUF, &vd->buf);
00489 if (ret < 0) {
00490 perror("Unable to queue buffer");
00491 goto fatal;;
00492 }
00493 }
00494 return 0;
00495 fatal:
00496 return -1;
00497
00498 }
00499
00500 static int video_enable(struct vdIn *vd)
00501 {
00502 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00503 int ret;
00504
00505 ret = ioctl(vd->fd, VIDIOC_STREAMON, &type);
00506 if (ret < 0) {
00507 perror("Unable to start capture");
00508 return ret;
00509 }
00510 vd->isstreaming = 1;
00511 return 0;
00512 }
00513
00514 static int video_disable(struct vdIn *vd)
00515 {
00516 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00517 int ret;
00518
00519 ret = ioctl(vd->fd, VIDIOC_STREAMOFF, &type);
00520 if (ret < 0) {
00521 perror("Unable to stop capture");
00522 return ret;
00523 }
00524 vd->isstreaming = 0;
00525 return 0;
00526 }
00527
00528
00529 int uvcGrab(struct vdIn *vd)
00530 {
00531 #define HEADERFRAME1 0xaf
00532 int ret;
00533
00534 if (!vd->isstreaming)
00535 if (video_enable(vd))
00536 goto err;
00537 memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
00538 vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00539 vd->buf.memory = V4L2_MEMORY_MMAP;
00540 ret = ioctl(vd->fd, VIDIOC_DQBUF, &vd->buf);
00541 if (ret < 0) {
00542 perror("Unable to dequeue buffer");
00543 goto err;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 switch (vd->formatIn) {
00606 case V4L2_PIX_FMT_MJPEG:
00607 if(vd->buf.bytesused <= HEADERFRAME1) {
00608
00609 printf("Ignoring empty buffer ...\n");
00610 return 0;
00611 }
00612 memcpy(vd->tmpbuffer, vd->mem[vd->buf.index],vd->buf.bytesused);
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 if (jpeg_decode(&vd->framebuffer, vd->tmpbuffer, &vd->width,
00637 &vd->height) < 0) {
00638 printf("jpeg decode errors\n");
00639 goto err;
00640 }
00641 if (debug)
00642 printf("bytes in used %d\n", vd->buf.bytesused);
00643 break;
00644 case V4L2_PIX_FMT_YUYV:
00645 if (vd->buf.bytesused > vd->framesizeIn)
00646 memcpy(vd->framebuffer, vd->mem[vd->buf.index],
00647 (size_t) vd->framesizeIn);
00648 else
00649 memcpy(vd->framebuffer, vd->mem[vd->buf.index],
00650 (size_t) vd->buf.bytesused);
00651 break;
00652 default:
00653 goto err;
00654 break;
00655 }
00656 ret = ioctl(vd->fd, VIDIOC_QBUF, &vd->buf);
00657 if (ret < 0) {
00658 perror("Unable to requeue buffer");
00659 goto err;
00660 }
00661
00662 return 0;
00663 err:
00664 vd->signalquit = 0;
00665 return -1;
00666 }
00667 int close_v4l2(struct vdIn *vd)
00668 {
00669 if (vd->isstreaming)
00670 video_disable(vd);
00671 if (vd->tmpbuffer)
00672 free(vd->tmpbuffer);
00673 vd->tmpbuffer = NULL;
00674 free(vd->framebuffer);
00675 vd->framebuffer = NULL;
00676 free(vd->videodevice);
00677 free(vd->status);
00678 free(vd->pictName);
00679 vd->videodevice = NULL;
00680 vd->status = NULL;
00681 vd->pictName = NULL;
00682 }
00683
00684
00685 static int isv4l2Control(struct vdIn *vd, int control,
00686 struct v4l2_queryctrl *queryctrl)
00687 {
00688 int err =0;
00689 queryctrl->id = control;
00690 if ((err= ioctl(vd->fd, VIDIOC_QUERYCTRL, queryctrl)) < 0) {
00691 perror("ioctl querycontrol error");
00692 } else if (queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) {
00693 printf("control %s disabled\n", (char *) queryctrl->name);
00694 } else if (queryctrl->flags & V4L2_CTRL_TYPE_BOOLEAN) {
00695 return 1;
00696 } else if (queryctrl->type & V4L2_CTRL_TYPE_INTEGER) {
00697 return 0;
00698 } else {
00699 printf("contol %s unsupported\n", (char *) queryctrl->name);
00700 }
00701 return -1;
00702 }
00703
00704 int v4l2GetControl(struct vdIn *vd, int control)
00705 {
00706 struct v4l2_queryctrl queryctrl;
00707 struct v4l2_control control_s;
00708 int err;
00709 if (isv4l2Control(vd, control, &queryctrl) < 0)
00710 return -1;
00711 control_s.id = control;
00712 if ((err = ioctl(vd->fd, VIDIOC_G_CTRL, &control_s)) < 0) {
00713 printf("ioctl get control error\n");
00714 return -1;
00715 }
00716 return control_s.value;
00717 }
00718
00719 int v4l2SetControl(struct vdIn *vd, int control, int value)
00720 {
00721 struct v4l2_control control_s;
00722 struct v4l2_queryctrl queryctrl;
00723 int min, max, step, val_def;
00724 int err;
00725 if (isv4l2Control(vd, control, &queryctrl) < 0)
00726 return -1;
00727 min = queryctrl.minimum;
00728 max = queryctrl.maximum;
00729 step = queryctrl.step;
00730 val_def = queryctrl.default_value;
00731 if ((value >= min) && (value <= max)) {
00732 control_s.id = control;
00733 control_s.value = value;
00734 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00735 printf("ioctl set control error\n");
00736 return -1;
00737 }
00738 }
00739 return 0;
00740 }
00741 int v4l2UpControl(struct vdIn *vd, int control)
00742 {
00743 struct v4l2_control control_s;
00744 struct v4l2_queryctrl queryctrl;
00745 int min, max, current, step, val_def;
00746 int err;
00747
00748 if (isv4l2Control(vd, control, &queryctrl) < 0)
00749 return -1;
00750 min = queryctrl.minimum;
00751 max = queryctrl.maximum;
00752 step = queryctrl.step;
00753 val_def = queryctrl.default_value;
00754 current = v4l2GetControl(vd, control);
00755 current += step;
00756 printf("max %d, min %d, step %d, default %d ,current %d\n",max,min,step,val_def,current);
00757 if (current <= max) {
00758 control_s.id = control;
00759 control_s.value = current;
00760 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00761 printf("ioctl set control error\n");
00762 return -1;
00763 }
00764 printf ("Control name:%s set to value:%d\n", queryctrl.name, control_s.value);
00765 } else {
00766 printf ("Control name:%s already has max value:%d\n", queryctrl.name, max);
00767 }
00768 return control_s.value;
00769 }
00770 int v4l2DownControl(struct vdIn *vd, int control)
00771 {
00772 struct v4l2_control control_s;
00773 struct v4l2_queryctrl queryctrl;
00774 int min, max, current, step, val_def;
00775 int err;
00776 if (isv4l2Control(vd, control, &queryctrl) < 0)
00777 return -1;
00778 min = queryctrl.minimum;
00779 max = queryctrl.maximum;
00780 step = queryctrl.step;
00781 val_def = queryctrl.default_value;
00782 current = v4l2GetControl(vd, control);
00783 current -= step;
00784 printf("max %d, min %d, step %d, default %d ,current %d\n",max,min,step,val_def,current);
00785 if (current >= min) {
00786 control_s.id = control;
00787 control_s.value = current;
00788 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00789 printf("ioctl set control error\n");
00790 return -1;
00791 }
00792 printf ("Control name:%s set to value:%d\n", queryctrl.name, control_s.value);
00793 }
00794 else {
00795 printf ("Control name:%s already has min value:%d\n", queryctrl.name, min);
00796 }
00797 return control_s.value;
00798 }
00799 int v4l2ToggleControl(struct vdIn *vd, int control)
00800 {
00801 struct v4l2_control control_s;
00802 struct v4l2_queryctrl queryctrl;
00803 int current;
00804 int err;
00805 if (isv4l2Control(vd, control, &queryctrl) != 1)
00806 return -1;
00807 current = v4l2GetControl(vd, control);
00808 control_s.id = control;
00809 control_s.value = !current;
00810 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00811 printf("ioctl toggle control error\n");
00812 return -1;
00813 }
00814 return control_s.value;
00815 }
00816 int v4l2ResetControl(struct vdIn *vd, int control)
00817 {
00818 struct v4l2_control control_s;
00819 struct v4l2_queryctrl queryctrl;
00820 int val_def;
00821 int err;
00822 if (isv4l2Control(vd, control, &queryctrl) < 0)
00823 return -1;
00824 val_def = queryctrl.default_value;
00825 control_s.id = control;
00826 control_s.value = val_def;
00827 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00828 printf("ioctl reset control error\n");
00829 return -1;
00830 }
00831
00832 return 0;
00833 }
00834
00835 int v4l2ResetPan(struct vdIn *vd)
00836 {
00837 int control = V4L2_CID_PAN_RESET;
00838 struct v4l2_control control_s;
00839 struct v4l2_queryctrl queryctrl;
00840 int err;
00841
00842 if (isv4l2Control(vd, control, &queryctrl) < 0)
00843 return -1;
00844
00845 control_s.id = control;
00846 control_s.value = 1;
00847 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00848 printf("ERROR: Unable to reset pan (error = %d)\n", errno);
00849 return -1;
00850 }
00851
00852 return 0;
00853 }
00854
00855 int v4l2ResetTilt(struct vdIn *vd)
00856 {
00857 int control = V4L2_CID_TILT_RESET;
00858 struct v4l2_control control_s;
00859 struct v4l2_queryctrl queryctrl;
00860 int err;
00861
00862 if (isv4l2Control(vd, control, &queryctrl) < 0)
00863 return -1;
00864
00865 control_s.id = control;
00866 control_s.value = 1;
00867 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00868 printf("ERROR: Unable to reset tilt (error = %d)\n", errno);
00869 return -1;
00870 }
00871
00872 return 0;
00873 }
00874
00875 int v4l2ResetPanTilt(struct vdIn *vd)
00876 {
00877 int control = V4L2_CID_PANTILT_RESET;
00878 struct v4l2_control control_s;
00879 struct v4l2_queryctrl queryctrl;
00880 unsigned char val;
00881 int err;
00882
00883 if (isv4l2Control(vd, control, &queryctrl) < 0)
00884 return -1;
00885
00886 control_s.id = control;
00887 control_s.value = 3;
00888 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00889 printf("ERROR: Unable to reset pan/tilt (error = %d)\n", errno);
00890 return -1;
00891 }
00892
00893 return 0;
00894 }
00895
00896 int v4L2UpDownPan(struct vdIn *vd, short inc)
00897 {
00898 int control = V4L2_CID_PAN_RELATIVE;
00899 struct v4l2_control control_s;
00900 struct v4l2_queryctrl queryctrl;
00901 int err;
00902
00903 if (isv4l2Control(vd, control, &queryctrl) < 0)
00904 return -1;
00905 control_s.id = control;
00906 control_s.value = inc;
00907 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00908 printf("ioctl pan updown control error\n");
00909 return -1;
00910 }
00911 return 0;
00912 }
00913
00914 int v4L2UpDownTilt(struct vdIn *vd, short inc)
00915 { int control = V4L2_CID_TILT_RELATIVE;
00916 struct v4l2_control control_s;
00917 struct v4l2_queryctrl queryctrl;
00918 int err;
00919
00920 if (isv4l2Control(vd, control, &queryctrl) < 0)
00921 return -1;
00922 control_s.id = control;
00923 control_s.value = inc;
00924 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00925 printf("ioctl tiltupdown control error\n");
00926 return -1;
00927 }
00928 return 0;
00929 }
00930
00931 int v4L2UpDownPanTilt(struct vdIn *vd, short inc_p, short inc_t) {
00932 int p_control = V4L2_CID_PAN_RELATIVE;
00933 int t_control = V4L2_CID_TILT_RELATIVE;
00934 struct v4l2_ext_controls control_s_array;
00935 struct v4l2_queryctrl queryctrl;
00936 struct v4l2_ext_control control_s[2];
00937 int err;
00938
00939 if(isv4l2Control(vd, p_control, &queryctrl) < 0 ||
00940 isv4l2Control(vd, t_control, &queryctrl) < 0)
00941 return -1;
00942 control_s_array.count = 2;
00943 control_s_array.ctrl_class = V4L2_CTRL_CLASS_USER;
00944 control_s_array.reserved[0] = 0;
00945 control_s_array.reserved[1] = 0;
00946 control_s_array.controls = control_s;
00947
00948 control_s[0].id = p_control;
00949 control_s[0].value = inc_p;
00950 control_s[1].id = t_control;
00951 control_s[1].value = inc_t;
00952
00953 if ((err = ioctl(vd->fd, VIDIOC_S_EXT_CTRLS, &control_s_array)) < 0) {
00954 printf("ioctl pan-tilt updown control error\n");
00955 return -1;
00956 }
00957 return 0;
00958 }
00959
00960 #if 0
00961
00962 union pantilt {
00963 struct {
00964 short pan;
00965 short tilt;
00966 } s16;
00967 int value;
00968 } __attribute__((packed)) ;
00969
00970 int v4L2UpDownPan(struct vdIn *vd, short inc)
00971 { int control = V4L2_CID_PANTILT_RELATIVE;
00972 struct v4l2_control control_s;
00973 struct v4l2_queryctrl queryctrl;
00974 int err;
00975
00976 union pantilt pan;
00977
00978 control_s.id = control;
00979 if (isv4l2Control(vd, control, &queryctrl) < 0)
00980 return -1;
00981
00982 pan.s16.pan = inc;
00983 pan.s16.tilt = 0;
00984
00985 control_s.value = pan.value ;
00986 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
00987 printf("ioctl pan updown control error\n");
00988 return -1;
00989 }
00990 return 0;
00991 }
00992
00993 int v4L2UpDownTilt(struct vdIn *vd, short inc)
00994 { int control = V4L2_CID_PANTILT_RELATIVE;
00995 struct v4l2_control control_s;
00996 struct v4l2_queryctrl queryctrl;
00997 int err;
00998 union pantilt pan;
00999 control_s.id = control;
01000 if (isv4l2Control(vd, control, &queryctrl) < 0)
01001 return -1;
01002
01003 pan.s16.pan= 0;
01004 pan.s16.tilt = inc;
01005
01006 control_s.value = pan.value;
01007 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
01008 printf("ioctl tiltupdown control error\n");
01009 return -1;
01010 }
01011 return 0;
01012 }
01013 #endif
01014
01015 int v4l2SetLightFrequencyFilter(struct vdIn *vd, int flt)
01016 { int control = V4L2_CID_POWER_LINE_FREQUENCY;
01017 struct v4l2_control control_s;
01018 struct v4l2_queryctrl queryctrl;
01019 int err;
01020 control_s.id = control;
01021 if (isv4l2Control(vd, control, &queryctrl) < 0)
01022 return -1;
01023
01024 control_s.value = flt;
01025
01026 if ((err = ioctl(vd->fd, VIDIOC_S_CTRL, &control_s)) < 0) {
01027 printf("ioctl set_light_frequency_filter error\n");
01028 return -1;
01029 }
01030 return 0;
01031 }
01032 int enum_frame_intervals(int dev, __u32 pixfmt, __u32 width, __u32 height)
01033 {
01034 int ret;
01035 struct v4l2_frmivalenum fival;
01036
01037 memset(&fival, 0, sizeof(fival));
01038 fival.index = 0;
01039 fival.pixel_format = pixfmt;
01040 fival.width = width;
01041 fival.height = height;
01042 printf("\tTime interval between frame: ");
01043 while ((ret = ioctl(dev, VIDIOC_ENUM_FRAMEINTERVALS, &fival)) == 0) {
01044 if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
01045 printf("%u/%u, ",
01046 fival.discrete.numerator, fival.discrete.denominator);
01047 } else if (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
01048 printf("{min { %u/%u } .. max { %u/%u } }, ",
01049 fival.stepwise.min.numerator, fival.stepwise.min.numerator,
01050 fival.stepwise.max.denominator, fival.stepwise.max.denominator);
01051 break;
01052 } else if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
01053 printf("{min { %u/%u } .. max { %u/%u } / "
01054 "stepsize { %u/%u } }, ",
01055 fival.stepwise.min.numerator, fival.stepwise.min.denominator,
01056 fival.stepwise.max.numerator, fival.stepwise.max.denominator,
01057 fival.stepwise.step.numerator, fival.stepwise.step.denominator);
01058 break;
01059 }
01060 fival.index++;
01061 }
01062 printf("\n");
01063 if (ret != 0 && errno != EINVAL) {
01064 perror("ERROR enumerating frame intervals");
01065 return errno;
01066 }
01067
01068 return 0;
01069 }
01070 int enum_frame_sizes(int dev, __u32 pixfmt)
01071 {
01072 int ret;
01073 struct v4l2_frmsizeenum fsize;
01074
01075 memset(&fsize, 0, sizeof(fsize));
01076 fsize.index = 0;
01077 fsize.pixel_format = pixfmt;
01078 while ((ret = ioctl(dev, VIDIOC_ENUM_FRAMESIZES, &fsize)) == 0) {
01079 if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
01080 printf("{ discrete: width = %u, height = %u }\n",
01081 fsize.discrete.width, fsize.discrete.height);
01082 ret = enum_frame_intervals(dev, pixfmt,
01083 fsize.discrete.width, fsize.discrete.height);
01084 if (ret != 0)
01085 printf(" Unable to enumerate frame sizes.\n");
01086 } else if (fsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
01087 printf("{ continuous: min { width = %u, height = %u } .. "
01088 "max { width = %u, height = %u } }\n",
01089 fsize.stepwise.min_width, fsize.stepwise.min_height,
01090 fsize.stepwise.max_width, fsize.stepwise.max_height);
01091 printf(" Refusing to enumerate frame intervals.\n");
01092 break;
01093 } else if (fsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
01094 printf("{ stepwise: min { width = %u, height = %u } .. "
01095 "max { width = %u, height = %u } / "
01096 "stepsize { width = %u, height = %u } }\n",
01097 fsize.stepwise.min_width, fsize.stepwise.min_height,
01098 fsize.stepwise.max_width, fsize.stepwise.max_height,
01099 fsize.stepwise.step_width, fsize.stepwise.step_height);
01100 printf(" Refusing to enumerate frame intervals.\n");
01101 break;
01102 }
01103 fsize.index++;
01104 }
01105 if (ret != 0 && errno != EINVAL) {
01106 perror("ERROR enumerating frame sizes");
01107 return errno;
01108 }
01109
01110 return 0;
01111 }
01112
01113 int enum_frame_formats(int dev, unsigned int *supported_formats, unsigned int max_formats)
01114 {
01115 int ret;
01116 struct v4l2_fmtdesc fmt;
01117
01118 memset(&fmt, 0, sizeof(fmt));
01119 fmt.index = 0;
01120 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
01121 while ((ret = ioctl(dev, VIDIOC_ENUM_FMT, &fmt)) == 0) {
01122 if(supported_formats == NULL) {
01123 printf("{ pixelformat = '%c%c%c%c', description = '%s' }\n",
01124 fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF,
01125 (fmt.pixelformat >> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF,
01126 fmt.description);
01127 ret = enum_frame_sizes(dev, fmt.pixelformat);
01128 if(ret != 0)
01129 printf(" Unable to enumerate frame sizes.\n");
01130 }
01131 else if(fmt.index < max_formats) {
01132 supported_formats[fmt.index] = fmt.pixelformat;
01133 }
01134
01135 fmt.index++;
01136 }
01137 if (errno != EINVAL) {
01138 perror("ERROR enumerating frame formats");
01139 return errno;
01140 }
01141
01142 return 0;
01143 }