video.cpp
Go to the documentation of this file.
00001 
00005 #include "video.hpp"
00006 
00007 void streamerSource::initialize_video_source() {
00008 
00009         bImgFormat = PIX_FMT_YUYV422; // original: PIX_FMT_YUVJ420P, then tried PIX_FMT_YUV420P
00010         bQuality = 3;
00011         //int fFrame = 0;
00012         video_sws = NULL;
00013         
00014         ixInputStream = -1;
00015         io = IO_METHOD_MMAP; //IO_METHOD_MMAP;
00016         fd = -1;
00017         buffers = NULL;
00018         n_buffers = 0;
00019         avframe_camera = NULL;
00020         avframe_rgb = NULL;
00021         avcodec = NULL;
00022         avcodec_context = NULL;
00023         avframe_camera_size = 0;
00024         avframe_rgb_size = 0;
00025         image = (usb_cam_camera_image_t *) calloc(1, sizeof(usb_cam_camera_image_t));
00026 
00027         /***** FFMPEG AVI Initialization *****/
00028         av_init_packet(&packet);
00029         av_register_all();
00030 
00031 };
00032 
00033 int streamerSource::close_video_file(std::string filename) {
00034     // Free the RGB image
00035     av_free(buffer);
00036     av_free(pFrameRGB);
00037 
00038     // Free the YUV frame
00039     av_free(pFrame);
00040 
00041     // Close the codec
00042     avcodec_close(pCodecCtx);
00043 
00044     // Close the video file
00045     av_close_input_file(pIFormatCtx);
00046     
00047     return 0;
00048 }
00049 
00050 
00051 int streamerSource::setup_video_file(std::string filename) {
00052         
00053         //return 0;
00054         
00055         printf("%s << Trying to set up file...\n", __FUNCTION__);
00056         av_register_all();
00057         // Open video file
00058         
00059         pIFormatCtx = NULL;
00060         // AVInputFormat *avIF = av_find_input_format("video4linux2");
00061         
00062         #ifdef __CONFIG_0__ // Steve's config
00063                 //pFormatCtx = NULL;
00064                 int err = avformat_open_input (&pIFormatCtx, filename.c_str(), NULL, NULL);     
00065         #endif
00066         
00067         #ifdef __CONFIG_1__ // Hajmi's config
00068                 int err = (av_open_input_file(&pIFormatCtx, filename.c_str(), NULL, 0, NULL) != 0);
00069         #endif
00070         
00071         if (err != 0) {
00072                 //if (av_open_input_file(&pFormatCtx, filename.c_str(), NULL, 0, NULL) != 0) {
00073                         
00074                         
00075                         if (err == ENOMEM) {
00076                                 printf("%s << Error = ENOMEM\n", __FUNCTION__);
00077                         } else if (err == EINVAL) {
00078                                 printf("%s << Error = EINVAL\n", __FUNCTION__);
00079                         } else {
00080                                 printf("%s << Error = (%d)\n", __FUNCTION__, err);
00081                         }
00082                         
00083                         //printf("%s << Couldn't open file (%s)...\n", __FUNCTION__, filename.c_str());
00084                         
00085                         return -1; // Couldn't open file
00086                 }
00087         
00088         
00089 
00090     // Retrieve stream information
00091     if (av_find_stream_info(pIFormatCtx) < 0) {
00092         printf("%s << Couldn't find stream info...\n", __FUNCTION__);
00093         return -1; // Couldn't find stream information
00094         }
00095 
00096         #ifdef __CONFIG_0__ // Steve's config
00097             // Dump information about file onto standard error
00098                 av_dump_format(pIFormatCtx, 0, filename.c_str(), 0);    
00099         #endif
00100 
00101 
00102     // Find the first video stream
00103     videoStream = -1;
00104     for (i = 0; i < pIFormatCtx->nb_streams; i++)
00105         if (pIFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
00106         {
00107             videoStream = i;
00108             break;
00109         }
00110     if (videoStream == -1) {
00111         printf("%s << Didn't find video stream...\n", __FUNCTION__);
00112         return -1; // Didn't find a video stream
00113         }
00114 
00115     // Get a pointer to the codec context for the video stream
00116     pCodecCtx = pIFormatCtx->streams[videoStream]->codec;
00117 
00118     // Find the decoder for the video stream
00119     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
00120     if (pCodec == NULL)
00121     {
00122         fprintf(stderr, "Unsupported codec!\n");
00123         return -1; // Codec not found
00124     }
00125     // Open codec
00126     if (avcodec_open(pCodecCtx, pCodec) < 0) {
00127         printf("%s << Couldn't open codec...\n", __FUNCTION__);
00128         return -1; // Could not open codec
00129         }
00130 
00131     // Allocate video frame
00132     pFrame = avcodec_alloc_frame();
00133 
00134     // Allocate an AVFrame structure
00135     pFrameRGB = avcodec_alloc_frame();
00136     if (pFrameRGB == NULL) {
00137         printf("%s << Couldn't allocate frame...\n", __FUNCTION__);
00138         return -1;
00139         }
00140 
00141     // Determine required buffer size and allocate buffer
00142     numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
00143             pCodecCtx->height);
00144     buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
00145 
00146     // Assign appropriate parts of buffer to image planes in pFrameRGB
00147     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
00148     // of AVPicture
00149     avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB24,
00150             pCodecCtx->width, pCodecCtx->height);
00151             
00152         return 0;
00153 }
00154 
00155 void streamerSource::close_video_capture() {
00156         
00157         //avformat_close_input (&pIFormatCtx);
00158         av_close_input_file(pIFormatCtx);
00159         
00160 }
00161 
00162 int streamerSource::setup_video_capture(std::string devicename, int& deviceWidth, int& deviceHeight, bool verbose) {
00163 
00164         if (verbose) { printf("%s << Registering (1)...\n", __FUNCTION__); }
00165         av_register_all();
00166         if (verbose) { printf("%s << Registering (2)...\n", __FUNCTION__); }
00167         avdevice_register_all();
00168         
00169         //avformat_alloc_context();
00170 
00171 // Open video stream
00172         if (verbose) { printf("%s << Finding format...\n", __FUNCTION__); }
00173     pIFormat = av_find_input_format("video4linux2");
00174     pIFormatCtx = NULL;
00175     
00176     
00177     
00178     if (verbose) { printf("%s << Opening format...\n", __FUNCTION__); }
00179     #ifdef __CONFIG_0__ // Steve's config
00180                 int err = avformat_open_input (&pIFormatCtx, devicename.c_str(), pIFormat, NULL);
00181                 //int err = avformat_open_input(&pIFormatCtx, filename.c_str(), pIFormat, NULL);
00182                 //bRet = av_open_input_file(&pIFormatCtx, filename.c_str(), pIFormat, 0, NULL);
00183         #endif
00184         
00185         #ifdef __CONFIG_1__ // Hajmi's config
00186                 int err = av_open_input_file(&pIFormatCtx, devicename.c_str(), pIFormat, 0, NULL);
00187         #endif
00188  
00189 
00190         if (err != 0) {
00191                 //if (av_open_input_file(&pFormatCtx, filename.c_str(), NULL, 0, NULL) != 0) {
00192                         
00193                         
00194                         if (err == ENOMEM) {
00195                                 printf("%s << Error = ENOMEM\n", __FUNCTION__);
00196                         } else if (err == EINVAL) {
00197                                 printf("%s << Error = EINVAL\n", __FUNCTION__);
00198                         } else {
00199                                 printf("%s << Error = (%d)\n", __FUNCTION__, err);
00200                         }
00201                         
00202                         //printf("%s << Couldn't open file (%s)...\n", __FUNCTION__, filename.c_str());
00203                         
00204                         //return -1; // Couldn't open file
00205                 }
00206 
00207     /* Retrieve stream information */
00208     if (verbose) { printf("%s << Retrieving stream info...\n", __FUNCTION__); }
00209     if (av_find_stream_info(pIFormatCtx) < 0) {
00210         fprintf(stderr, "No stream info\n");
00211         return 1;
00212     }
00213  
00214     /* Find the first video stream */
00215     ixInputStream = -1;
00216     if (verbose) { printf("%s << Finding first stream...\n", __FUNCTION__); }
00217     for (ix = 0; ix < pIFormatCtx->nb_streams; ix++) {
00218         if (pIFormatCtx->streams[ix]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00219             ixInputStream = ix;
00220             break;
00221         }
00222     }
00223     if (ixInputStream == -1) {
00224         fprintf(stderr, "No video stream in file\n");
00225         return 1;
00226     }
00227  
00228     /* Get a pointer to the codec context for the video stream */
00229     if (verbose) { printf("%s << Obtain codec context pointer...\n", __FUNCTION__); }
00230     pICodecCtx = pIFormatCtx->streams[ixInputStream]->codec;
00231  
00232     /* Find the decoder for the video stream */
00233     if (verbose) { printf("%s << Find decoder...\n", __FUNCTION__); }
00234     pICodec = avcodec_find_decoder(pICodecCtx->codec_id);
00235     if (!pICodec) {
00236         fprintf(stderr, "Codec not found\n");
00237         return 1;
00238     }
00239  
00240     /* Open input codec */
00241     if (verbose) { printf("%s << Open input codec...\n", __FUNCTION__); }
00242     if (avcodec_open(pICodecCtx, pICodec) < 0) {
00243         fprintf(stderr, "Could not open codec\n");
00244         return 1;
00245     }
00246  
00247     /* Allocate video frame */
00248     if (verbose) { printf("%s << Allocating video frame...\n", __FUNCTION__); }
00249     pFrame = avcodec_alloc_frame();
00250  
00251     /* Determine required buffer size and allocate buffer */
00252         //printf("%s << DEBUG: Hack %d\n", __FUNCTION__, 32151);
00253         //if (verbose) { printf("%s << Getting buffer size...\n", __FUNCTION__); }
00254         if (verbose) { printf("%s << Video stream frame size = (%d, %d)\n", __FUNCTION__, pICodecCtx->width, pICodecCtx->height); }
00255     
00256     deviceWidth = pICodecCtx->width;
00257     deviceHeight = pICodecCtx->height;
00258     
00259     //szBuffer = avpicture_get_size((PixelFormat) bImgFormat, pICodecCtx->width, pICodecCtx->height);
00260     //if (verbose) { printf("%s << Buffer size = (%d {%d}: [%d,%d])\n", __FUNCTION__, szBuffer, bImgFormat, pICodecCtx->width, pICodecCtx->height); }
00261     //pBuffer = (uint8_t*) av_mallocz( szBuffer);
00262  
00263     /* Allocate Output Codec */
00264     if (verbose) { printf("%s << Allocating output codec...\n", __FUNCTION__); }
00265     pOCodecCtx = avcodec_alloc_context();
00266     if (!pOCodecCtx) {
00267         fprintf(stderr, "Could not allocate codec\n");
00268         return 1;
00269     }
00270  
00271     /* Initialize picture size and other format parameters */
00272     if (verbose) { printf("%s << Initializing image size etc...\n", __FUNCTION__); }
00273     pOCodecCtx->bit_rate = pICodecCtx->bit_rate;
00274     pOCodecCtx->width = pICodecCtx->width;
00275     pOCodecCtx->height = pICodecCtx->height;
00276     pOCodecCtx->pix_fmt = (PixelFormat) bImgFormat;
00277     pOCodecCtx->codec_id = CODEC_ID_RAWVIDEO; //CODEC_ID_MJPEG;
00278     pOCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
00279     pOCodecCtx->time_base.num = pICodecCtx->time_base.num;
00280     pOCodecCtx->time_base.den = pICodecCtx->time_base.den;
00281  
00282     /* Allocate codec for JPEG */
00283     if (verbose) { printf("%s << Allocating codec for JPEG...\n", __FUNCTION__); }
00284     pOCodec = avcodec_find_encoder(pOCodecCtx->codec_id);
00285     if (!pOCodec) {
00286         fprintf(stderr, "Codec not found\n");
00287         return 1;
00288     }
00289     
00290     if (verbose) { printf("%s << Attempting to open codec...\n", __FUNCTION__); }
00291     if (avcodec_open(pOCodecCtx, pOCodec) < 0) {
00292         fprintf(stderr, "Could not open codec\n");
00293         return 1;
00294     }
00295  
00296     /* Initialize all VBR settings */
00297     if (verbose) { printf("%s << Initializing VBR settings...\n", __FUNCTION__); }
00298     pOCodecCtx->qmin = pOCodecCtx->qmax = bQuality;
00299     pOCodecCtx->mb_lmin = pOCodecCtx->lmin = pOCodecCtx->qmin * FF_QP2LAMBDA;
00300     pOCodecCtx->mb_lmax = pOCodecCtx->lmax = pOCodecCtx->qmax * FF_QP2LAMBDA;
00301     pOCodecCtx->flags |= CODEC_FLAG_QSCALE;
00302     pOCodecCtx->global_quality = pOCodecCtx->qmin * FF_QP2LAMBDA;
00303     
00304     if (verbose) { printf("%s << Exiting...\n", __FUNCTION__); }
00305     
00306     return 0;
00307 }
00308 
00309 void streamerSource::errno_exit(const char * s)
00310 {
00311   fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
00312 
00313         //printf("%s << HERE (%d) \n", __FUNCTION__, 0);
00314   exit(EXIT_FAILURE);
00315   //printf("%s << THERE (%d)\n", __FUNCTION__, 1);
00316 }
00317 
00318 
00319 int streamerSource::xioctl(int fd, int request, void * arg)
00320 {
00321   int r;
00322 
00323   do
00324     r = ioctl(fd, request, arg); while (-1==r&&EINTR==errno);
00325 
00326   return r;
00327 }
00328 
00329 
00330 
00334 //unsigned char streamerSource::CLIPVALUE(int val)
00335 //{
00336   // Old method (if)
00337 /*   val = val < 0 ? 0 : val; */
00338 /*   return val > 255 ? 255 : val; */
00339 
00340   // New method (array)
00341 //  return uchar_clipping_table[val+clipping_table_offset];
00342 //}
00343 
00365 void streamerSource::YUV2RGB(const unsigned char y,
00366         const unsigned char u,
00367         const unsigned char v,
00368         unsigned char* r,
00369         unsigned char* g,
00370         unsigned char* b)
00371 {
00372   //const int y2=(int)y;
00373   //const int u2=(int)u-128;
00374   //const int v2=(int)v-128;
00375   //std::cerr << "YUV=("<<y2<<","<<u2<<","<<v2<<")"<<std::endl;
00376 
00377 
00378   // This is the normal YUV conversion, but
00379   // appears to be incorrect for the firewire cameras
00380   //   int r2 = y2 + ( (v2*91947) >> 16);
00381   //   int g2 = y2 - ( ((u2*22544) + (v2*46793)) >> 16 );
00382   //   int b2 = y2 + ( (u2*115999) >> 16);
00383   // This is an adjusted version (UV spread out a bit)
00384   //int r2 = y2 + ( (v2*37221) >> 15);
00385   //int g2 = y2 - ( ((u2*12975) + (v2*18949)) >> 15 );
00386   //int b2 = y2 + ( (u2*66883) >> 15);
00387   //std::cerr << "   RGB=("<<r2<<","<<g2<<","<<b2<<")"<<std::endl;
00388 
00389 
00390   // Cap the values.
00391         /*
00392   *r=CLIPVALUE(r2);
00393   *g=CLIPVALUE(g2);
00394   *b=CLIPVALUE(b2);
00395         */
00396 }
00397 
00398 void streamerSource::uyvy2rgb (char *YUV, char *RGB, int NumPixels) {
00399   int i, j;
00400   unsigned char y0, y1, u, v;
00401   unsigned char r = 0, g = 0, b = 0;
00402   for (i = 0, j = 0; i < (NumPixels << 1); i += 4, j += 6)
00403     {
00404       u = (unsigned char) YUV[i + 0];
00405       y0 = (unsigned char) YUV[i + 1];
00406       v = (unsigned char) YUV[i + 2];
00407       y1 = (unsigned char) YUV[i + 3];
00408       YUV2RGB (y0, u, v, &r, &g, &b);
00409       RGB[j + 0] = r;
00410       RGB[j + 1] = g;
00411       RGB[j + 2] = b;
00412       YUV2RGB (y1, u, v, &r, &g, &b);
00413       RGB[j + 3] = r;
00414       RGB[j + 4] = g;
00415       RGB[j + 5] = b;
00416     }
00417 }
00418 
00419 void streamerSource::yuyv2rgb(char *YUV, char *RGB, int NumPixels) {
00420   int i, j;
00421   unsigned char y0, y1, u, v;
00422   unsigned char r = 0, g = 0, b = 0;
00423 
00424   for (i = 0, j = 0; i < (NumPixels << 1); i += 4, j += 6)
00425     {
00426       y0 = (unsigned char) YUV[i + 0];
00427       u = (unsigned char) YUV[i + 1];
00428       y1 = (unsigned char) YUV[i + 2];
00429       v = (unsigned char) YUV[i + 3];
00430       YUV2RGB (y0, u, v, &r, &g, &b);
00431       RGB[j + 0] = r;
00432       RGB[j + 1] = g;
00433       RGB[j + 2] = b;
00434       YUV2RGB (y1, u, v, &r, &g, &b);
00435       RGB[j + 3] = r;
00436       RGB[j + 4] = g;
00437       RGB[j + 5] = b;
00438     }
00439 }
00440 
00441 int streamerSource::init_mjpeg_decoder(int image_width, int image_height)
00442 {
00443   //avcodec_init();
00444   av_register_all();
00445   avcodec_register_all();
00446 
00447   avcodec = avcodec_find_decoder(CODEC_ID_MJPEG);
00448   if (!avcodec)
00449   {
00450     fprintf(stderr,"Could not find MJPEG decoder\n");
00451     return 0;
00452   }
00453 
00454   avcodec_context = avcodec_alloc_context();
00455   avframe_camera = avcodec_alloc_frame();
00456   avframe_rgb = avcodec_alloc_frame();
00457 
00458   avpicture_alloc((AVPicture *)avframe_rgb, PIX_FMT_RGB24, image_width, image_height);
00459 
00460   avcodec_context->codec_id = CODEC_ID_MJPEG;
00461   avcodec_context->width = image_width;
00462   avcodec_context->height = image_height;
00463 
00464   avframe_camera_size = avpicture_get_size(PIX_FMT_YUV422P, image_width, image_height);
00465   avframe_rgb_size = avpicture_get_size(PIX_FMT_RGB24, image_width, image_height);
00466 
00467   /* open it */
00468   if (avcodec_open(avcodec_context, avcodec) < 0)
00469   {
00470     fprintf(stderr,"Could not open MJPEG Decoder\n");
00471     return 0;
00472   }
00473   return 1;
00474 }
00475 
00476 void streamerSource::mjpeg2rgb(char *MJPEG, int len, char *RGB, int NumPixels)
00477 {
00478   int got_picture;
00479 
00480   memset(RGB, 0, avframe_rgb_size);
00481         
00482         printf("%s << Entering attempted fix...\n", __FUNCTION__);
00483 
00484   //avcodec_decode_video(avcodec_context, avframe_camera, &got_picture, (uint8_t *) MJPEG, len);
00485 
00486         av_init_packet(&packet);
00487 
00488         avcodec_decode_video2(avcodec_context, avframe_camera, &got_picture, &packet);
00489 
00490         printf("%s << Exiting attempted fix...\n", __FUNCTION__);
00491 
00492   if (!got_picture) {
00493     fprintf(stderr,"Webcam: expected picture but didn't get it...\n");
00494     return;
00495   }
00496 
00497   int xsize = avcodec_context->width;
00498   int ysize = avcodec_context->height;
00499   int pic_size = avpicture_get_size(avcodec_context->pix_fmt, xsize, ysize);
00500   if (pic_size != avframe_camera_size) {
00501     fprintf(stderr,"outbuf size mismatch.  pic_size: %d bufsize: %d\n",pic_size,avframe_camera_size);
00502     return;
00503   }
00504 
00505   video_sws = sws_getContext( xsize, ysize, avcodec_context->pix_fmt, xsize, ysize, PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
00506   sws_scale(video_sws, avframe_camera->data, avframe_camera->linesize, 0, ysize, avframe_rgb->data, avframe_rgb->linesize );
00507 //  img_convert((AVPicture *) avframe_rgb, PIX_FMT_RGB24, (AVPicture *) avframe_camera, avcodec_context->pix_fmt, xsize, ysize);
00508 
00509   int size = avpicture_layout((AVPicture *) avframe_rgb, PIX_FMT_RGB24, xsize, ysize, (uint8_t *)RGB, avframe_rgb_size);
00510   if (size != avframe_rgb_size) {
00511     fprintf(stderr,"webcam: avpicture_layout error: %d\n",size);
00512     return;
00513   }
00514 }
00515 
00516 void streamerSource::process_image(const void * src, int len, usb_cam_camera_image_t *dest)
00517 {
00518   if(pixelformat==V4L2_PIX_FMT_YUYV)
00519     yuyv2rgb((char*)src, dest->image, dest->width*dest->height);
00520   else if(pixelformat==V4L2_PIX_FMT_UYVY)
00521     uyvy2rgb((char*)src, dest->image, dest->width*dest->height);
00522   else if(pixelformat==V4L2_PIX_FMT_MJPEG)
00523     mjpeg2rgb((char*)src, len, dest->image, dest->width*dest->height);
00524 }
00525 
00526 int streamerSource::read_frame()
00527 {
00528   struct v4l2_buffer buf;
00529   unsigned int i;
00530   int len;
00531 
00532   switch (io) {
00533   case IO_METHOD_READ:
00534 
00535         printf("%s << IO_METHOD_READ\n", __FUNCTION__);
00536     len = read(fd, buffers[0].start, buffers[0].length);
00537     if (len==-1) {
00538       switch (errno) {
00539       case EAGAIN:
00540         return 0;
00541 
00542       case EIO:
00543         /* Could ignore EIO, see spec. */
00544 
00545         /* fall through */
00546 
00547       default:
00548         errno_exit("read");
00549       }
00550     }
00551 
00552     process_image(buffers[0].start, len, image);
00553 
00554     break;
00555 
00556   case IO_METHOD_MMAP:
00557 
00558         printf("%s << IO_METHOD_MMAP\n", __FUNCTION__);
00559     CLEAR (buf);
00560 
00561     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00562     buf.memory = V4L2_MEMORY_MMAP;
00563 
00564     if (-1==xioctl(fd, VIDIOC_DQBUF, &buf)) {
00565       switch (errno) {
00566       case EAGAIN:
00567         return 0;
00568 
00569       case EIO:
00570         /* Could ignore EIO, see spec. */
00571 
00572         /* fall through */
00573 
00574       default:
00575         errno_exit("VIDIOC_DQBUF");
00576       }
00577     }
00578 
00579     assert (buf.index < n_buffers);
00580     len = buf.bytesused;
00581 
00582         printf("%s << IO_METHOD_MMAP: Processing image...\n", __FUNCTION__);
00583     process_image(buffers[buf.index].start, len, image);
00584 
00585     if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00586       errno_exit("VIDIOC_QBUF");
00587 
00588     break;
00589 
00590   case IO_METHOD_USERPTR:
00591 
00592         printf("%s << IO_METHOD_USERPTR\n", __FUNCTION__);
00593     CLEAR (buf);
00594 
00595     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00596     buf.memory = V4L2_MEMORY_USERPTR;
00597 
00598     if (-1==xioctl(fd, VIDIOC_DQBUF, &buf)) {
00599       switch (errno) {
00600       case EAGAIN:
00601         return 0;
00602 
00603       case EIO:
00604         /* Could ignore EIO, see spec. */
00605 
00606         /* fall through */
00607 
00608       default:
00609         errno_exit("VIDIOC_DQBUF");
00610       }
00611     }
00612 
00613     for(i = 0; i<n_buffers; ++i)
00614       if (buf.m.userptr==(unsigned long) buffers[i].start&&buf.length==buffers[i].length)
00615         break;
00616 
00617     assert (i < n_buffers);
00618     len = buf.bytesused;
00619     process_image((void *) buf.m.userptr, len, image);
00620 
00621     if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00622       errno_exit("VIDIOC_QBUF");
00623 
00624     break;
00625   }
00626 
00627   return 1;
00628 }
00629 
00630 void streamerSource::stop_capturing(void)
00631 {
00632   enum v4l2_buf_type type;
00633 
00634   switch (io) {
00635           case IO_METHOD_READ:
00636                 /* Nothing to do. */
00637                 break;
00638 
00639           case IO_METHOD_MMAP:
00640           case IO_METHOD_USERPTR:
00641                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00642 
00643                 if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type)) {
00644                         printf("%s << DEBUG (%d)\n", __FUNCTION__, 0);
00645                   errno_exit("VIDIOC_STREAMOFF");
00646                   printf("%s << DEBUG (%d)\n", __FUNCTION__, 1);
00647           }
00648                 break;
00649   }
00650 }
00651 
00652 void streamerSource::start_capturing(void)
00653 {
00654   unsigned int i;
00655   enum v4l2_buf_type type;
00656 
00657   switch (io) {
00658   case IO_METHOD_READ:
00659     /* Nothing to do. */
00660     break;
00661 
00662   case IO_METHOD_MMAP:
00663         printf("%s << method = IO_METHOD_MMAP\n", __FUNCTION__);
00664     for(i = 0; i<n_buffers; ++i) {
00665       struct v4l2_buffer buf;
00666 
00667       CLEAR (buf);
00668 
00669       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00670       buf.memory = V4L2_MEMORY_MMAP;
00671       buf.index = i;
00672 
00673       if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00674         errno_exit("VIDIOC_QBUF");
00675     }
00676 
00677     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00678 
00679     if (-1==xioctl(fd, VIDIOC_STREAMON, &type))
00680       errno_exit("VIDIOC_STREAMON");
00681 
00682     break;
00683 
00684   case IO_METHOD_USERPTR:
00685         printf("%s << method = IO_METHOD_USERPTR\n", __FUNCTION__);
00686     for(i = 0; i<n_buffers; ++i) {
00687       struct v4l2_buffer buf;
00688 
00689       CLEAR (buf);
00690 
00691       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00692       buf.memory = V4L2_MEMORY_USERPTR;
00693       buf.index = i;
00694       buf.m.userptr = (unsigned long) buffers[i].start;
00695       buf.length = buffers[i].length;
00696 
00697       if (-1==xioctl(fd, VIDIOC_QBUF, &buf))
00698         errno_exit("VIDIOC_QBUF");
00699     }
00700 
00701     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00702 
00703     if (-1==xioctl(fd, VIDIOC_STREAMON, &type))
00704       errno_exit("VIDIOC_STREAMON");
00705 
00706     break;
00707   }
00708   
00709   std::cin.get();
00710 }
00711 
00712 
00713 void streamerSource::uninit_device(void)
00714 {
00715   unsigned int i;
00716 
00717   switch (io) {
00718   case IO_METHOD_READ:
00719     free(buffers[0].start);
00720     break;
00721 
00722   case IO_METHOD_MMAP:
00723     for(i = 0; i<n_buffers; ++i)
00724       if (-1==munmap(buffers[i].start, buffers[i].length))
00725         errno_exit("munmap");
00726     break;
00727 
00728   case IO_METHOD_USERPTR:
00729     for(i = 0; i<n_buffers; ++i)
00730       free(buffers[i].start);
00731     break;
00732   }
00733 
00734   free(buffers);
00735 }
00736 
00737 void streamerSource::init_read(unsigned int buffer_size)
00738 {
00739         printf("%s << DEBUG %d (n_buffers = %d)\n", __FUNCTION__, 21421, n_buffers);
00740   
00741         //buffers = new buffer;
00742  buffers = (usb_buffer*)calloc(1, sizeof(*buffers));
00743 
00744         //buffers = (buffer*)calloc(1, sizeof(buffer));
00745 
00746 
00747         //buffers = new buffer[n_buffers];
00748 
00749   if (!buffers) {
00750     fprintf(stderr, "Out of memory\n");
00751     exit(EXIT_FAILURE);
00752   }
00753 
00754   buffers[0].length = buffer_size;
00755   buffers[0].start = malloc(buffer_size);
00756 
00757   if (!buffers[0].start) {
00758     fprintf(stderr, "Out of memory\n");
00759     exit(EXIT_FAILURE);
00760   }
00761 }
00762 
00763 void streamerSource::init_mmap(void)
00764 {
00765   struct v4l2_requestbuffers req;
00766 
00767   CLEAR (req);
00768 
00769   req.count = 4;
00770   req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00771   req.memory = V4L2_MEMORY_MMAP;
00772 
00773   if (-1==xioctl(fd, VIDIOC_REQBUFS, &req)) {
00774     if (EINVAL==errno) {
00775       fprintf(stderr, "%s does not support memory mapping\n", camera_dev);
00776       exit(EXIT_FAILURE);
00777     } else {
00778       errno_exit("VIDIOC_REQBUFS");
00779     }
00780   }
00781 
00782   if (req.count<2) {
00783     fprintf(stderr, "Insufficient buffer memory on %s\n", camera_dev);
00784     exit(EXIT_FAILURE);
00785   }
00786 
00787         printf("%s << DEBUG %d\n", __FUNCTION__, 23981);
00788 
00789         // MONKEY
00790 
00791         printf("%s << n_buffers = %d (%d, %d)\n", __FUNCTION__, n_buffers, req.count, int(sizeof(*buffers)));
00792 
00793         /*
00794         for (int iii = 0; iii < req.count; iii++) {
00795                 // buffers[iii] = new buffer;
00796         }
00797         */
00798         
00799         //buffers = usb_buffer
00800 
00801     buffers = (usb_buffer*) calloc(req.count, sizeof(*buffers));
00802         //buffers = new buffer*[req.count];
00803 
00804 // DyBytes*[MAX_SIZE];
00805 
00806   if (!buffers) {
00807     fprintf(stderr, "Out of memory\n");
00808     exit(EXIT_FAILURE);
00809   }
00810 
00811   for(n_buffers = 0; n_buffers<req.count; ++n_buffers) {
00812     struct v4l2_buffer buf;
00813 
00814     CLEAR (buf);
00815 
00816     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00817     buf.memory = V4L2_MEMORY_MMAP;
00818     buf.index = n_buffers;
00819 
00820     if (-1==xioctl(fd, VIDIOC_QUERYBUF, &buf))
00821       errno_exit("VIDIOC_QUERYBUF");
00822 
00823     buffers[n_buffers].length = buf.length;
00824     buffers[n_buffers].start = mmap(NULL /* start anywhere */, buf.length, PROT_READ|PROT_WRITE /* required */, MAP_SHARED /* recommended */, fd, buf.m.offset);
00825 
00826     if (MAP_FAILED==buffers[n_buffers].start)
00827       errno_exit("mmap");
00828   }
00829 }
00830 
00831 void streamerSource::init_userp(unsigned int buffer_size)
00832 {
00833   struct v4l2_requestbuffers req;
00834   unsigned int page_size;
00835 
00836   page_size = getpagesize();
00837   buffer_size = (buffer_size+page_size-1)&~(page_size-1);
00838 
00839   CLEAR (req);
00840 
00841   req.count = 4;
00842   req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00843   req.memory = V4L2_MEMORY_USERPTR;
00844 
00845   if (-1==xioctl(fd, VIDIOC_REQBUFS, &req)) {
00846     if (EINVAL==errno) {
00847       fprintf(stderr, "%s does not support "
00848         "user pointer i/o\n", camera_dev);
00849       exit(EXIT_FAILURE);
00850     } else {
00851       errno_exit("VIDIOC_REQBUFS");
00852     }
00853   }
00854 
00855         printf("%s << DEBUG %d\n", __FUNCTION__, 62626);
00856            buffers = (usb_buffer*)calloc(4, sizeof(*buffers));
00857 
00858   if (!buffers) {
00859     fprintf(stderr, "Out of memory\n");
00860     exit(EXIT_FAILURE);
00861   }
00862 
00863   for(n_buffers = 0; n_buffers<4; ++n_buffers) {
00864     buffers[n_buffers].length = buffer_size;
00865     buffers[n_buffers].start = memalign(/* boundary */page_size, buffer_size);
00866 
00867     if (!buffers[n_buffers].start) {
00868       fprintf(stderr, "Out of memory\n");
00869       exit(EXIT_FAILURE);
00870     }
00871   }
00872 }
00873 
00874 void streamerSource::init_device(int image_width, int image_height)
00875 {
00876   struct v4l2_capability cap;
00877   struct v4l2_cropcap cropcap;
00878   struct v4l2_crop crop;
00879   struct v4l2_format fmt;
00880   unsigned int min;
00881 
00882   if (-1==xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
00883     if (EINVAL==errno) {
00884       fprintf(stderr, "%s is no V4L2 device\n", camera_dev);
00885       exit(EXIT_FAILURE);
00886     } else {
00887       errno_exit("VIDIOC_QUERYCAP");
00888     }
00889   }
00890 
00891   if (!(cap.capabilities&V4L2_CAP_VIDEO_CAPTURE)) {
00892     fprintf(stderr, "%s is no video capture device\n", camera_dev);
00893     exit(EXIT_FAILURE);
00894   }
00895 
00896   switch (io) {
00897   case IO_METHOD_READ:
00898     if (!(cap.capabilities&V4L2_CAP_READWRITE)) {
00899       fprintf(stderr, "%s does not support read i/o\n", camera_dev);
00900       exit(EXIT_FAILURE);
00901     }
00902 
00903     break;
00904 
00905   case IO_METHOD_MMAP:
00906   case IO_METHOD_USERPTR:
00907     if (!(cap.capabilities&V4L2_CAP_STREAMING)) {
00908       fprintf(stderr, "%s does not support streaming i/o\n", camera_dev);
00909       exit(EXIT_FAILURE);
00910     }
00911 
00912     break;
00913   }
00914 
00915   /* Select video input, video standard and tune here. */
00916 
00917   CLEAR (cropcap);
00918 
00919   cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00920 
00921   if (0==xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
00922     crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00923     crop.c = cropcap.defrect; /* reset to default */
00924 
00925     if (-1==xioctl(fd, VIDIOC_S_CROP, &crop)) {
00926       switch (errno) {
00927       case EINVAL:
00928         /* Cropping not supported. */
00929         break;
00930       default:
00931         /* Errors ignored. */
00932         break;
00933       }
00934     }
00935   } else {
00936     /* Errors ignored. */
00937   }
00938 
00939   CLEAR (fmt);
00940 
00941 //  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00942 //  fmt.fmt.pix.width = 640;
00943 //  fmt.fmt.pix.height = 480;
00944 //  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
00945 //  fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00946 
00947   fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00948   fmt.fmt.pix.width = image_width;
00949   fmt.fmt.pix.height = image_height;
00950   fmt.fmt.pix.pixelformat = pixelformat;
00951   fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00952 
00953 
00954   if (-1==xioctl(fd, VIDIOC_S_FMT, &fmt))
00955     errno_exit("VIDIOC_S_FMT");
00956 
00957   /* Note VIDIOC_S_FMT may change width and height. */
00958 
00959   /* Buggy driver paranoia. */
00960   min = fmt.fmt.pix.width*2;
00961   if (fmt.fmt.pix.bytesperline<min)
00962     fmt.fmt.pix.bytesperline = min;
00963   min = fmt.fmt.pix.bytesperline*fmt.fmt.pix.height;
00964   if (fmt.fmt.pix.sizeimage<min)
00965     fmt.fmt.pix.sizeimage = min;
00966 
00967   image_width = fmt.fmt.pix.width;
00968   image_height = fmt.fmt.pix.height;
00969 
00970   switch (io) {
00971   case IO_METHOD_READ:
00972     init_read(fmt.fmt.pix.sizeimage);
00973     break;
00974 
00975   case IO_METHOD_MMAP:
00976     init_mmap();
00977     break;
00978 
00979   case IO_METHOD_USERPTR:
00980     init_userp(fmt.fmt.pix.sizeimage);
00981     break;
00982   }
00983 }
00984 
00985 void streamerSource::close_device()
00986 {
00987   if (-1==close(fd))
00988     errno_exit("close");
00989 
00990   fd = -1;
00991 }
00992 
00993 void streamerSource::open_device()
00994 {
00995   struct stat st;
00996 
00997   if (-1==stat(camera_dev, &st)) {
00998     fprintf(stderr, "Cannot identify '%s': %d, %s\n", camera_dev, errno, strerror(errno));
00999     exit(EXIT_FAILURE);
01000   }
01001 
01002   if (!S_ISCHR (st.st_mode)) {
01003     fprintf(stderr, "%s is no device\n", camera_dev);
01004     exit(EXIT_FAILURE);
01005   }
01006 
01007   fd = open(camera_dev, O_RDWR /* required */|O_NONBLOCK, 0);
01008 
01009   if (-1==fd) {
01010     fprintf(stderr, "Cannot open '%s': %d, %s\n", camera_dev, errno, strerror(errno));
01011     exit(EXIT_FAILURE);
01012   }
01013 }
01014 
01015 void streamerSource::usb_cam_camera_start(const char* dev, usb_cam_io_method io_method,
01016     usb_cam_pixel_format pixel_format, int image_width, int image_height)
01017 {
01018   camera_dev = (char*)calloc(1,strlen(dev)+1);
01019   strcpy(camera_dev,dev);
01020 
01021   io = io_method;
01022   if(pixel_format == PIXEL_FORMAT_YUYV)
01023     pixelformat = V4L2_PIX_FMT_YUYV;
01024   else if(pixel_format == PIXEL_FORMAT_UYVY)
01025     pixelformat = V4L2_PIX_FMT_UYVY;
01026   else if(pixel_format == PIXEL_FORMAT_MJPEG) {
01027     pixelformat = V4L2_PIX_FMT_MJPEG;
01028     init_mjpeg_decoder(image_width, image_height);
01029   }
01030   else {
01031     fprintf(stderr, "Unknown pixelformat.\n");
01032     exit(EXIT_FAILURE);
01033   }
01034 
01035   open_device();
01036   init_device(image_width, image_height);
01037   start_capturing();
01038 
01039   image->width = image_width;
01040   image->height = image_height;
01041   image->bytes_per_pixel = 16;
01042 
01043   image->image_size = image->width*image->height*image->bytes_per_pixel;
01044   image->is_new = 0;
01045   image->image = (char *) calloc(image->image_size, sizeof(char));
01046   memset(image->image, 0, image->image_size*sizeof(char));
01047 
01048 }
01049 
01050 void streamerSource::usb_cam_camera_shutdown()
01051 {
01052   stop_capturing();
01053   uninit_device();
01054   close_device();
01055 
01056   if (avcodec_context) {
01057     avcodec_close(avcodec_context);
01058     av_free(avcodec_context);
01059     avcodec_context = NULL;
01060   }
01061   if (avframe_camera)
01062     av_free(avframe_camera);
01063   avframe_camera = NULL;
01064   if (avframe_rgb)
01065     av_free(avframe_rgb);
01066   avframe_rgb = NULL;
01067 }
01068 
01069 void streamerSource::usb_cam_camera_grab_image()
01070 {
01071   fd_set fds;
01072   struct timeval tv;
01073   int r;
01074 
01075   FD_ZERO (&fds);
01076   FD_SET (fd, &fds);
01077 
01078   /* Timeout. */
01079   tv.tv_sec = 2;
01080   tv.tv_usec = 0;
01081 
01082   r = select(fd+1, &fds, NULL, NULL, &tv);
01083 
01084   if (-1==r) {
01085     if (EINTR==errno)
01086       return;
01087 
01088     errno_exit("select");
01089   }
01090 
01091   if (0==r) {
01092     fprintf(stderr, "select timeout\n");
01093     exit(EXIT_FAILURE);
01094   }
01095 
01096   read_frame();
01097   image->is_new = 1;
01098 }
01099 
01100 


thermalvis
Author(s): Stephen Vidas
autogenerated on Sun Jan 5 2014 11:38:45