00001
00005 #include "video.hpp"
00006
00007 void streamerSource::initialize_video_source() {
00008
00009 bImgFormat = PIX_FMT_YUYV422;
00010 bQuality = 3;
00011
00012 video_sws = NULL;
00013
00014 ixInputStream = -1;
00015 io = 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
00028 av_init_packet(&packet);
00029 av_register_all();
00030
00031 };
00032
00033 int streamerSource::close_video_file(std::string filename) {
00034
00035 av_free(buffer);
00036 av_free(pFrameRGB);
00037
00038
00039 av_free(pFrame);
00040
00041
00042 avcodec_close(pCodecCtx);
00043
00044
00045 av_close_input_file(pIFormatCtx);
00046
00047 return 0;
00048 }
00049
00050
00051 int streamerSource::setup_video_file(std::string filename) {
00052
00053
00054
00055 printf("%s << Trying to set up file...\n", __FUNCTION__);
00056 av_register_all();
00057
00058
00059 pIFormatCtx = NULL;
00060
00061
00062 #ifdef __CONFIG_0__ // Steve's config
00063
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
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
00084
00085 return -1;
00086 }
00087
00088
00089
00090
00091 if (av_find_stream_info(pIFormatCtx) < 0) {
00092 printf("%s << Couldn't find stream info...\n", __FUNCTION__);
00093 return -1;
00094 }
00095
00096 #ifdef __CONFIG_0__ // Steve's config
00097
00098 av_dump_format(pIFormatCtx, 0, filename.c_str(), 0);
00099 #endif
00100
00101
00102
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;
00113 }
00114
00115
00116 pCodecCtx = pIFormatCtx->streams[videoStream]->codec;
00117
00118
00119 pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
00120 if (pCodec == NULL)
00121 {
00122 fprintf(stderr, "Unsupported codec!\n");
00123 return -1;
00124 }
00125
00126 if (avcodec_open(pCodecCtx, pCodec) < 0) {
00127 printf("%s << Couldn't open codec...\n", __FUNCTION__);
00128 return -1;
00129 }
00130
00131
00132 pFrame = avcodec_alloc_frame();
00133
00134
00135 pFrameRGB = avcodec_alloc_frame();
00136 if (pFrameRGB == NULL) {
00137 printf("%s << Couldn't allocate frame...\n", __FUNCTION__);
00138 return -1;
00139 }
00140
00141
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
00147
00148
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
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
00170
00171
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
00182
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
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
00203
00204
00205 }
00206
00207
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
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
00229 if (verbose) { printf("%s << Obtain codec context pointer...\n", __FUNCTION__); }
00230 pICodecCtx = pIFormatCtx->streams[ixInputStream]->codec;
00231
00232
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
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
00248 if (verbose) { printf("%s << Allocating video frame...\n", __FUNCTION__); }
00249 pFrame = avcodec_alloc_frame();
00250
00251
00252
00253
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
00260
00261
00262
00263
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
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;
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
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
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
00314 exit(EXIT_FAILURE);
00315
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
00335
00336
00337
00338
00339
00340
00341
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
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
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
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
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
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
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
00544
00545
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
00571
00572
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
00605
00606
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
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
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
00742 buffers = (usb_buffer*)calloc(1, sizeof(*buffers));
00743
00744
00745
00746
00747
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
00790
00791 printf("%s << n_buffers = %d (%d, %d)\n", __FUNCTION__, n_buffers, req.count, int(sizeof(*buffers)));
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 buffers = (usb_buffer*) calloc(req.count, sizeof(*buffers));
00802
00803
00804
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 , buf.length, PROT_READ|PROT_WRITE , MAP_SHARED , 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(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
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;
00924
00925 if (-1==xioctl(fd, VIDIOC_S_CROP, &crop)) {
00926 switch (errno) {
00927 case EINVAL:
00928
00929 break;
00930 default:
00931
00932 break;
00933 }
00934 }
00935 } else {
00936
00937 }
00938
00939 CLEAR (fmt);
00940
00941
00942
00943
00944
00945
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
00958
00959
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 |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
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