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 }