usb_cam.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2009, Robert Bosch LLC.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Robert Bosch nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *********************************************************************/
00036 #define __STDC_CONSTANT_MACROS
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <assert.h>
00041 #include <fcntl.h>              /* low-level i/o */
00042 #include <unistd.h>
00043 #include <errno.h>
00044 #include <malloc.h>
00045 #include <sys/stat.h>
00046 #include <sys/types.h>
00047 #include <sys/time.h>
00048 #include <sys/mman.h>
00049 #include <sys/ioctl.h>
00050 
00051 #include <asm/types.h>          /* for videodev2.h */
00052 
00053 extern "C" {
00054 #include <linux/videodev2.h>
00055 #include <libavcodec/avcodec.h>
00056 #include <libswscale/swscale.h>
00057 }
00058 
00059 #include <usb_cam/usb_cam.h>
00060 
00061 #define CLEAR(x) memset (&(x), 0, sizeof (x))
00062 
00063 struct buffer {
00064   void * start;
00065   size_t length;
00066 };
00067 
00068 static char *camera_dev;
00069 static unsigned int pixelformat;
00070 static usb_cam_io_method io = IO_METHOD_MMAP;
00071 static int fd = -1;
00072 struct buffer * buffers = NULL;
00073 static unsigned int n_buffers = 0;
00074 static AVFrame *avframe_camera = NULL;
00075 static AVFrame *avframe_rgb = NULL;
00076 static AVCodec *avcodec = NULL;
00077 static AVCodecContext *avcodec_context = NULL;
00078 static int avframe_camera_size = 0;
00079 static int avframe_rgb_size = 0;
00080 
00081 struct SwsContext *video_sws = NULL;
00082 
00083 static void errno_exit(const char * s)
00084 {
00085   fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
00086 
00087   exit(EXIT_FAILURE);
00088 }
00089 
00090 static int xioctl(int fd, int request, void * arg)
00091 {
00092   int r;
00093 
00094   do
00095     r = ioctl(fd, request, arg); while (-1==r&&EINTR==errno);
00096 
00097   return r;
00098 }
00099 
00100 const unsigned char uchar_clipping_table[] = {
00101   0,0,0,0,0,0,0,0, // -128 - -121
00102   0,0,0,0,0,0,0,0, // -120 - -113
00103   0,0,0,0,0,0,0,0, // -112 - -105
00104   0,0,0,0,0,0,0,0, // -104 -  -97
00105   0,0,0,0,0,0,0,0, //  -96 -  -89
00106   0,0,0,0,0,0,0,0, //  -88 -  -81
00107   0,0,0,0,0,0,0,0, //  -80 -  -73
00108   0,0,0,0,0,0,0,0, //  -72 -  -65
00109   0,0,0,0,0,0,0,0, //  -64 -  -57
00110   0,0,0,0,0,0,0,0, //  -56 -  -49
00111   0,0,0,0,0,0,0,0, //  -48 -  -41
00112   0,0,0,0,0,0,0,0, //  -40 -  -33
00113   0,0,0,0,0,0,0,0, //  -32 -  -25
00114   0,0,0,0,0,0,0,0, //  -24 -  -17
00115   0,0,0,0,0,0,0,0, //  -16 -   -9
00116   0,0,0,0,0,0,0,0, //   -8 -   -1
00117   0,1,2,3,4,5,6,7,
00118   8,9,10,11,12,13,14,15,
00119   16,17,18,19,20,21,22,23,
00120   24,25,26,27,28,29,30,31,
00121   32,33,34,35,36,37,38,39,
00122   40,41,42,43,44,45,46,47,
00123   48,49,50,51,52,53,54,55,
00124   56,57,58,59,60,61,62,63,
00125   64,65,66,67,68,69,70,71,
00126   72,73,74,75,76,77,78,79,
00127   80,81,82,83,84,85,86,87,
00128   88,89,90,91,92,93,94,95,
00129   96,97,98,99,100,101,102,103,
00130   104,105,106,107,108,109,110,111,
00131   112,113,114,115,116,117,118,119,
00132   120,121,122,123,124,125,126,127,
00133   128,129,130,131,132,133,134,135,
00134   136,137,138,139,140,141,142,143,
00135   144,145,146,147,148,149,150,151,
00136   152,153,154,155,156,157,158,159,
00137   160,161,162,163,164,165,166,167,
00138   168,169,170,171,172,173,174,175,
00139   176,177,178,179,180,181,182,183,
00140   184,185,186,187,188,189,190,191,
00141   192,193,194,195,196,197,198,199,
00142   200,201,202,203,204,205,206,207,
00143   208,209,210,211,212,213,214,215,
00144   216,217,218,219,220,221,222,223,
00145   224,225,226,227,228,229,230,231,
00146   232,233,234,235,236,237,238,239,
00147   240,241,242,243,244,245,246,247,
00148   248,249,250,251,252,253,254,255,
00149   255,255,255,255,255,255,255,255, // 256-263
00150   255,255,255,255,255,255,255,255, // 264-271
00151   255,255,255,255,255,255,255,255, // 272-279
00152   255,255,255,255,255,255,255,255, // 280-287
00153   255,255,255,255,255,255,255,255, // 288-295
00154   255,255,255,255,255,255,255,255, // 296-303
00155   255,255,255,255,255,255,255,255, // 304-311
00156   255,255,255,255,255,255,255,255, // 312-319
00157   255,255,255,255,255,255,255,255, // 320-327
00158   255,255,255,255,255,255,255,255, // 328-335
00159   255,255,255,255,255,255,255,255, // 336-343
00160   255,255,255,255,255,255,255,255, // 344-351
00161   255,255,255,255,255,255,255,255, // 352-359
00162   255,255,255,255,255,255,255,255, // 360-367
00163   255,255,255,255,255,255,255,255, // 368-375
00164   255,255,255,255,255,255,255,255, // 376-383
00165 };
00166 const int clipping_table_offset = 128;
00167 
00171 static unsigned char
00172 CLIPVALUE(int val)
00173 {
00174   // Old method (if)
00175 /*   val = val < 0 ? 0 : val; */
00176 /*   return val > 255 ? 255 : val; */
00177 
00178   // New method (array)
00179   return uchar_clipping_table[val+clipping_table_offset];
00180 }
00181 
00203 static void
00204 YUV2RGB(const unsigned char y,
00205         const unsigned char u,
00206         const unsigned char v,
00207         unsigned char* r,
00208         unsigned char* g,
00209         unsigned char* b)
00210 {
00211   const int y2=(int)y;
00212   const int u2=(int)u-128;
00213   const int v2=(int)v-128;
00214   //std::cerr << "YUV=("<<y2<<","<<u2<<","<<v2<<")"<<std::endl;
00215 
00216 
00217   // This is the normal YUV conversion, but
00218   // appears to be incorrect for the firewire cameras
00219   //   int r2 = y2 + ( (v2*91947) >> 16);
00220   //   int g2 = y2 - ( ((u2*22544) + (v2*46793)) >> 16 );
00221   //   int b2 = y2 + ( (u2*115999) >> 16);
00222   // This is an adjusted version (UV spread out a bit)
00223   int r2 = y2 + ( (v2*37221) >> 15);
00224   int g2 = y2 - ( ((u2*12975) + (v2*18949)) >> 15 );
00225   int b2 = y2 + ( (u2*66883) >> 15);
00226   //std::cerr << "   RGB=("<<r2<<","<<g2<<","<<b2<<")"<<std::endl;
00227 
00228 
00229   // Cap the values.
00230   *r=CLIPVALUE(r2);
00231   *g=CLIPVALUE(g2);
00232   *b=CLIPVALUE(b2);
00233 }
00234 
00235 void
00236 uyvy2rgb (char *YUV, char *RGB, int NumPixels) {
00237   int i, j;
00238   unsigned char y0, y1, u, v;
00239   unsigned char r, g, b;
00240   for (i = 0, j = 0; i < (NumPixels << 1); i += 4, j += 6)
00241     {
00242       u = (unsigned char) YUV[i + 0];
00243       y0 = (unsigned char) YUV[i + 1];
00244       v = (unsigned char) YUV[i + 2];
00245       y1 = (unsigned char) YUV[i + 3];
00246       YUV2RGB (y0, u, v, &r, &g, &b);
00247       RGB[j + 0] = r;
00248       RGB[j + 1] = g;
00249       RGB[j + 2] = b;
00250       YUV2RGB (y1, u, v, &r, &g, &b);
00251       RGB[j + 3] = r;
00252       RGB[j + 4] = g;
00253       RGB[j + 5] = b;
00254     }
00255 }
00256 
00257 static void
00258 yuyv2rgb(char *YUV, char *RGB, int NumPixels) {
00259   int i, j;
00260   unsigned char y0, y1, u, v;
00261   unsigned char r, g, b;
00262 
00263   for (i = 0, j = 0; i < (NumPixels << 1); i += 4, j += 6)
00264     {
00265       y0 = (unsigned char) YUV[i + 0];
00266       u = (unsigned char) YUV[i + 1];
00267       y1 = (unsigned char) YUV[i + 2];
00268       v = (unsigned char) YUV[i + 3];
00269       YUV2RGB (y0, u, v, &r, &g, &b);
00270       RGB[j + 0] = r;
00271       RGB[j + 1] = g;
00272       RGB[j + 2] = b;
00273       YUV2RGB (y1, u, v, &r, &g, &b);
00274       RGB[j + 3] = r;
00275       RGB[j + 4] = g;
00276       RGB[j + 5] = b;
00277     }
00278 }
00279 
00280 static int init_mjpeg_decoder(int image_width, int image_height)
00281 {
00282   avcodec_init();
00283   avcodec_register_all();
00284 
00285   avcodec = avcodec_find_decoder(CODEC_ID_MJPEG);
00286   if (!avcodec)
00287   {
00288     fprintf(stderr,"Could not find MJPEG decoder\n");
00289     return 0;
00290   }
00291 
00292   avcodec_context = avcodec_alloc_context();
00293   avframe_camera = avcodec_alloc_frame();
00294   avframe_rgb = avcodec_alloc_frame();
00295 
00296   avpicture_alloc((AVPicture *)avframe_rgb, PIX_FMT_RGB24, image_width, image_height);
00297 
00298   avcodec_context->codec_id = CODEC_ID_MJPEG;
00299   avcodec_context->width = image_width;
00300   avcodec_context->height = image_height;
00301 
00302 #if LIBAVCODEC_VERSION_MAJOR > 52
00303   avcodec_context->pix_fmt = PIX_FMT_YUV422P;
00304   avcodec_context->codec_type = AVMEDIA_TYPE_VIDEO;
00305 #endif
00306 
00307   avframe_camera_size = avpicture_get_size(PIX_FMT_YUV422P, image_width, image_height);
00308   avframe_rgb_size = avpicture_get_size(PIX_FMT_RGB24, image_width, image_height);
00309 
00310   /* open it */
00311   if (avcodec_open(avcodec_context, avcodec) < 0)
00312   {
00313     fprintf(stderr,"Could not open MJPEG Decoder\n");
00314     return 0;
00315   }
00316   return 1;
00317 }
00318 
00319 static void
00320 mjpeg2rgb(char *MJPEG, int len, char *RGB, int NumPixels)
00321 {
00322   int got_picture;
00323 
00324   memset(RGB, 0, avframe_rgb_size);
00325 
00326 #if LIBAVCODEC_VERSION_MAJOR > 52
00327   int decoded_len;
00328   AVPacket avpkt;
00329   av_init_packet(&avpkt);
00330   
00331   avpkt.size = len;
00332   avpkt.data = (unsigned char*)MJPEG;
00333   decoded_len = avcodec_decode_video2(avcodec_context, avframe_camera, &got_picture, &avpkt);
00334 
00335   if (decoded_len < 0) {
00336       fprintf(stderr, "Error while decoding frame.\n");
00337       return;
00338   }
00339 #else
00340   avcodec_decode_video(avcodec_context, avframe_camera, &got_picture, (uint8_t *) MJPEG, len);
00341 #endif
00342 
00343   if (!got_picture) {
00344     fprintf(stderr,"Webcam: expected picture but didn't get it...\n");
00345     return;
00346   }
00347 
00348   int xsize = avcodec_context->width;
00349   int ysize = avcodec_context->height;
00350   int pic_size = avpicture_get_size(avcodec_context->pix_fmt, xsize, ysize);
00351   if (pic_size != avframe_camera_size) {
00352     fprintf(stderr,"outbuf size mismatch.  pic_size: %d bufsize: %d\n",pic_size,avframe_camera_size);
00353     return;
00354   }
00355 
00356   video_sws = sws_getContext( xsize, ysize, avcodec_context->pix_fmt, xsize, ysize, PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
00357   sws_scale(video_sws, avframe_camera->data, avframe_camera->linesize, 0, ysize, avframe_rgb->data, avframe_rgb->linesize );
00358   sws_freeContext(video_sws);  
00359 
00360   int size = avpicture_layout((AVPicture *) avframe_rgb, PIX_FMT_RGB24, xsize, ysize, (uint8_t *)RGB, avframe_rgb_size);
00361   if (size != avframe_rgb_size) {
00362     fprintf(stderr,"webcam: avpicture_layout error: %d\n",size);
00363     return;
00364   }
00365 }
00366 
00367 static void process_image(const void * src, int len, usb_cam_camera_image_t *dest)
00368 {
00369   if(pixelformat==V4L2_PIX_FMT_YUYV)
00370     yuyv2rgb((char*)src, dest->image, dest->width*dest->height);
00371   else if(pixelformat==V4L2_PIX_FMT_UYVY)
00372     uyvy2rgb((char*)src, dest->image, dest->width*dest->height);
00373   else if(pixelformat==V4L2_PIX_FMT_MJPEG)
00374     mjpeg2rgb((char*)src, len, dest->image, dest->width*dest->height);
00375 }
00376 
00377 static int read_frame(usb_cam_camera_image_t *image)
00378 {
00379   struct v4l2_buffer buf;
00380   unsigned int i;
00381   int len;
00382 
00383   switch (io) {
00384   case IO_METHOD_READ:
00385     len = read(fd, buffers[0].start, buffers[0].length);
00386     if (len==-1) {
00387       switch (errno) {
00388       case EAGAIN:
00389         return 0;
00390 
00391       case EIO:
00392         /* Could ignore EIO, see spec. */
00393 
00394         /* fall through */
00395 
00396       default:
00397         errno_exit("read");
00398       }
00399     }
00400 
00401     process_image(buffers[0].start, len, image);
00402 
00403     break;
00404 
00405   case IO_METHOD_MMAP:
00406     CLEAR (buf);
00407 
00408     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00409     buf.memory = V4L2_MEMORY_MMAP;
00410 
00411     if (-1==xioctl(fd, VIDIOC_DQBUF, &buf)) {
00412       switch (errno) {
00413       case EAGAIN:
00414         return 0;
00415 
00416       case EIO:
00417         /* Could ignore EIO, see spec. */
00418 
00419         /* fall through */
00420 
00421       default:
00422         errno_exit("VIDIOC_DQBUF");
00423       }
00424     }
00425 
00426     assert (buf.index < n_buffers);
00427     len = buf.bytesused;
00428     process_image(buffers[buf.index].start, len, image);
00429 
00430     if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00431       errno_exit("VIDIOC_QBUF");
00432 
00433     break;
00434 
00435   case IO_METHOD_USERPTR:
00436     CLEAR (buf);
00437 
00438     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00439     buf.memory = V4L2_MEMORY_USERPTR;
00440 
00441     if (-1==xioctl(fd, VIDIOC_DQBUF, &buf)) {
00442       switch (errno) {
00443       case EAGAIN:
00444         return 0;
00445 
00446       case EIO:
00447         /* Could ignore EIO, see spec. */
00448 
00449         /* fall through */
00450 
00451       default:
00452         errno_exit("VIDIOC_DQBUF");
00453       }
00454     }
00455 
00456     for(i = 0; i<n_buffers; ++i)
00457       if (buf.m.userptr==(unsigned long) buffers[i].start&&buf.length==buffers[i].length)
00458         break;
00459 
00460     assert (i < n_buffers);
00461     len = buf.bytesused;
00462     process_image((void *) buf.m.userptr, len, image);
00463 
00464     if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00465       errno_exit("VIDIOC_QBUF");
00466 
00467     break;
00468   }
00469 
00470   return 1;
00471 }
00472 
00473 static void stop_capturing(void)
00474 {
00475   enum v4l2_buf_type type;
00476 
00477   switch (io) {
00478   case IO_METHOD_READ:
00479     /* Nothing to do. */
00480     break;
00481 
00482   case IO_METHOD_MMAP:
00483   case IO_METHOD_USERPTR:
00484     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00485 
00486     if (-1==xioctl(fd, VIDIOC_STREAMOFF, &type))
00487       errno_exit("VIDIOC_STREAMOFF");
00488 
00489     break;
00490   }
00491 }
00492 
00493 static void start_capturing(void)
00494 {
00495   unsigned int i;
00496   enum v4l2_buf_type type;
00497 
00498   switch (io) {
00499   case IO_METHOD_READ:
00500     /* Nothing to do. */
00501     break;
00502 
00503   case IO_METHOD_MMAP:
00504     for(i = 0; i<n_buffers; ++i) {
00505       struct v4l2_buffer buf;
00506 
00507       CLEAR (buf);
00508 
00509       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00510       buf.memory = V4L2_MEMORY_MMAP;
00511       buf.index = i;
00512 
00513       if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00514         errno_exit("VIDIOC_QBUF");
00515     }
00516 
00517     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00518 
00519     if (-1==xioctl(fd, VIDIOC_STREAMON, &type))
00520       errno_exit("VIDIOC_STREAMON");
00521 
00522     break;
00523 
00524   case IO_METHOD_USERPTR:
00525     for(i = 0; i<n_buffers; ++i) {
00526       struct v4l2_buffer buf;
00527 
00528       CLEAR (buf);
00529 
00530       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00531       buf.memory = V4L2_MEMORY_USERPTR;
00532       buf.index = i;
00533       buf.m.userptr = (unsigned long) buffers[i].start;
00534       buf.length = buffers[i].length;
00535 
00536       if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00537         errno_exit("VIDIOC_QBUF");
00538     }
00539 
00540     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00541 
00542     if (-1==xioctl(fd, VIDIOC_STREAMON, &type))
00543       errno_exit("VIDIOC_STREAMON");
00544 
00545     break;
00546   }
00547 }
00548 
00549 static void uninit_device(void)
00550 {
00551   unsigned int i;
00552 
00553   switch (io) {
00554   case IO_METHOD_READ:
00555     free(buffers[0].start);
00556     break;
00557 
00558   case IO_METHOD_MMAP:
00559     for(i = 0; i<n_buffers; ++i)
00560       if (-1==munmap(buffers[i].start, buffers[i].length))
00561         errno_exit("munmap");
00562     break;
00563 
00564   case IO_METHOD_USERPTR:
00565     for(i = 0; i<n_buffers; ++i)
00566       free(buffers[i].start);
00567     break;
00568   }
00569 
00570   free(buffers);
00571 }
00572 
00573 static void init_read(unsigned int buffer_size)
00574 {
00575   buffers = (buffer*)calloc(1, sizeof(*buffers));
00576 
00577   if (!buffers) {
00578     fprintf(stderr, "Out of memory\n");
00579     exit(EXIT_FAILURE);
00580   }
00581 
00582   buffers[0].length = buffer_size;
00583   buffers[0].start = malloc(buffer_size);
00584 
00585   if (!buffers[0].start) {
00586     fprintf(stderr, "Out of memory\n");
00587     exit(EXIT_FAILURE);
00588   }
00589 }
00590 
00591 static void init_mmap(void)
00592 {
00593   struct v4l2_requestbuffers req;
00594 
00595   CLEAR (req);
00596 
00597   req.count = 4;
00598   req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00599   req.memory = V4L2_MEMORY_MMAP;
00600 
00601   if (-1==xioctl(fd, VIDIOC_REQBUFS, &req)) {
00602     if (EINVAL==errno) {
00603       fprintf(stderr, "%s does not support memory mapping\n", camera_dev);
00604       exit(EXIT_FAILURE);
00605     } else {
00606       errno_exit("VIDIOC_REQBUFS");
00607     }
00608   }
00609 
00610   if (req.count<2) {
00611     fprintf(stderr, "Insufficient buffer memory on %s\n", camera_dev);
00612     exit(EXIT_FAILURE);
00613   }
00614 
00615   buffers = (buffer*)calloc(req.count, sizeof(*buffers));
00616 
00617   if (!buffers) {
00618     fprintf(stderr, "Out of memory\n");
00619     exit(EXIT_FAILURE);
00620   }
00621 
00622   for(n_buffers = 0; n_buffers<req.count; ++n_buffers) {
00623     struct v4l2_buffer buf;
00624 
00625     CLEAR (buf);
00626 
00627     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00628     buf.memory = V4L2_MEMORY_MMAP;
00629     buf.index = n_buffers;
00630 
00631     if (-1==xioctl(fd, VIDIOC_QUERYBUF, &buf))
00632       errno_exit("VIDIOC_QUERYBUF");
00633 
00634     buffers[n_buffers].length = buf.length;
00635     buffers[n_buffers].start = mmap(NULL /* start anywhere */, buf.length, PROT_READ|PROT_WRITE /* required */, MAP_SHARED /* recommended */, fd, buf.m.offset);
00636 
00637     if (MAP_FAILED==buffers[n_buffers].start)
00638       errno_exit("mmap");
00639   }
00640 }
00641 
00642 static void init_userp(unsigned int buffer_size)
00643 {
00644   struct v4l2_requestbuffers req;
00645   unsigned int page_size;
00646 
00647   page_size = getpagesize();
00648   buffer_size = (buffer_size+page_size-1)&~(page_size-1);
00649 
00650   CLEAR (req);
00651 
00652   req.count = 4;
00653   req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00654   req.memory = V4L2_MEMORY_USERPTR;
00655 
00656   if (-1==xioctl(fd, VIDIOC_REQBUFS, &req)) {
00657     if (EINVAL==errno) {
00658       fprintf(stderr, "%s does not support "
00659         "user pointer i/o\n", camera_dev);
00660       exit(EXIT_FAILURE);
00661     } else {
00662       errno_exit("VIDIOC_REQBUFS");
00663     }
00664   }
00665 
00666   buffers = (buffer*)calloc(4, sizeof(*buffers));
00667 
00668   if (!buffers) {
00669     fprintf(stderr, "Out of memory\n");
00670     exit(EXIT_FAILURE);
00671   }
00672 
00673   for(n_buffers = 0; n_buffers<4; ++n_buffers) {
00674     buffers[n_buffers].length = buffer_size;
00675     buffers[n_buffers].start = memalign(/* boundary */page_size, buffer_size);
00676 
00677     if (!buffers[n_buffers].start) {
00678       fprintf(stderr, "Out of memory\n");
00679       exit(EXIT_FAILURE);
00680     }
00681   }
00682 }
00683 
00684 static void init_device(int image_width, int image_height)
00685 {
00686   struct v4l2_capability cap;
00687   struct v4l2_cropcap cropcap;
00688   struct v4l2_crop crop;
00689   struct v4l2_format fmt;
00690   unsigned int min;
00691 
00692   if (-1==xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
00693     if (EINVAL==errno) {
00694       fprintf(stderr, "%s is no V4L2 device\n", camera_dev);
00695       exit(EXIT_FAILURE);
00696     } else {
00697       errno_exit("VIDIOC_QUERYCAP");
00698     }
00699   }
00700 
00701   if (!(cap.capabilities&V4L2_CAP_VIDEO_CAPTURE)) {
00702     fprintf(stderr, "%s is no video capture device\n", camera_dev);
00703     exit(EXIT_FAILURE);
00704   }
00705 
00706   switch (io) {
00707   case IO_METHOD_READ:
00708     if (!(cap.capabilities&V4L2_CAP_READWRITE)) {
00709       fprintf(stderr, "%s does not support read i/o\n", camera_dev);
00710       exit(EXIT_FAILURE);
00711     }
00712 
00713     break;
00714 
00715   case IO_METHOD_MMAP:
00716   case IO_METHOD_USERPTR:
00717     if (!(cap.capabilities&V4L2_CAP_STREAMING)) {
00718       fprintf(stderr, "%s does not support streaming i/o\n", camera_dev);
00719       exit(EXIT_FAILURE);
00720     }
00721 
00722     break;
00723   }
00724 
00725   /* Select video input, video standard and tune here. */
00726 
00727   CLEAR (cropcap);
00728 
00729   cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00730 
00731   if (0==xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
00732     crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00733     crop.c = cropcap.defrect; /* reset to default */
00734 
00735     if (-1==xioctl(fd, VIDIOC_S_CROP, &crop)) {
00736       switch (errno) {
00737       case EINVAL:
00738         /* Cropping not supported. */
00739         break;
00740       default:
00741         /* Errors ignored. */
00742         break;
00743       }
00744     }
00745   } else {
00746     /* Errors ignored. */
00747   }
00748 
00749   CLEAR (fmt);
00750 
00751 //  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00752 //  fmt.fmt.pix.width = 640;
00753 //  fmt.fmt.pix.height = 480;
00754 //  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
00755 //  fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00756 
00757   fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00758   fmt.fmt.pix.width = image_width;
00759   fmt.fmt.pix.height = image_height;
00760   fmt.fmt.pix.pixelformat = pixelformat;
00761   fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00762 
00763 
00764   if (-1==xioctl(fd, VIDIOC_S_FMT, &fmt))
00765     errno_exit("VIDIOC_S_FMT");
00766 
00767   /* Note VIDIOC_S_FMT may change width and height. */
00768 
00769   /* Buggy driver paranoia. */
00770   min = fmt.fmt.pix.width*2;
00771   if (fmt.fmt.pix.bytesperline<min)
00772     fmt.fmt.pix.bytesperline = min;
00773   min = fmt.fmt.pix.bytesperline*fmt.fmt.pix.height;
00774   if (fmt.fmt.pix.sizeimage<min)
00775     fmt.fmt.pix.sizeimage = min;
00776 
00777   image_width = fmt.fmt.pix.width;
00778   image_height = fmt.fmt.pix.height;
00779 
00780   switch (io) {
00781   case IO_METHOD_READ:
00782     init_read(fmt.fmt.pix.sizeimage);
00783     break;
00784 
00785   case IO_METHOD_MMAP:
00786     init_mmap();
00787     break;
00788 
00789   case IO_METHOD_USERPTR:
00790     init_userp(fmt.fmt.pix.sizeimage);
00791     break;
00792   }
00793 }
00794 
00795 static void close_device(void)
00796 {
00797   if (-1==close(fd))
00798     errno_exit("close");
00799 
00800   fd = -1;
00801 }
00802 
00803 static void open_device(void)
00804 {
00805   struct stat st;
00806 
00807   if (-1==stat(camera_dev, &st)) {
00808     fprintf(stderr, "Cannot identify '%s': %d, %s\n", camera_dev, errno, strerror(errno));
00809     exit(EXIT_FAILURE);
00810   }
00811 
00812   if (!S_ISCHR (st.st_mode)) {
00813     fprintf(stderr, "%s is no device\n", camera_dev);
00814     exit(EXIT_FAILURE);
00815   }
00816 
00817   fd = open(camera_dev, O_RDWR /* required */|O_NONBLOCK, 0);
00818 
00819   if (-1==fd) {
00820     fprintf(stderr, "Cannot open '%s': %d, %s\n", camera_dev, errno, strerror(errno));
00821     exit(EXIT_FAILURE);
00822   }
00823 }
00824 
00825 usb_cam_camera_image_t *usb_cam_camera_start(const char* dev, usb_cam_io_method io_method,
00826     usb_cam_pixel_format pixel_format, int image_width, int image_height)
00827 {
00828   camera_dev = (char*)calloc(1,strlen(dev)+1);
00829   strcpy(camera_dev,dev);
00830 
00831   usb_cam_camera_image_t *image;
00832   io = io_method;
00833   if(pixel_format == PIXEL_FORMAT_YUYV)
00834     pixelformat = V4L2_PIX_FMT_YUYV;
00835   else if(pixel_format == PIXEL_FORMAT_UYVY)
00836     pixelformat = V4L2_PIX_FMT_UYVY;
00837   else if(pixel_format == PIXEL_FORMAT_MJPEG) {
00838     pixelformat = V4L2_PIX_FMT_MJPEG;
00839     init_mjpeg_decoder(image_width, image_height);
00840   }
00841   else {
00842     fprintf(stderr, "Unknown pixelformat.\n");
00843     exit(EXIT_FAILURE);
00844   }
00845 
00846   open_device();
00847   init_device(image_width, image_height);
00848   start_capturing();
00849 
00850   image = (usb_cam_camera_image_t *) calloc(1, sizeof(usb_cam_camera_image_t));
00851 
00852   image->width = image_width;
00853   image->height = image_height;
00854   image->bytes_per_pixel = 24;
00855 
00856   image->image_size = image->width*image->height*image->bytes_per_pixel;
00857   image->is_new = 0;
00858   image->image = (char *) calloc(image->image_size, sizeof(char));
00859   memset(image->image, 0, image->image_size*sizeof(char));
00860 
00861   return image;
00862 }
00863 
00864 void usb_cam_camera_shutdown(void)
00865 {
00866   stop_capturing();
00867   uninit_device();
00868   close_device();
00869 
00870   if (avcodec_context) {
00871     avcodec_close(avcodec_context);
00872     av_free(avcodec_context);
00873     avcodec_context = NULL;
00874   }
00875   if (avframe_camera)
00876     av_free(avframe_camera);
00877   avframe_camera = NULL;
00878   if (avframe_rgb)
00879     av_free(avframe_rgb);
00880   avframe_rgb = NULL;
00881 }
00882 
00883 void usb_cam_camera_grab_image(usb_cam_camera_image_t *image)
00884 {
00885   fd_set fds;
00886   struct timeval tv;
00887   int r;
00888 
00889   FD_ZERO (&fds);
00890   FD_SET (fd, &fds);
00891 
00892   /* Timeout. */
00893   tv.tv_sec = 5;
00894   tv.tv_usec = 0;
00895 
00896   r = select(fd+1, &fds, NULL, NULL, &tv);
00897 
00898   if (-1==r) {
00899     if (EINTR==errno)
00900       return;
00901 
00902     errno_exit("select");
00903   }
00904 
00905   if (0==r) {
00906     fprintf(stderr, "select timeout\n");
00907     exit(EXIT_FAILURE);
00908   }
00909 
00910   read_frame(image);
00911   image->is_new = 1;
00912 }
00913 
00914 // enables/disables auto focus
00915 void usb_cam_camera_set_auto_focus(int value)
00916 {
00917   struct v4l2_queryctrl queryctrl;
00918   struct v4l2_ext_control control;
00919 
00920   memset(&queryctrl, 0, sizeof(queryctrl));
00921   queryctrl.id = V4L2_CID_FOCUS_AUTO;
00922 
00923   if (-1 == xioctl(fd, VIDIOC_QUERYCTRL, &queryctrl)) {
00924     if (errno != EINVAL) {
00925       perror("VIDIOC_QUERYCTRL");
00926       return;
00927     } else {
00928       printf("V4L2_CID_FOCUS_AUTO is not supported\n");
00929       return;
00930     }
00931   } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
00932     printf("V4L2_CID_FOCUS_AUTO is not supported\n");
00933     return;
00934   } else {
00935     memset(&control, 0, sizeof(control));
00936     control.id = V4L2_CID_FOCUS_AUTO;
00937     control.value = value;
00938 
00939     if (-1 == xioctl(fd, VIDIOC_S_CTRL, &control)) {
00940       perror("VIDIOC_S_CTRL");
00941       return;
00942     }
00943   }
00944 }
00945 
00946 
00947 


usb_cam
Author(s): Benjamin Pitzer
autogenerated on Mon Oct 6 2014 10:09:47