1 #ifndef USB_CAM_HARDWARE_USB_CAM_HARDWARE 2 #define USB_CAM_HARDWARE_USB_CAM_HARDWARE 16 #include <sys/ioctl.h> 19 #include <sys/types.h> 21 #include <linux/videodev2.h> 48 const std::string video_device(param_nh.
param< std::string >(
"video_device",
"/dev/video0"));
49 fd_ = open(video_device.c_str(), O_RDWR | O_NONBLOCK);
61 std::memset(&cropcap, 0,
sizeof(cropcap));
63 if (
xioctl(
fd_, VIDIOC_CROPCAP, &cropcap) == 0) {
66 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
67 crop.c = cropcap.defrect;
75 std::memset(&format, 0,
sizeof(format));
76 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
77 format.fmt.pix.width = param_nh.
param(
"image_width", 640);
78 format.fmt.pix.height = param_nh.
param(
"image_height", 480);
79 const std::string pixel_format(param_nh.
param< std::string >(
"pixel_format",
"mjpeg"));
80 if (pixel_format ==
"grey") {
81 format.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
82 }
else if (pixel_format ==
"h264") {
83 format.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
84 }
else if (pixel_format ==
"mjpeg") {
85 format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
86 }
else if (pixel_format ==
"rgb24") {
87 format.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
88 }
else if (pixel_format ==
"uyvy") {
89 format.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
90 }
else if (pixel_format ==
"yuyv") {
91 format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
93 ROS_ERROR_STREAM(
"Pixel format \"" << pixel_format <<
"\" is not supported");
96 format.fmt.pix.field = V4L2_FIELD_INTERLACED;
97 if (
xioctl(
fd_, VIDIOC_S_FMT, &format) < 0) {
106 v4l2_streamparm streamparm;
107 std::memset(&streamparm, 0,
sizeof(streamparm));
108 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
109 if (
xioctl(
fd_, VIDIOC_G_PARM, &streamparm) < 0) {
110 ROS_ERROR(
"Cannot get streaming parameters");
113 v4l2_fract &timeperframe(streamparm.parm.capture.timeperframe);
114 timeperframe.numerator = 1;
115 timeperframe.denominator = param_nh.
param(
"framerate", 30);
116 if (
xioctl(
fd_, VIDIOC_S_PARM, &streamparm) < 0) {
121 ros::Duration(static_cast< double >(timeperframe.numerator) / timeperframe.denominator);
127 v4l2_requestbuffers reqbufs;
128 std::memset(&reqbufs, 0,
sizeof(reqbufs));
130 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
131 reqbufs.memory = V4L2_MEMORY_MMAP;
132 if (
xioctl(
fd_, VIDIOC_REQBUFS, &reqbufs) < 0) {
136 if (reqbufs.count < 2) {
137 ROS_ERROR(
"Insufficient buffer memory on the device");
141 for (std::size_t i = 0; i < reqbufs.count; ++i) {
143 std::memset(&buffer, 0,
sizeof(buffer));
144 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
145 buffer.memory = V4L2_MEMORY_MMAP;
147 if (
xioctl(
fd_, VIDIOC_QUERYBUF, &buffer) < 0) {
153 mapped_buffer.
start = mmap(NULL , buffer.length, PROT_READ | PROT_WRITE,
154 MAP_SHARED,
fd_, buffer.m.offset);
155 mapped_buffer.
length = buffer.length;
156 if (mapped_buffer.
start == MAP_FAILED) {
167 for (std::size_t i = 0; i <
buffers_.size(); ++i) {
169 std::memset(&buffer, 0,
sizeof(buffer));
170 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
171 buffer.memory = V4L2_MEMORY_MMAP;
173 if (
xioctl(
fd_, VIDIOC_QBUF, &buffer) < 0) {
179 v4l2_buf_type buf_type;
180 buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
181 if (
xioctl(
fd_, VIDIOC_STREAMON, &buf_type) < 0) {
187 return time_per_frame;
193 ROS_ERROR(
"last packet is not cleared. call write() first.");
199 std::memset(&buffer, 0,
sizeof(buffer));
200 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
201 buffer.memory = V4L2_MEMORY_MMAP;
202 if (
xioctl(
fd_, VIDIOC_DQBUF, &buffer) < 0) {
228 std::memset(&buffer, 0,
sizeof(buffer));
229 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
230 buffer.memory = V4L2_MEMORY_MMAP;
232 if (
xioctl(
fd_, VIDIOC_QBUF, &buffer) == 0) {
247 v4l2_buf_type buf_type;
248 buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
249 if (
xioctl(
fd_, VIDIOC_STREAMOFF, &buf_type) < 0) {
257 if (munmap(buffer.start, buffer.length) < 0) {
265 if (close(
fd_) < 0) {
273 static int xioctl(
int fd,
int request,
void *arg) {
276 result = ioctl(fd, request, arg);
278 }
while (result < 0 && errno == EINTR);
void registerInterface(T *iface)
virtual void read(const ros::Time &time, const ros::Duration &period)
ros::Duration init(ros::NodeHandle param_nh)
virtual ~USBCamHardware()
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
virtual void write(const ros::Time &time, const ros::Duration &period)
static int xioctl(int fd, int request, void *arg)
#define ROS_ERROR_STREAM(args)
std::vector< Buffer > buffers_
usb_cam_hardware_interface::PacketInterface packet_interface_