Panda3D
webcamVideoV4L.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file webcamVideoV4L.cxx
10  * @author rdb
11  * @date 2010-06-11
12  */
13 
14 #include "webcamVideoV4L.h"
15 
16 #if defined(HAVE_VIDEO4LINUX) && !defined(CPPPARSER)
17 
18 #include "webcamVideoCursorV4L.h"
19 #include "dcast.h"
20 
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 #include <linux/videodev2.h>
24 
25 #ifndef CPPPARSER
26 #ifndef VIDIOC_ENUM_FRAMESIZES
27 enum v4l2_frmsizetypes {
28  V4L2_FRMSIZE_TYPE_DISCRETE = 1,
29  V4L2_FRMSIZE_TYPE_CONTINUOUS = 2,
30  V4L2_FRMSIZE_TYPE_STEPWISE = 3,
31 };
32 
33 struct v4l2_frmsize_discrete {
34  __u32 width;
35  __u32 height;
36 };
37 
38 struct v4l2_frmsize_stepwise {
39  __u32 min_width;
40  __u32 max_width;
41  __u32 step_width;
42  __u32 min_height;
43  __u32 max_height;
44  __u32 step_height;
45 };
46 
47 struct v4l2_frmsizeenum {
48  __u32 index;
49  __u32 pixel_format;
50  __u32 type;
51  union {
52  struct v4l2_frmsize_discrete discrete;
53  struct v4l2_frmsize_stepwise stepwise;
54  };
55  __u32 reserved[2];
56 };
57 
58 #define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct v4l2_frmsizeenum)
59 #endif
60 
61 #ifndef VIDIOC_ENUM_FRAMEINTERVALS
62 enum v4l2_frmivaltypes {
63  V4L2_FRMIVAL_TYPE_DISCRETE = 1,
64  V4L2_FRMIVAL_TYPE_CONTINUOUS = 2,
65  V4L2_FRMIVAL_TYPE_STEPWISE = 3,
66 };
67 
68 struct v4l2_frmival_stepwise {
69  struct v4l2_fract min;
70  struct v4l2_fract max;
71  struct v4l2_fract step;
72 };
73 
74 struct v4l2_frmivalenum {
75  __u32 index;
76  __u32 pixel_format;
77  __u32 width;
78  __u32 height;
79  __u32 type;
80  union {
81  struct v4l2_fract discrete;
82  struct v4l2_frmival_stepwise stepwise;
83  };
84  __u32 reserved[2];
85 };
86 
87 #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum)
88 #endif
89 #endif
90 
91 TypeHandle WebcamVideoV4L::_type_handle;
92 
93 /**
94  *
95  */
96 void WebcamVideoV4L::
97 add_options_for_size(int fd, const std::string &dev, const char *name, unsigned width, unsigned height, unsigned pixelformat) {
98  struct v4l2_frmivalenum frmivalenum;
99  for (int k = 0;; k++) {
100  memset(&frmivalenum, 0, sizeof frmivalenum);
101  frmivalenum.index = k;
102  frmivalenum.pixel_format = pixelformat;
103  frmivalenum.width = width;
104  frmivalenum.height = height;
105  if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) == -1) {
106  break;
107  }
108  double fps = 0.0;
109  switch (frmivalenum.type) {
110  case V4L2_FRMIVAL_TYPE_DISCRETE:
111  fps = ((double) frmivalenum.discrete.denominator) / ((double) frmivalenum.discrete.numerator);
112  break;
113 
114  case V4L2_FRMIVAL_TYPE_CONTINUOUS:
115  case V4L2_FRMIVAL_TYPE_STEPWISE:
116  {
117  // Select the maximum framerate.
118  double max_fps = ((double) frmivalenum.stepwise.max.denominator) / ((double) frmivalenum.stepwise.max.numerator);
119  fps = max_fps;
120  }
121  break;
122 
123  default:
124  continue;
125  }
126 
127  // Create a new webcam video object
128  PT(WebcamVideoV4L) wc = new WebcamVideoV4L;
129  wc->set_name(name);
130  wc->_device = dev;
131  wc->_size_x = width;
132  wc->_size_y = height;
133  wc->_fps = fps;
134  wc->_pformat = pixelformat;
135  wc->_pixel_format = std::string((char*) &pixelformat, 4);
136 
137  WebcamVideoV4L::_all_webcams.push_back(DCAST(WebcamVideo, wc));
138  }
139 }
140 
141 /**
142  * Finds all Video4Linux webcams and adds them to the global list
143  * _all_webcams.
144  */
145 void find_all_webcams_v4l() {
146  struct v4l2_capability cap2;
147 
148  vector_string devs;
149  GlobPattern pattern ("/dev/video*");
150  pattern.match_files(devs);
151  for (vector_string::iterator it = devs.begin(); it != devs.end(); ++it) {
152  int fd = open(it->c_str(), O_RDWR);
153  if (fd != -1) {
154  // Check for Video4Linux2 capabilities
155  if (ioctl(fd, VIDIOC_QUERYCAP, &cap2) != -1) {
156  if ((cap2.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
157  (cap2.capabilities & V4L2_CAP_STREAMING)) {
158  struct v4l2_fmtdesc fmt;
159  for (int i = 0;; i++) {
160  memset(&fmt, 0, sizeof fmt);
161  fmt.index = i;
162  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
163  if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
164  break;
165  }
166 
167  // Only accept supported formats.
168  switch (fmt.pixelformat) {
169 #ifdef HAVE_JPEG
170  case V4L2_PIX_FMT_MJPEG:
171 #endif
172  case V4L2_PIX_FMT_YUYV:
173  case V4L2_PIX_FMT_BGR24:
174  case V4L2_PIX_FMT_BGR32:
175  case V4L2_PIX_FMT_RGB24:
176  case V4L2_PIX_FMT_RGB32:
177  case V4L2_PIX_FMT_GREY:
178  break;
179 
180  default:
181  continue;
182  }
183 
184  struct v4l2_frmsizeenum frmsizeenum;
185  for (int j = 0;; j++) {
186  memset(&frmsizeenum, 0, sizeof frmsizeenum);
187  frmsizeenum.index = j;
188  frmsizeenum.pixel_format = fmt.pixelformat;
189  if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == -1) {
190  break;
191  }
192 
193  switch (frmsizeenum.type) {
194  case V4L2_FRMSIZE_TYPE_DISCRETE:
195  // Easy, add the options with this discrete size.
196  WebcamVideoV4L::
197  add_options_for_size(fd, *it, (const char *)cap2.card,
198  frmsizeenum.discrete.width,
199  frmsizeenum.discrete.height,
200  fmt.pixelformat);
201  break;
202 
203  case V4L2_FRMSIZE_TYPE_CONTINUOUS:
204  {
205  // Okay, er, we don't have a proper handling of this, so
206  // let's add all powers of two in this range.
207 
208  __u32 width = Texture::up_to_power_2(frmsizeenum.stepwise.min_width);
209  for (; width <= frmsizeenum.stepwise.max_width; width *= 2) {
210  __u32 height = Texture::up_to_power_2(frmsizeenum.stepwise.min_height);
211  for (; height <= frmsizeenum.stepwise.max_height; height *= 2) {
212  WebcamVideoV4L::
213  add_options_for_size(fd, *it, (const char *)cap2.card, width, height, fmt.pixelformat);
214  }
215  }
216  }
217  break;
218 
219  case V4L2_FRMSIZE_TYPE_STEPWISE:
220  {
221  __u32 width = Texture::up_to_power_2(frmsizeenum.stepwise.min_width);
222  for (; width <= frmsizeenum.stepwise.max_width; width *= 2) {
223  __u32 height = Texture::up_to_power_2(frmsizeenum.stepwise.min_height);
224  for (; height <= frmsizeenum.stepwise.max_height; height *= 2) {
225  if ((width - frmsizeenum.stepwise.min_width) % frmsizeenum.stepwise.step_width == 0 &&
226  (height - frmsizeenum.stepwise.min_height) % frmsizeenum.stepwise.step_height == 0) {
227  WebcamVideoV4L::
228  add_options_for_size(fd, *it, (const char *)cap2.card, width, height, fmt.pixelformat);
229  }
230  }
231  }
232  }
233  break;
234  }
235  }
236  }
237  continue;
238  }
239  }
240  }
241  close(fd);
242  }
243 }
244 
245 /**
246  * Open this video, returning a MovieVideoCursor.
247  */
248 PT(MovieVideoCursor) WebcamVideoV4L::
249 open() {
250  return new WebcamVideoCursorV4L(this);
251 }
252 
253 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Allows you to open a webcam or other video capture device as a video stream.
Definition: webcamVideo.h:23
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A MovieVideo is actually any source that provides a sequence of video frames.
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
Definition: texture.cxx:1983
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
Definition: globPattern.h:32