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