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
GlobPattern
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
Definition: globPattern.h:32
MovieVideoCursor
A MovieVideo is actually any source that provides a sequence of video frames.
Definition: movieVideoCursor.h:41
Texture::up_to_power_2
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
Definition: texture.cxx:2008
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
WebcamVideo
Allows you to open a webcam or other video capture device as a video stream.
Definition: webcamVideo.h:23
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
webcamVideoCursorV4L.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
webcamVideoV4L.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.