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