v4l2uvc.c

00001 /*******************************************************************************
00002 #                 uvcview: Sdl video Usb Video Class grabber           .         #
00003 #This package work with the Logitech UVC based webcams with the mjpeg feature. #
00004 #All the decoding is in user space with the embedded jpeg decoder              #
00005 #.                                                                             #
00006 #                 Copyright (C) 2005 2006 Laurent Pinchart &&  Michel Xhaard     #
00007 #                                                                              #
00008 # This program is free software; you can redistribute it and/or modify         #
00009 # it under the terms of the GNU General Public License as published by         #
00010 # the Free Software Foundation; either version 2 of the License, or            #
00011 # (at your option) any later version.                                          #
00012 #                                                                              #
00013 # This program is distributed in the hope that it will be useful,              #
00014 # but WITHOUT ANY WARRANTY; without even the implied warranty of               #
00015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
00016 # GNU General Public License for more details.                                 #
00017 #                                                                              #
00018 # You should have received a copy of the GNU General Public License            #
00019 # along with this program; if not, write to the Free Software                  #
00020 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    #
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;                //mmap by default;
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     /* alloc a temp buffer to reconstruct the pict */
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) //struct vdIn *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   //Name of the device
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   //subroutine to read menu items of controls with type 3
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         //SDL_Delay(10);
00178       } else {
00179         printf ("error getting control menu");
00180         break;
00181       }
00182     }
00183   }
00184 
00185   //predefined controls
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       //SDL_Delay(10);
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   //driver specific controls
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       //SDL_Delay(20);
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         //SDL_Delay(10);
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         //SDL_Delay(10);
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         //SDL_Delay(10);
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     //SDL_Delay(100);
00291   }
00292 }
00293 
00294 
00295 int load_controls(int vd) //struct vdIn *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         //SDL_Delay(20);
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         // Enumerate the supported formats to check whether the requested one
00358         // is available. If not, we try to fall back to YUYV.
00359         unsigned int device_formats[16] = { 0 };        // Assume no device supports more than 16 formats
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                 // The requested format is supported
00375                 printf("  Frame format: "FOURCC_FORMAT"\n", FOURCC_ARGS(vd->formatIn));
00376         }
00377         else if(fallback_format >= 0) {
00378                 // The requested format is not supported but there's a fallback format
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                 // The requested format is not supported and no fallback format is available
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         // Set pixel format and frame size
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                 /* look the format is not part of the deal ??? */
00410                 //vd->formatIn = vd->fmt.fmt.pix.pixelformat;
00411         }
00412         else {
00413                 printf("  Frame size:   %dx%d\n", vd->width, vd->height);
00414         }
00415 
00416         /* set framerate */
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         /* request buffers */
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         /* map the buffers */
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 /* start anywhere */ ,
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         /* Queue the buffers. */
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         ///* Capture a single raw frame */
00548         //if (vd->rawFrameCapture && vd->buf.bytesused > 0) {
00549         //        FILE *frame = NULL;
00550         //        char filename[13];
00551         //        int ret;
00552 
00553         //        /* Disable frame capturing unless we're in frame stream mode */
00554         //        if(vd->rawFrameCapture == 1)
00555         //                vd->rawFrameCapture = 0;
00556 
00557         //        /* Create a file name and open the file */
00558         //        sprintf(filename, "frame%03u.raw", vd->fileCounter++ % 1000);
00559         //        frame = fopen(filename, "wb");
00560         //        if(frame == NULL) {
00561         //                perror("Unable to open file for raw frame capturing");
00562         //                goto end_capture;
00563         //        }
00564         //
00565         //        /* Write the raw data to the file */
00566         //        ret = fwrite(vd->mem[vd->buf.index], vd->buf.bytesused, 1, frame);
00567         //        if(ret < 1) {
00568         //                perror("Unable to write to file");
00569         //                goto end_capture;
00570         //        }
00571         //        printf("Saved raw frame to %s (%u bytes)\n", filename, vd->buf.bytesused);
00572         //        if(vd->rawFrameCapture == 2) {
00573         //                vd->rfsBytesWritten += vd->buf.bytesused;
00574         //                vd->rfsFramesWritten++;
00575         //        }
00576 
00577 
00578         //        /* Clean up */
00579   //end_capture:
00580         //        if(frame)
00581         //                fclose(frame);
00582         //}
00583 
00584 
00585 
00586         /* Capture raw stream data */
00587         //if (vd->captureFile && vd->buf.bytesused > 0) {
00588         //        int ret;
00589         //        ret = fwrite(vd->mem[vd->buf.index], vd->buf.bytesused, 1, vd->captureFile);
00590         //        if (ret < 1) {
00591         //                perror("Unable to write raw stream to file");
00592         //                fprintf(stderr, "Stream capturing terminated.\n");
00593         //                fclose(vd->captureFile);
00594         //                vd->captureFile = NULL;
00595         //                vd->framesWritten = 0;
00596         //                vd->bytesWritten = 0;
00597         //        } else {
00598         //                vd->framesWritten++;
00599         //                vd->bytesWritten += vd->buf.bytesused;
00600         //                if (debug)
00601         //                        printf("Appended raw frame to stream file (%u bytes)\n", vd->buf.bytesused);
00602         //        }
00603         //}
00604 
00605     switch (vd->formatIn) {
00606       case V4L2_PIX_FMT_MJPEG:
00607         if(vd->buf.bytesused <= HEADERFRAME1) {        /* Prevent crash on empty image */
00608           /*            if(debug)*/
00609           printf("Ignoring empty buffer ...\n");
00610           return 0;
00611         }
00612         memcpy(vd->tmpbuffer, vd->mem[vd->buf.index],vd->buf.bytesused);
00613         /* avi recording is toggled on */
00614         //if (vd->toggleAvi) {
00615         //  /* if vd->avifile is NULL, then we need to initialize it */
00616         //  if (vd->avifile == NULL) {
00617         //    //vd->avifile = AVI_open_output_file(vd->avifilename);
00618 
00619         //    /* if avifile is NULL, there was an error */
00620         //    if (vd->avifile == NULL ) {
00621         //      fprintf(stderr,"Error opening avifile %s\n",vd->avifilename);
00622         //    }
00623         //    else {
00624         //      /* we default the fps to 15, we'll reset it on close */
00625         //      //AVI_set_video(vd->avifile, vd->width, vd->height,
00626         //      //    15, "MJPG");
00627         //      printf("recording to %s\n",vd->avifilename);
00628         //    }
00629         //  } else {
00630         //    /* if we have a valid avifile, record the frame to it */
00631         //    // AVI_write_frame(vd->avifile, vd->tmpbuffer,
00632         //    //     vd->buf.bytesused, vd->framecount);
00633         //    vd->framecount++;
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 /* return >= 0 ok otherwhise -1 */
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 }
Generated on Sun May 8 08:05:42 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3