2 #include <linux/videodev2.h>
77 printf(
"Error in conversion between FFMPEG and Video4Linux pixel format constant '%s'\n",
pixel_format_name.c_str());
84 printf(
"Unable to initialize FFMPEG decoder\n");
94 struct v4l2_capability cap;
95 struct v4l2_cropcap cropcap;
96 struct v4l2_crop crop;
97 struct v4l2_format fmt;
99 struct v4l2_streamparm stream_params;
105 printf(
"Cannot identify device by name '%s' (%i)\n",
video_device_name.c_str(), errno);
108 if(!S_ISCHR(st.st_mode))
110 printf(
"'%s' is not a proper V4L device (%i)\n",
video_device_name.c_str(), errno);
118 printf(
"Cannot create a file handler for V4L device '%s' (%i)\n",
video_device_name.c_str(), errno);
126 printf(
"File handler created for V4L-incompatible device '%s' (%i)\n",
video_device_name.c_str(), errno);
128 printf(
"Cannot query capabilities from V4L device '%s' (%i)\n",
video_device_name.c_str(), errno);
131 if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
133 printf(
"V4L device '%s' does not support capture mode (%i)\n",
video_device_name.c_str(), errno);
139 if(!(cap.capabilities & V4L2_CAP_READWRITE))
147 if(!(cap.capabilities & V4L2_CAP_STREAMING))
158 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
161 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
162 crop.c = cropcap.defrect;
166 printf(
"Video4Linux: CROP mode is not supported\n");
168 printf(
"Video4Linux: IOCTL is not supported\n");
172 printf(
"Video4Linux: internal error occurred, hoping for device fallback\n");
174 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
178 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
185 min = fmt.fmt.pix.width * 2;
186 if(fmt.fmt.pix.bytesperline < min)
187 fmt.fmt.pix.bytesperline = min;
188 min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
189 if(fmt.fmt.pix.sizeimage < min)
190 fmt.fmt.pix.sizeimage = min;
193 CLEAR(stream_params);
194 stream_params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
197 printf(
"Cannot set stream parameters (%i)\n", errno);
200 if(!stream_params.parm.capture.capability && V4L2_CAP_TIMEPERFRAME)
201 printf(
"Video4Linux: V4L2_CAP_TIMEPERFRAME not supported\n");
204 stream_params.parm.capture.timeperframe.numerator = 1;
205 stream_params.parm.capture.timeperframe.denominator =
framerate;
207 printf(
"Video4Linux: cannot set desired framerate: %i fps (%i)\n",
framerate, errno);
231 av_packet_free(&
avpkt);
254 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
255 avcodec_register_all();
260 printf(
"Initializing FFMPEG decoder for MJPEG compression\n");
265 printf(
"Initializing FFMPEG decoder for H.264 compression\n");
284 av_log_set_level(AV_LOG_ERROR);
286 av_log_set_level(AV_LOG_INFO);
287 #if LIBAVCODEC_VERSION_MAJOR < 55
294 #if LIBAVCODEC_VERSION_MAJOR < 55
295 avpicture_alloc(
reinterpret_cast<AVPicture *
>(
avframe_rgb),
314 #if LIBAVCODEC_VERSION_MAJOR > 52
325 case AV_PIX_FMT_YUVJ420P:
329 case AV_PIX_FMT_YUVJ422P:
333 case AV_PIX_FMT_YUVJ444P:
342 #if LIBAVCODEC_VERSION_MAJOR < 55
357 printf(
"Cannot open FFMPEG decoder context\n");
371 avpkt = av_packet_alloc();
381 enum v4l2_buf_type type;
386 printf(
"Capturing from block device, cancelling memory remap\n");
391 struct v4l2_buffer buf;
393 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
394 buf.memory = V4L2_MEMORY_MMAP;
398 printf(
"Video4linux: unable to configure stream (%i)\n", errno);
406 struct v4l2_buffer buf;
408 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
409 buf.memory = V4L2_MEMORY_USERPTR;
411 buf.m.userptr =
reinterpret_cast<uint64_t
>(
buffers[i].
start);
415 printf(
"Video4linux: unable to configure stream (%i)\n", errno);
421 printf(
"Video4linux: attempt to start stream with unknown I/O method. Dropping request\n");
423 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
426 printf(
"Video4linux: unable to start stream (%i)\n", errno);
437 enum v4l2_buf_type type;
445 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
448 printf(
"Video4linux: cannot stop the device properly (%i)\n", errno);
453 printf(
"Attempt to stop streaming over unknown I/O channel\n");
470 printf(
"Video4linux: unable to deallocate frame buffers\n");
478 printf(
"Attempt to free buffer for unknown I/O method\n");
488 printf(
"Unable to close device handler properly\n");
508 r = select(
file_dev + 1, &fds,
nullptr,
nullptr, &tv);
517 printf(
"Video4linux: frame mapping operation failed (%i)\n", errno);
521 printf(
"Video4linux: frame mapping timeout (%i)\n", errno);
526 struct v4l2_buffer buf;
529 struct timespec stamp;
530 int64_t buffer_time_us;
539 else if(errno == EIO){}
542 printf(
"Block device read failure (%i)\n", errno);
550 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
551 buf.memory = V4L2_MEMORY_MMAP;
556 else if(errno == EIO){}
559 printf(
"Memory mapping failure (%i)\n", errno);
570 printf(
"Unable to exchange buffer with driver (%i)\n", errno);
576 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
577 buf.memory = V4L2_MEMORY_USERPTR;
582 else if(errno == EIO){}
585 printf(
"Unable to exchange poiner with driver (%i)\n", errno);
600 printf(
"Unable to exchange buffer with driver (%i)\n", errno);
605 printf(
"Attempt to grab the frame via unknown I/O method (%i)\n", errno);
607 bool processing_result =
false;
613 processing_result =
process_image(
reinterpret_cast<const void *
>(buf.m.userptr), len,
image);
614 if(!processing_result)
616 printf(
"2D processing operation fault\n");
641 struct v4l2_requestbuffers req;
644 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
645 req.memory = V4L2_MEMORY_MMAP;
649 printf(
"Video4Linux: device '%s' does not support memory mapping (%i)\n",
video_device_name.c_str(), errno);
651 printf(
"Video4Linux: unable to start memory mapping (%i)\n", errno);
656 printf(
"Video4Linux: insufficient memory buffers number (%i)\n", req.count);
662 printf(
"Out of memory\n");
667 struct v4l2_buffer buf;
671 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
672 buf.memory = V4L2_MEMORY_MMAP;
677 printf(
"Video4Linux: unable to query buffer status (%i)\n", errno);
683 PROT_READ | PROT_WRITE,
688 printf(
"Video4Linux: unable to allocate memory (%i)\n", errno);
698 printf(
"Out of memory\n");
705 printf(
"Out of memory\n");
711 struct v4l2_requestbuffers req;
712 unsigned int page_size;
713 page_size = getpagesize();
714 buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
717 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
718 req.memory = V4L2_MEMORY_USERPTR;
723 printf(
"Video4Linux: device '%s' does not support USERPTR access mode\n",
video_device_name.c_str());
728 printf(
"Video4Linux: device '%s' does not support streaming access\n",
video_device_name.c_str());
735 printf(
"Out of memory\n");
744 printf(
"Out of memory\n");
758 char* MJPEG =
const_cast<char *
>(
reinterpret_cast<const char *
>(src));
759 char* RGB = dest->
image;
760 static int got_picture = 1;
763 #if LIBAVCODEC_VERSION_MAJOR > 52
764 av_init_packet(
avpkt);
765 av_packet_from_data(
avpkt,
reinterpret_cast<unsigned char*
>(MJPEG), len);
768 printf(
"FFMPEG: error passing frame to decoder context\n");
775 printf(
"FFMPEG: buffer empty: expected picture data\n");
781 printf(
"FFMPEG: error decoding frame\n");
786 printf(
"FFMPEG: MJPEG frame data expected, but was not received\n");
792 #if LIBAVCODEC_VERSION_MAJOR > 52
793 int pic_size = av_image_get_buffer_size(
avcodec_context->pix_fmt, xsize, ysize, 1);
796 int pic_size = avpicture_get_size(
avcodec_context->pix_fmt, xsize, ysize);
801 printf(
"FFMPEG: MJPEG output buffer size mismatch: %i (%i expected)\n",
avframe_camera_size, pic_size);
807 #if LIBAVCODEC_VERSION_MAJOR > 52
808 int size = av_image_copy_to_buffer(
809 reinterpret_cast<uint8_t *
>(RGB),
818 int size = avpicture_layout(
819 reinterpret_cast<AVPicture *
>(
avframe_rgb), AV_PIX_FMT_RGB24,
824 printf(
"FFMPEG: image layout mismatch: %i (%i expected)\n", size,
avframe_rgb_size);
833 struct v4l2_fmtdesc current_format;
834 current_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
835 current_format.index = 0;
836 for(current_format.index = 0;
838 current_format.index++)
840 struct v4l2_frmsizeenum current_size;
841 current_size.index = 0;
842 current_size.pixel_format = current_format.pixelformat;
844 for(current_size.index = 0;
846 file_dev,
static_cast<int>(VIDIOC_ENUM_FRAMESIZES), ¤t_size) == 0;
847 current_size.index++)
849 struct v4l2_frmivalenum current_interval;
850 current_interval.index = 0;
851 current_interval.pixel_format = current_size.pixel_format;
852 current_interval.width = current_size.discrete.width;
853 current_interval.height = current_size.discrete.height;
854 for(current_interval.index = 0;
856 file_dev,
static_cast<int>(VIDIOC_ENUM_FRAMEINTERVALS), ¤t_interval) == 0;
857 current_interval.index++)
859 if(current_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
861 capture_format.
format = current_format;
862 capture_format.
size = current_size;
863 capture_format.
interval = current_interval;
892 memcpy(dest->
image, src, len);
900 std::stringstream ss;
902 std::string
cmd = ss.str();
906 const int kBufferSize = 256;
908 FILE * stream = popen(
cmd.c_str(),
"r");
911 while (!feof(stream))
913 if(fgets(
buffer, kBufferSize, stream) != NULL)
918 if (output.length() > 0)
920 printf(
"Video4linux: error setting camera parameter: '%s'\n", output.c_str());
926 printf(
"Video4linux: error running control command: '%s'\n",
cmd.c_str());
936 printf(
"Video4linux: Querying V4L2 driver for available controls (register base 0x%X, 0..99)\n", V4L2_CID_BASE);
937 struct v4l2_queryctrl ctrl;
938 struct v4l2_querymenu menu;
939 memset (&ctrl, 0,
sizeof (ctrl));
940 memset (&menu, 0,
sizeof (menu));
941 std::vector<std::string> disabled_controls;
943 ctrl.id = V4L2_CID_BASE;
944 while(ioctl(
file_dev, VIDIOC_QUERYCTRL, &ctrl) == 0)
947 std::stringstream description;
948 if(ctrl.flags & V4L2_CTRL_FLAG_DISABLED)
955 control.
type =
static_cast<v4l2_ctrl_type
>(ctrl.type);
956 control.
value = std::to_string(ctrl.default_value);
957 description << std::string(reinterpret_cast<char*>(ctrl.name)) <<
", min = "
958 << std::to_string(ctrl.minimum) <<
", max = "
959 << std::to_string(ctrl.maximum) <<
", step = "
960 << std::to_string(ctrl.step) <<
", flags = 0x" << std::hex << ctrl.flags << std::dec;
961 if(ctrl.type == V4L2_CTRL_TYPE_MENU)
964 description <<
" [ ";
965 for(menu.index = ctrl.minimum; menu.index <= ctrl.maximum; menu.index++)
967 if(ioctl(
file_dev, VIDIOC_QUERYMENU, &menu) == 0)
968 description << menu.index <<
": " << std::string(
reinterpret_cast<char*
>(menu.name)) <<
" ";
977 ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
979 if(!disabled_controls.empty())
981 std::cout <<
"Disabled controls: ";
982 for(
auto dc: disabled_controls)
983 std::cout << dc <<
" ";
984 std::cout << std::endl;
986 printf(
"Sorting control names:\n");
991 if(c->name.find(
"auto") != std::string::npos)
1000 printf(
"\t%s\n", c.name.c_str());
1005 printf(
"Video4linux: Setting up auxiliary camera parameters\n");
1008 printf(
"Video4linux: camera controls was not queried properly, please call v4l_query_controls() before!\n");
1015 printf(
"Video4linux: cannot set V4L control %s\n", control.name.c_str());