Panda3D
 All Classes Functions Variables Enumerations
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 TypeHandle WebcamVideoV4L::_type_handle;
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: add_options_for_size
30 // Access: Private, Static
31 // Description:
32 ////////////////////////////////////////////////////////////////////
33 void WebcamVideoV4L::
34 add_options_for_size(int fd, const string &dev, const char *name, unsigned width, unsigned height, unsigned pixelformat) {
35  struct v4l2_frmivalenum frmivalenum;
36  for (int k = 0;; k++) {
37  memset(&frmivalenum, 0, sizeof frmivalenum);
38  frmivalenum.index = k;
39  frmivalenum.pixel_format = pixelformat;
40  frmivalenum.width = width;
41  frmivalenum.height = height;
42  if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) == -1) {
43  break;
44  }
45  double fps = 0.0;
46  switch (frmivalenum.type) {
47  case V4L2_FRMIVAL_TYPE_DISCRETE:
48  fps = ((double) frmivalenum.discrete.denominator) / ((double) frmivalenum.discrete.numerator);
49  break;
50 
51  case V4L2_FRMIVAL_TYPE_CONTINUOUS:
52  case V4L2_FRMIVAL_TYPE_STEPWISE:
53  {
54  // Select the maximum framerate.
55  double max_fps = ((double) frmivalenum.stepwise.max.denominator) / ((double) frmivalenum.stepwise.max.numerator);
56  fps = max_fps;
57  }
58  break;
59 
60  default:
61  continue;
62  }
63 
64  // Create a new webcam video object
65  PT(WebcamVideoV4L) wc = new WebcamVideoV4L;
66  wc->set_name(name);
67  wc->_device = dev;
68  wc->_size_x = width;
69  wc->_size_y = height;
70  wc->_fps = fps;
71  wc->_pformat = pixelformat;
72  wc->_pixel_format = string((char*) &pixelformat, 4);
73 
74  WebcamVideoV4L::_all_webcams.push_back(DCAST(WebcamVideo, wc));
75  }
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: find_all_webcams_v4l
80 // Access: Public, Static
81 // Description: Finds all Video4Linux webcams and adds them to
82 // the global list _all_webcams.
83 ////////////////////////////////////////////////////////////////////
84 void find_all_webcams_v4l() {
85  struct v4l2_capability cap2;
86 
87  vector_string devs;
88  GlobPattern pattern ("/dev/video*");
89  pattern.match_files(devs);
90  for (vector_string::iterator it = devs.begin(); it != devs.end(); ++it) {
91  int fd = open(it->c_str(), O_RDWR);
92  if (fd != -1) {
93  // Check for Video4Linux2 capabilities
94  if (ioctl(fd, VIDIOC_QUERYCAP, &cap2) != -1) {
95  if ((cap2.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
96  (cap2.capabilities & V4L2_CAP_STREAMING)) {
97  struct v4l2_fmtdesc fmt;
98  for (int i = 0;; i++) {
99  memset(&fmt, 0, sizeof fmt);
100  fmt.index = i;
101  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
102  if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
103  break;
104  }
105 
106  // Only accept supported formats.
107  switch (fmt.pixelformat) {
108 #ifdef HAVE_JPEG
109  case V4L2_PIX_FMT_MJPEG:
110 #endif
111  case V4L2_PIX_FMT_YUYV:
112  case V4L2_PIX_FMT_BGR24:
113  case V4L2_PIX_FMT_BGR32:
114  case V4L2_PIX_FMT_RGB24:
115  case V4L2_PIX_FMT_RGB32:
116  break;
117 
118  default:
119  continue;
120  }
121 
122  struct v4l2_frmsizeenum frmsizeenum;
123  for (int j = 0;; j++) {
124  memset(&frmsizeenum, 0, sizeof frmsizeenum);
125  frmsizeenum.index = j;
126  frmsizeenum.pixel_format = fmt.pixelformat;
127  if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == -1) {
128  break;
129  }
130 
131  switch (frmsizeenum.type) {
132  case V4L2_FRMSIZE_TYPE_DISCRETE:
133  // Easy, add the options with this discrete size.
134  WebcamVideoV4L::
135  add_options_for_size(fd, *it, (const char *)cap2.card,
136  frmsizeenum.discrete.width,
137  frmsizeenum.discrete.height,
138  fmt.pixelformat);
139  break;
140 
141  case V4L2_FRMSIZE_TYPE_CONTINUOUS:
142  {
143  // Okay, er, we don't have a proper handling of this,
144  // so let's add all powers of two in this range.
145 
146  __u32 width = Texture::up_to_power_2(frmsizeenum.stepwise.min_width);
147  for (; width <= frmsizeenum.stepwise.max_width; width *= 2) {
148  __u32 height = Texture::up_to_power_2(frmsizeenum.stepwise.min_height);
149  for (; height <= frmsizeenum.stepwise.max_height; height *= 2) {
150  WebcamVideoV4L::
151  add_options_for_size(fd, *it, (const char *)cap2.card, width, height, fmt.pixelformat);
152  }
153  }
154  }
155  break;
156 
157  case V4L2_FRMSIZE_TYPE_STEPWISE:
158  {
159  __u32 width = Texture::up_to_power_2(frmsizeenum.stepwise.min_width);
160  for (; width <= frmsizeenum.stepwise.max_width; width *= 2) {
161  __u32 height = Texture::up_to_power_2(frmsizeenum.stepwise.min_height);
162  for (; height <= frmsizeenum.stepwise.max_height; height *= 2) {
163  if ((width - frmsizeenum.stepwise.min_width) % frmsizeenum.stepwise.step_width == 0 &&
164  (height - frmsizeenum.stepwise.min_height) % frmsizeenum.stepwise.step_height == 0) {
165  WebcamVideoV4L::
166  add_options_for_size(fd, *it, (const char *)cap2.card, width, height, fmt.pixelformat);
167  }
168  }
169  }
170  }
171  break;
172  }
173  }
174  }
175  continue;
176  }
177  }
178  }
179  close(fd);
180  }
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: WebcamVideoV4L::open
185 // Access: Published, Virtual
186 // Description: Open this video, returning a MovieVideoCursor.
187 ////////////////////////////////////////////////////////////////////
188 PT(MovieVideoCursor) WebcamVideoV4L::
189 open() {
190  return new WebcamVideoCursorV4L(this);
191 }
192 
193 #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:1838
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