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_s;
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);
563 buffer_time_s = buf.timestamp.tv_sec +
static_cast<int64_t
>(round(buf.timestamp.tv_usec / 1000000.0));
564 stamp.tv_sec =
static_cast<time_t
>(round(buffer_time_s)) +
epoch_time_shift;
565 stamp.tv_nsec =
static_cast<int64_t
>(buf.timestamp.tv_usec * 1000.0);
571 printf(
"Unable to exchange buffer with driver (%i)\n", errno);
578 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
579 buf.memory = V4L2_MEMORY_USERPTR;
584 else if(errno == EIO){}
587 printf(
"Unable to exchange poiner with driver (%i)\n", errno);
591 buffer_time_s = buf.timestamp.tv_sec +
static_cast<int64_t
>(round(buf.timestamp.tv_usec / 1000000.0));
593 stamp.tv_sec =
static_cast<time_t
>(round(buffer_time_s)) +
epoch_time_shift;
594 stamp.tv_nsec =
static_cast<int64_t
>(buf.timestamp.tv_usec / 1000.0);
599 assert(i < buffers_count);
604 printf(
"Unable to exchange buffer with driver (%i)\n", errno);
610 printf(
"Attempt to grab the frame via unknown I/O method (%i)\n", errno);
612 bool processing_result =
false;
618 processing_result =
process_image(reinterpret_cast<const void *>(buf.m.userptr), len,
image);
619 if(!processing_result)
621 printf(
"2D processing operation fault\n");
646 struct v4l2_requestbuffers req;
649 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
650 req.memory = V4L2_MEMORY_MMAP;
654 printf(
"Video4Linux: device '%s' does not support memory mapping (%i)\n",
video_device_name.c_str(), errno);
656 printf(
"Video4Linux: unable to start memory mapping (%i)\n", errno);
661 printf(
"Video4Linux: insufficient memory buffers number (%i)\n", req.count);
667 printf(
"Out of memory\n");
672 struct v4l2_buffer buf;
676 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
677 buf.memory = V4L2_MEMORY_MMAP;
682 printf(
"Video4Linux: unable to query buffer status (%i)\n", errno);
688 PROT_READ | PROT_WRITE,
693 printf(
"Video4Linux: unable to allocate memory (%i)\n", errno);
703 printf(
"Out of memory\n");
710 printf(
"Out of memory\n");
716 struct v4l2_requestbuffers req;
717 unsigned int page_size;
718 page_size = getpagesize();
719 buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
722 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
723 req.memory = V4L2_MEMORY_USERPTR;
728 printf(
"Video4Linux: device '%s' does not support USERPTR access mode\n",
video_device_name.c_str());
733 printf(
"Video4Linux: device '%s' does not support streaming access\n",
video_device_name.c_str());
740 printf(
"Out of memory\n");
749 printf(
"Out of memory\n");
763 char* MJPEG =
const_cast<char *
>(
reinterpret_cast<const char *
>(src));
764 char* RGB = dest->
image;
765 static int got_picture = 1;
768 #if LIBAVCODEC_VERSION_MAJOR > 52 769 av_init_packet(
avpkt);
770 av_packet_from_data(
avpkt, reinterpret_cast<unsigned char*>(MJPEG), len);
773 printf(
"FFMPEG: error passing frame to decoder context\n");
780 printf(
"FFMPEG: buffer empty: expected picture data\n");
786 printf(
"FFMPEG: error decoding frame\n");
791 printf(
"FFMPEG: MJPEG frame data expected, but was not received\n");
797 #if LIBAVCODEC_VERSION_MAJOR > 52 798 int pic_size = av_image_get_buffer_size(
avcodec_context->pix_fmt, xsize, ysize, 1);
801 int pic_size = avpicture_get_size(
avcodec_context->pix_fmt, xsize, ysize);
806 printf(
"FFMPEG: MJPEG output buffer size mismatch: %i (%i expected)\n",
avframe_camera_size, pic_size);
812 #if LIBAVCODEC_VERSION_MAJOR > 52 813 int size = av_image_copy_to_buffer(
814 reinterpret_cast<uint8_t *>(RGB),
823 int size = avpicture_layout(
824 reinterpret_cast<AVPicture *>(
avframe_rgb), AV_PIX_FMT_RGB24,
829 printf(
"FFMPEG: image layout mismatch: %i (%i expected)\n", size,
avframe_rgb_size);
838 struct v4l2_fmtdesc current_format;
839 current_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
840 current_format.index = 0;
841 for(current_format.index = 0;
843 current_format.index++)
845 struct v4l2_frmsizeenum current_size;
846 current_size.index = 0;
847 current_size.pixel_format = current_format.pixelformat;
849 for(current_size.index = 0;
851 file_dev, static_cast<int>(VIDIOC_ENUM_FRAMESIZES), ¤t_size) == 0;
852 current_size.index++)
854 struct v4l2_frmivalenum current_interval;
855 current_interval.index = 0;
856 current_interval.pixel_format = current_size.pixel_format;
857 current_interval.width = current_size.discrete.width;
858 current_interval.height = current_size.discrete.height;
859 for(current_interval.index = 0;
861 file_dev, static_cast<int>(VIDIOC_ENUM_FRAMEINTERVALS), ¤t_interval) == 0;
862 current_interval.index++)
864 if(current_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
866 capture_format.
format = current_format;
867 capture_format.
size = current_size;
868 capture_format.
interval = current_interval;
897 memcpy(dest->
image, src, len);
905 std::stringstream ss;
906 ss <<
"v4l2-ctl --device=" <<
video_device_name <<
" -c " << param <<
"=" << value <<
" 2>&1";
907 std::string
cmd = ss.str();
911 const int kBufferSize = 256;
913 FILE * stream = popen(cmd.c_str(),
"r");
916 while (!feof(stream))
918 if(fgets(buffer, kBufferSize, stream) != NULL)
919 output.append(buffer);
923 if (output.length() > 0)
925 printf(
"Video4linux: error setting camera parameter: '%s'\n", output.c_str());
931 printf(
"Video4linux: error running control command: '%s'\n", cmd.c_str());
941 printf(
"Video4linux: Querying V4L2 driver for available controls (register base 0x%X, 0..99)\n", V4L2_CID_BASE);
942 struct v4l2_queryctrl ctrl;
943 struct v4l2_querymenu menu;
944 memset (&ctrl, 0,
sizeof (ctrl));
945 memset (&menu, 0,
sizeof (menu));
946 std::vector<std::string> disabled_controls;
948 ctrl.id = V4L2_CID_BASE;
949 while(ioctl(
file_dev, VIDIOC_QUERYCTRL, &ctrl) == 0)
952 std::stringstream description;
953 if(ctrl.flags & V4L2_CTRL_FLAG_DISABLED)
960 control.
type =
static_cast<v4l2_ctrl_type
>(ctrl.type);
961 control.
value = std::to_string(ctrl.default_value);
962 description << std::string(reinterpret_cast<char*>(ctrl.name)) <<
", min = " 963 << std::to_string(ctrl.minimum) <<
", max = " 964 << std::to_string(ctrl.maximum) <<
", step = " 965 << std::to_string(ctrl.step) <<
", flags = 0x" << std::hex << ctrl.flags << std::dec;
966 if(ctrl.type == V4L2_CTRL_TYPE_MENU)
969 description <<
" [ ";
970 for(menu.index = ctrl.minimum; menu.index <= ctrl.maximum; menu.index++)
972 if(ioctl(
file_dev, VIDIOC_QUERYMENU, &menu) == 0)
973 description << menu.index <<
": " << std::string(reinterpret_cast<char*>(menu.name)) <<
" ";
982 ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
984 if(!disabled_controls.empty())
986 std::cout <<
"Disabled controls: ";
987 for(
auto dc: disabled_controls)
988 std::cout << dc <<
" ";
989 std::cout << std::endl;
991 printf(
"Sorting control names:\n");
996 if(c->name.find(
"auto") != std::string::npos)
1005 printf(
"\t%s\n", c.name.c_str());
1010 printf(
"Video4linux: Setting up auxiliary camera parameters\n");
1013 printf(
"Video4linux: camera controls was not queried properly, please call v4l_query_controls() before!\n");
1020 printf(
"Video4linux: cannot set V4L control %s\n", control.name.c_str());
static bool full_ffmpeg_log
static bool process_image(const void *src, int len, camera_image_t *dest)
virtual ~AbstractV4LUSBCam()
static camera_image_t * read_frame()
static const time_t epoch_time_shift
static AVCodecContext * avcodec_context
static color_format_t color_format
static void run_grabber(unsigned int &buffer_size)
#define AV_CODEC_ID_MJPEG
static bool decode_ffmpeg(const void *src, int len, camera_image_t *dest)
static AVFrame * avframe_rgb
static AVFrame * avframe_camera
bool YUV4202RGB(char *YUV, char *&RGB, const int &width, const int &height)
static void v4l_query_controls()
static bool streaming_status
static std::string color_format_name
static void close_handlers()
static io_method_t io_method
color_format_t color_format_from_string(const std::string &str)
static std::string io_method_name
static unsigned int buffers_count
static int avframe_rgb_size
static std::vector< camera_control_t > controls
static int avframe_camera_size
static std::vector< capture_format_t > & get_supported_formats()
static void release_device()
static bool init_decoder()
static pixel_format_t pixel_format
bool MONO102MONO8(const char *RAW, char *&MONO, const int &NumPixels)
static camera_image_t * image
io_method_t io_method_from_string(const std::string &str)
static unsigned int v4l_pixel_format
static AVDictionary * avoptions
static bool start_capture()
static void adjust_camera()
time_t get_epoch_time_shift()
Get epoch time shift.
static std::set< std::string > ignore_controls
static AVCodecID codec_id
static std::string video_device_name
std::string v4l_control_name_to_param_name(const char *name)
bool UYVY2RGB(const char *YUV, char *&RGB, const int &NumPixels)
static std::string pixel_format_name
static struct SwsContext * video_sws
static bool set_v4l_parameter(const std::string ¶m, const std::string &value)
static std::vector< capture_format_t > supported_formats
pixel_format_t pixel_format_from_string(const std::string &str)
int xioctl(int fd, int request, void *arg)
bool COPY2RGB(const char *input, char *&output, const int &NumPixels)
bool YUYV2RGB(const char *YUV, char *&RGB, const int &NumPixels)
unsigned int v4l_pixel_format_from_pixel_format(const pixel_format_t &pixelformat, bool &mono)