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)