//打开设备
void UsbCam::open_device(void)
{
struct stat st;
// camera_dev_为 /dev/video0设备文件名
//获取设备文件的属性
if (-1 == stat(camera_dev_.c_str(), &st))
{
ROS_ERROR_STREAM("Cannot identify '" << camera_dev_ << "': " << errno << ", " << strerror(errno));
exit(EXIT_FAILURE);
}
// 如果是字符设备
if (!S_ISCHR(st.st_mode))
{
ROS_ERROR_STREAM(camera_dev_ << " is no device");
exit(EXIT_FAILURE);
}
//打开获取文件描述符
fd_ = open(camera_dev_.c_str(), O_RDWR /* required */| O_NONBLOCK, 0);
if (-1 == fd_)
{
ROS_ERROR_STREAM("Cannot open '" << camera_dev_ << "': " << errno << ", " << strerror(errno));
exit(EXIT_FAILURE);
}
}
void UsbCam::init_device(int image_width, int image_height, int framerate)
{
struct v4l2_capability cap; //设备属性
struct v4l2_cropcap cropcap; //图像的缩放
struct v4l2_crop crop; //设置窗口取景参数
struct v4l2_format fmt; //帧格式
unsigned int min;
if (-1 == xioctl(fd_, VIDIOC_QUERYCAP, &cap))
{
if (EINVAL == errno)
{
ROS_ERROR_STREAM(camera_dev_ << " is no V4L2 device");
exit(EXIT_FAILURE);
}
else
{
errno_exit("VIDIOC_QUERYCAP");
}
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
{
ROS_ERROR_STREAM(camera_dev_ << " is no video capture device");
exit(EXIT_FAILURE);
}
switch (io_)
{
case IO_METHOD_READ:
if (!(cap.capabilities & V4L2_CAP_READWRITE))
{
ROS_ERROR_STREAM(camera_dev_ << " does not support read i/o");
exit(EXIT_FAILURE);
}
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if (!(cap.capabilities & V4L2_CAP_STREAMING))
{
ROS_ERROR_STREAM(camera_dev_ << " does not support streaming i/o");
exit(EXIT_FAILURE);
}
break;
}
/* Select video input, video standard and tune here. */
CLEAR(cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == xioctl(fd_, VIDIOC_CROPCAP, &cropcap))
{
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect; /* reset to default */
if (-1 == xioctl(fd_, VIDIOC_S_CROP, &crop))
{
switch (errno)
{
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
}
}
}
else
{
/* Errors ignored. */
}
CLEAR(fmt);
// fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
// fmt.fmt.pix.width = 640;
// fmt.fmt.pix.height = 480;
// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
// fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = image_width;
fmt.fmt.pix.height = image_height;
fmt.fmt.pix.pixelformat = pixelformat_;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (-1 == xioctl(fd_, VIDIOC_S_FMT, &fmt))
errno_exit("VIDIOC_S_FMT");
/* Note VIDIOC_S_FMT may change width and height. */
/* Buggy driver paranoia. */
min = fmt.fmt.pix.width * 2;
if (fmt.fmt.pix.bytesperline < min)
fmt.fmt.pix.bytesperline = min;
min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
if (fmt.fmt.pix.sizeimage < min)
fmt.fmt.pix.sizeimage = min;
image_width = fmt.fmt.pix.width;
image_height = fmt.fmt.pix.height;
struct v4l2_streamparm stream_params;
memset(&stream_params, 0, sizeof(stream_params));
stream_params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl(fd_, VIDIOC_G_PARM, &stream_params) < 0)
errno_exit("Couldn't query v4l fps!");
ROS_DEBUG("Capability flag: 0x%x", stream_params.parm.capture.capability);
stream_params.parm.capture.timeperframe.numerator = 1;
stream_params.parm.capture.timeperframe.denominator = framerate;
if (xioctl(fd_, VIDIOC_S_PARM, &stream_params) < 0)
ROS_WARN("Couldn't set camera framerate");
else
ROS_DEBUG("Set framerate to be %i", framerate);
switch (io_)
{
case IO_METHOD_READ:
init_read(fmt.fmt.pix.sizeimage);
break;
case IO_METHOD_MMAP:
init_mmap();
break;
case IO_METHOD_USERPTR:
init_userp(fmt.fmt.pix.sizeimage);
break;
}
}