Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: media/video/capture/linux/video_capture_device_linux.cc

Issue 197873014: Revert of Implement ScopedFD in terms of ScopedGeneric. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/video/capture/linux/video_capture_device_linux.h" 5 #include "media/video/capture/linux/video_capture_device_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #if defined(OS_OPENBSD) 9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h> 10 #include <sys/videoio.h>
11 #else 11 #else
12 #include <linux/videodev2.h> 12 #include <linux/videodev2.h>
13 #endif 13 #endif
14 #include <sys/ioctl.h> 14 #include <sys/ioctl.h>
15 #include <sys/mman.h> 15 #include <sys/mman.h>
16 16
17 #include <list> 17 #include <list>
18 #include <string> 18 #include <string>
19 19
20 #include "base/bind.h" 20 #include "base/bind.h"
21 #include "base/files/file_enumerator.h" 21 #include "base/files/file_enumerator.h"
22 #include "base/files/scoped_file.h"
23 #include "base/posix/eintr_wrapper.h" 22 #include "base/posix/eintr_wrapper.h"
24 #include "base/strings/stringprintf.h" 23 #include "base/strings/stringprintf.h"
25 24
26 namespace media { 25 namespace media {
27 26
28 // Max number of video buffers VideoCaptureDeviceLinux can allocate. 27 // Max number of video buffers VideoCaptureDeviceLinux can allocate.
29 enum { kMaxVideoBuffers = 2 }; 28 enum { kMaxVideoBuffers = 2 };
30 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw. 29 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw.
31 enum { kCaptureTimeoutUs = 200000 }; 30 enum { kCaptureTimeoutUs = 200000 };
32 // The number of continuous timeouts tolerated before treated as error. 31 // The number of continuous timeouts tolerated before treated as error.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { 112 void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
114 DCHECK(device_names->empty()); 113 DCHECK(device_names->empty());
115 base::FilePath path("/dev/"); 114 base::FilePath path("/dev/");
116 base::FileEnumerator enumerator( 115 base::FileEnumerator enumerator(
117 path, false, base::FileEnumerator::FILES, "video*"); 116 path, false, base::FileEnumerator::FILES, "video*");
118 117
119 while (!enumerator.Next().empty()) { 118 while (!enumerator.Next().empty()) {
120 base::FileEnumerator::FileInfo info = enumerator.GetInfo(); 119 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
121 120
122 std::string unique_id = path.value() + info.GetName().value(); 121 std::string unique_id = path.value() + info.GetName().value();
123 base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY))); 122 int fd;
124 if (!fd.is_valid()) { 123 if ((fd = HANDLE_EINTR(open(unique_id.c_str() , O_RDONLY))) < 0) {
125 // Failed to open this device. 124 // Failed to open this device.
126 continue; 125 continue;
127 } 126 }
127 file_util::ScopedFD fd_closer(&fd);
128 // Test if this is a V4L2 capture device. 128 // Test if this is a V4L2 capture device.
129 v4l2_capability cap; 129 v4l2_capability cap;
130 if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && 130 if ((HANDLE_EINTR(ioctl(fd, VIDIOC_QUERYCAP, &cap)) == 0) &&
131 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && 131 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
132 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { 132 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
133 // This is a V4L2 video capture device 133 // This is a V4L2 video capture device
134 if (HasUsableFormats(fd.get())) { 134 if (HasUsableFormats(fd)) {
135 Name device_name(base::StringPrintf("%s", cap.card), unique_id); 135 Name device_name(base::StringPrintf("%s", cap.card), unique_id);
136 device_names->push_back(device_name); 136 device_names->push_back(device_name);
137 } else { 137 } else {
138 DVLOG(1) << "No usable formats reported by " << info.GetName().value(); 138 DVLOG(1) << "No usable formats reported by " << info.GetName().value();
139 } 139 }
140 } 140 }
141 } 141 }
142 } 142 }
143 143
144 void VideoCaptureDevice::GetDeviceSupportedFormats( 144 void VideoCaptureDevice::GetDeviceSupportedFormats(
145 const Name& device, 145 const Name& device,
146 VideoCaptureFormats* supported_formats) { 146 VideoCaptureFormats* supported_formats) {
147 if (device.id().empty()) 147 if (device.id().empty())
148 return; 148 return;
149 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); 149 int fd;
150 if (!fd.is_valid()) { 150 if ((fd = HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))) < 0) {
151 // Failed to open this device. 151 // Failed to open this device.
152 return; 152 return;
153 } 153 }
154 file_util::ScopedFD fd_closer(&fd);
154 supported_formats->clear(); 155 supported_formats->clear();
155 156
156 // Retrieve the caps one by one, first get pixel format, then sizes, then 157 // Retrieve the caps one by one, first get pixel format, then sizes, then
157 // frame rates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference. 158 // frame rates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference.
158 v4l2_fmtdesc pixel_format = {}; 159 v4l2_fmtdesc pixel_format = {};
159 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 160 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
160 while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FMT, &pixel_format)) == 0) { 161 while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &pixel_format)) == 0) {
161 VideoCaptureFormat supported_format; 162 VideoCaptureFormat supported_format;
162 supported_format.pixel_format = 163 supported_format.pixel_format =
163 V4l2ColorToVideoCaptureColorFormat((int32)pixel_format.pixelformat); 164 V4l2ColorToVideoCaptureColorFormat((int32)pixel_format.pixelformat);
164 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) { 165 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) {
165 ++pixel_format.index; 166 ++pixel_format.index;
166 continue; 167 continue;
167 } 168 }
168 169
169 v4l2_frmsizeenum frame_size = {}; 170 v4l2_frmsizeenum frame_size = {};
170 frame_size.pixel_format = pixel_format.pixelformat; 171 frame_size.pixel_format = pixel_format.pixelformat;
171 while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 172 while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 0) {
172 0) {
173 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { 173 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
174 supported_format.frame_size.SetSize( 174 supported_format.frame_size.SetSize(
175 frame_size.discrete.width, frame_size.discrete.height); 175 frame_size.discrete.width, frame_size.discrete.height);
176 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 176 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
177 // TODO(mcasas): see http://crbug.com/249953, support these devices. 177 // TODO(mcasas): see http://crbug.com/249953, support these devices.
178 NOTIMPLEMENTED(); 178 NOTIMPLEMENTED();
179 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { 179 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
180 // TODO(mcasas): see http://crbug.com/249953, support these devices. 180 // TODO(mcasas): see http://crbug.com/249953, support these devices.
181 NOTIMPLEMENTED(); 181 NOTIMPLEMENTED();
182 } 182 }
183 v4l2_frmivalenum frame_interval = {}; 183 v4l2_frmivalenum frame_interval = {};
184 frame_interval.pixel_format = pixel_format.pixelformat; 184 frame_interval.pixel_format = pixel_format.pixelformat;
185 frame_interval.width = frame_size.discrete.width; 185 frame_interval.width = frame_size.discrete.width;
186 frame_interval.height = frame_size.discrete.height; 186 frame_interval.height = frame_size.discrete.height;
187 while (HANDLE_EINTR(ioctl( 187 while (HANDLE_EINTR(
188 fd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) { 188 ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) {
189 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) { 189 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
190 if (frame_interval.discrete.numerator != 0) { 190 if (frame_interval.discrete.numerator != 0) {
191 supported_format.frame_rate = 191 supported_format.frame_rate =
192 static_cast<float>(frame_interval.discrete.denominator) / 192 static_cast<float>(frame_interval.discrete.denominator) /
193 static_cast<float>(frame_interval.discrete.numerator); 193 static_cast<float>(frame_interval.discrete.numerator);
194 } else { 194 } else {
195 supported_format.frame_rate = 0; 195 supported_format.frame_rate = 0;
196 } 196 }
197 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { 197 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
198 // TODO(mcasas): see http://crbug.com/249953, support these devices. 198 // TODO(mcasas): see http://crbug.com/249953, support these devices.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 return usb_id; 248 return usb_id;
249 } 249 }
250 250
251 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) { 251 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
252 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name); 252 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
253 if (!self) 253 if (!self)
254 return NULL; 254 return NULL;
255 // Test opening the device driver. This is to make sure it is available. 255 // Test opening the device driver. This is to make sure it is available.
256 // We will reopen it again in our worker thread when someone 256 // We will reopen it again in our worker thread when someone
257 // allocates the camera. 257 // allocates the camera.
258 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY))); 258 int fd = HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY));
259 if (!fd.is_valid()) { 259 if (fd < 0) {
260 DVLOG(1) << "Cannot open device"; 260 DVLOG(1) << "Cannot open device";
261 delete self; 261 delete self;
262 return NULL; 262 return NULL;
263 } 263 }
264 close(fd);
264 265
265 return self; 266 return self;
266 } 267 }
267 268
268 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) 269 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
269 : state_(kIdle), 270 : state_(kIdle),
270 device_name_(device_name), 271 device_name_(device_name),
272 device_fd_(-1),
271 v4l2_thread_("V4L2Thread"), 273 v4l2_thread_("V4L2Thread"),
272 buffer_pool_(NULL), 274 buffer_pool_(NULL),
273 buffer_pool_size_(0), 275 buffer_pool_size_(0),
274 timeout_count_(0) {} 276 timeout_count_(0) {}
275 277
276 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { 278 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
277 state_ = kIdle; 279 state_ = kIdle;
278 // Check if the thread is running. 280 // Check if the thread is running.
279 // This means that the device have not been DeAllocated properly. 281 // This means that the device have not been DeAllocated properly.
280 DCHECK(!v4l2_thread_.IsRunning()); 282 DCHECK(!v4l2_thread_.IsRunning());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 317
316 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, 318 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
317 int height, 319 int height,
318 int frame_rate, 320 int frame_rate,
319 scoped_ptr<Client> client) { 321 scoped_ptr<Client> client) {
320 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 322 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
321 323
322 client_ = client.Pass(); 324 client_ = client.Pass();
323 325
324 // Need to open camera with O_RDWR after Linux kernel 3.3. 326 // Need to open camera with O_RDWR after Linux kernel 3.3.
325 device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR))); 327 device_fd_ = HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR));
326 if (!device_fd_.is_valid()) { 328 if (device_fd_ < 0) {
327 SetErrorState("Failed to open V4L2 device driver."); 329 SetErrorState("Failed to open V4L2 device driver.");
328 return; 330 return;
329 } 331 }
332 device_fd_closer_.reset(&device_fd_);
330 333
331 // Test if this is a V4L2 capture device. 334 // Test if this is a V4L2 capture device.
332 v4l2_capability cap; 335 v4l2_capability cap;
333 if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) && 336 if (!((HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QUERYCAP, &cap)) == 0) &&
334 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && 337 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
335 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) { 338 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) {
336 // This is not a V4L2 video capture device. 339 // This is not a V4L2 video capture device.
337 device_fd_.reset(); 340 device_fd_closer_.reset();
341 device_fd_ = -1;
338 SetErrorState("This is not a V4L2 video capture device"); 342 SetErrorState("This is not a V4L2 video capture device");
339 return; 343 return;
340 } 344 }
341 345
342 // Get supported video formats in preferred order. 346 // Get supported video formats in preferred order.
343 // For large resolutions, favour mjpeg over raw formats. 347 // For large resolutions, favour mjpeg over raw formats.
344 std::list<int> v4l2_formats; 348 std::list<int> v4l2_formats;
345 GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight, 349 GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight,
346 &v4l2_formats); 350 &v4l2_formats);
347 351
348 v4l2_fmtdesc fmtdesc; 352 v4l2_fmtdesc fmtdesc;
349 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc)); 353 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
350 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 354 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
351 355
352 // Enumerate image formats. 356 // Enumerate image formats.
353 std::list<int>::iterator best = v4l2_formats.end(); 357 std::list<int>::iterator best = v4l2_formats.end();
354 while (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == 358 while (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) {
355 0) {
356 best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat); 359 best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat);
357 fmtdesc.index++; 360 fmtdesc.index++;
358 } 361 }
359 362
360 if (best == v4l2_formats.end()) { 363 if (best == v4l2_formats.end()) {
361 SetErrorState("Failed to find a supported camera format."); 364 SetErrorState("Failed to find a supported camera format.");
362 return; 365 return;
363 } 366 }
364 367
365 // Set format and frame size now. 368 // Set format and frame size now.
366 v4l2_format video_fmt; 369 v4l2_format video_fmt;
367 memset(&video_fmt, 0, sizeof(video_fmt)); 370 memset(&video_fmt, 0, sizeof(video_fmt));
368 video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 371 video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
369 video_fmt.fmt.pix.sizeimage = 0; 372 video_fmt.fmt.pix.sizeimage = 0;
370 video_fmt.fmt.pix.width = width; 373 video_fmt.fmt.pix.width = width;
371 video_fmt.fmt.pix.height = height; 374 video_fmt.fmt.pix.height = height;
372 video_fmt.fmt.pix.pixelformat = *best; 375 video_fmt.fmt.pix.pixelformat = *best;
373 376
374 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt)) < 0) { 377 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_S_FMT, &video_fmt)) < 0) {
375 SetErrorState("Failed to set camera format"); 378 SetErrorState("Failed to set camera format");
376 return; 379 return;
377 } 380 }
378 381
379 // Set capture framerate in the form of capture interval. 382 // Set capture framerate in the form of capture interval.
380 v4l2_streamparm streamparm; 383 v4l2_streamparm streamparm;
381 memset(&streamparm, 0, sizeof(v4l2_streamparm)); 384 memset(&streamparm, 0, sizeof(v4l2_streamparm));
382 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 385 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
383 // The following line checks that the driver knows about framerate get/set. 386 // The following line checks that the driver knows about framerate get/set.
384 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) { 387 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_G_PARM, &streamparm)) >= 0) {
385 // Now check if the device is able to accept a capture framerate set. 388 // Now check if the device is able to accept a capture framerate set.
386 if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) { 389 if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
387 streamparm.parm.capture.timeperframe.numerator = 1; 390 streamparm.parm.capture.timeperframe.numerator = 1;
388 streamparm.parm.capture.timeperframe.denominator = 391 streamparm.parm.capture.timeperframe.denominator =
389 (frame_rate) ? frame_rate : kTypicalFramerate; 392 (frame_rate) ? frame_rate : kTypicalFramerate;
390 393
391 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < 394 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_S_PARM, &streamparm)) < 0) {
392 0) {
393 SetErrorState("Failed to set camera framerate"); 395 SetErrorState("Failed to set camera framerate");
394 return; 396 return;
395 } 397 }
396 DVLOG(2) << "Actual camera driverframerate: " 398 DVLOG(2) << "Actual camera driverframerate: "
397 << streamparm.parm.capture.timeperframe.denominator << "/" 399 << streamparm.parm.capture.timeperframe.denominator << "/"
398 << streamparm.parm.capture.timeperframe.numerator; 400 << streamparm.parm.capture.timeperframe.numerator;
399 } 401 }
400 } 402 }
401 // TODO(mcasas): what should be done if the camera driver does not allow 403 // TODO(mcasas): what should be done if the camera driver does not allow
402 // framerate configuration, or the actual one is different from the desired? 404 // framerate configuration, or the actual one is different from the desired?
403 405
404 // Store our current width and height. 406 // Store our current width and height.
405 capture_format_.frame_size.SetSize(video_fmt.fmt.pix.width, 407 capture_format_.frame_size.SetSize(video_fmt.fmt.pix.width,
406 video_fmt.fmt.pix.height); 408 video_fmt.fmt.pix.height);
407 capture_format_.frame_rate = frame_rate; 409 capture_format_.frame_rate = frame_rate;
408 capture_format_.pixel_format = 410 capture_format_.pixel_format =
409 V4l2ColorToVideoCaptureColorFormat(video_fmt.fmt.pix.pixelformat); 411 V4l2ColorToVideoCaptureColorFormat(video_fmt.fmt.pix.pixelformat);
410 412
411 // Start capturing. 413 // Start capturing.
412 if (!AllocateVideoBuffers()) { 414 if (!AllocateVideoBuffers()) {
413 // Error, We can not recover. 415 // Error, We can not recover.
414 SetErrorState("Allocate buffer failed"); 416 SetErrorState("Allocate buffer failed");
415 return; 417 return;
416 } 418 }
417 419
418 // Start UVC camera. 420 // Start UVC camera.
419 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 421 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
420 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &type)) == -1) { 422 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_STREAMON, &type)) == -1) {
421 SetErrorState("VIDIOC_STREAMON failed"); 423 SetErrorState("VIDIOC_STREAMON failed");
422 return; 424 return;
423 } 425 }
424 426
425 state_ = kCapturing; 427 state_ = kCapturing;
426 // Post task to start fetching frames from v4l2. 428 // Post task to start fetching frames from v4l2.
427 v4l2_thread_.message_loop()->PostTask( 429 v4l2_thread_.message_loop()->PostTask(
428 FROM_HERE, 430 FROM_HERE,
429 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask, 431 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
430 base::Unretained(this))); 432 base::Unretained(this)));
431 } 433 }
432 434
433 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() { 435 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() {
434 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 436 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
435 437
436 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 438 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
437 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &type)) < 0) { 439 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_STREAMOFF, &type)) < 0) {
438 SetErrorState("VIDIOC_STREAMOFF failed"); 440 SetErrorState("VIDIOC_STREAMOFF failed");
439 return; 441 return;
440 } 442 }
441 // We don't dare to deallocate the buffers if we can't stop 443 // We don't dare to deallocate the buffers if we can't stop
442 // the capture device. 444 // the capture device.
443 DeAllocateVideoBuffers(); 445 DeAllocateVideoBuffers();
444 446
445 // We need to close and open the device if we want to change the settings 447 // We need to close and open the device if we want to change the settings
446 // Otherwise VIDIOC_S_FMT will return error 448 // Otherwise VIDIOC_S_FMT will return error
447 // Sad but true. 449 // Sad but true.
448 device_fd_.reset(); 450 device_fd_closer_.reset();
451 device_fd_ = -1;
449 state_ = kIdle; 452 state_ = kIdle;
450 client_.reset(); 453 client_.reset();
451 } 454 }
452 455
453 void VideoCaptureDeviceLinux::OnCaptureTask() { 456 void VideoCaptureDeviceLinux::OnCaptureTask() {
454 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 457 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
455 458
456 if (state_ != kCapturing) { 459 if (state_ != kCapturing) {
457 return; 460 return;
458 } 461 }
459 462
460 fd_set r_set; 463 fd_set r_set;
461 FD_ZERO(&r_set); 464 FD_ZERO(&r_set);
462 FD_SET(device_fd_.get(), &r_set); 465 FD_SET(device_fd_, &r_set);
463 timeval timeout; 466 timeval timeout;
464 467
465 timeout.tv_sec = 0; 468 timeout.tv_sec = 0;
466 timeout.tv_usec = kCaptureTimeoutUs; 469 timeout.tv_usec = kCaptureTimeoutUs;
467 470
468 // First argument to select is the highest numbered file descriptor +1. 471 // First argument to select is the highest numbered file descriptor +1.
469 // Refer to http://linux.die.net/man/2/select for more information. 472 // Refer to http://linux.die.net/man/2/select for more information.
470 int result = 473 int result =
471 HANDLE_EINTR(select(device_fd_.get() + 1, &r_set, NULL, NULL, &timeout)); 474 HANDLE_EINTR(select(device_fd_ + 1, &r_set, NULL, NULL, &timeout));
472 // Check if select have failed. 475 // Check if select have failed.
473 if (result < 0) { 476 if (result < 0) {
474 // EINTR is a signal. This is not really an error. 477 // EINTR is a signal. This is not really an error.
475 if (errno != EINTR) { 478 if (errno != EINTR) {
476 SetErrorState("Select failed"); 479 SetErrorState("Select failed");
477 return; 480 return;
478 } 481 }
479 v4l2_thread_.message_loop()->PostDelayedTask( 482 v4l2_thread_.message_loop()->PostDelayedTask(
480 FROM_HERE, 483 FROM_HERE,
481 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask, 484 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
482 base::Unretained(this)), 485 base::Unretained(this)),
483 base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs)); 486 base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs));
484 } 487 }
485 488
486 // Check if select timeout. 489 // Check if select timeout.
487 if (result == 0) { 490 if (result == 0) {
488 timeout_count_++; 491 timeout_count_++;
489 if (timeout_count_ >= kContinuousTimeoutLimit) { 492 if (timeout_count_ >= kContinuousTimeoutLimit) {
490 SetErrorState(base::StringPrintf( 493 SetErrorState(base::StringPrintf(
491 "Continuous timeout %d times", timeout_count_)); 494 "Continuous timeout %d times", timeout_count_));
492 timeout_count_ = 0; 495 timeout_count_ = 0;
493 return; 496 return;
494 } 497 }
495 } else { 498 } else {
496 timeout_count_ = 0; 499 timeout_count_ = 0;
497 } 500 }
498 501
499 // Check if the driver have filled a buffer. 502 // Check if the driver have filled a buffer.
500 if (FD_ISSET(device_fd_.get(), &r_set)) { 503 if (FD_ISSET(device_fd_, &r_set)) {
501 v4l2_buffer buffer; 504 v4l2_buffer buffer;
502 memset(&buffer, 0, sizeof(buffer)); 505 memset(&buffer, 0, sizeof(buffer));
503 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 506 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
504 buffer.memory = V4L2_MEMORY_MMAP; 507 buffer.memory = V4L2_MEMORY_MMAP;
505 // Dequeue a buffer. 508 // Dequeue a buffer.
506 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { 509 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_DQBUF, &buffer)) == 0) {
507 client_->OnIncomingCapturedData( 510 client_->OnIncomingCapturedData(
508 static_cast<uint8*>(buffer_pool_[buffer.index].start), 511 static_cast<uint8*>(buffer_pool_[buffer.index].start),
509 buffer.bytesused, 512 buffer.bytesused,
510 capture_format_, 513 capture_format_,
511 0, 514 0,
512 base::TimeTicks::Now()); 515 base::TimeTicks::Now());
513 516
514 // Enqueue the buffer again. 517 // Enqueue the buffer again.
515 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { 518 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QBUF, &buffer)) == -1) {
516 SetErrorState(base::StringPrintf( 519 SetErrorState(base::StringPrintf(
517 "Failed to enqueue capture buffer errno %d", errno)); 520 "Failed to enqueue capture buffer errno %d", errno));
518 } 521 }
519 } else { 522 } else {
520 SetErrorState(base::StringPrintf( 523 SetErrorState(base::StringPrintf(
521 "Failed to dequeue capture buffer errno %d", errno)); 524 "Failed to dequeue capture buffer errno %d", errno));
522 return; 525 return;
523 } 526 }
524 } 527 }
525 528
526 v4l2_thread_.message_loop()->PostTask( 529 v4l2_thread_.message_loop()->PostTask(
527 FROM_HERE, 530 FROM_HERE,
528 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask, 531 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
529 base::Unretained(this))); 532 base::Unretained(this)));
530 } 533 }
531 534
532 bool VideoCaptureDeviceLinux::AllocateVideoBuffers() { 535 bool VideoCaptureDeviceLinux::AllocateVideoBuffers() {
533 v4l2_requestbuffers r_buffer; 536 v4l2_requestbuffers r_buffer;
534 memset(&r_buffer, 0, sizeof(r_buffer)); 537 memset(&r_buffer, 0, sizeof(r_buffer));
535 538
536 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 539 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
537 r_buffer.memory = V4L2_MEMORY_MMAP; 540 r_buffer.memory = V4L2_MEMORY_MMAP;
538 r_buffer.count = kMaxVideoBuffers; 541 r_buffer.count = kMaxVideoBuffers;
539 542
540 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) { 543 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer)) < 0) {
541 return false; 544 return false;
542 } 545 }
543 546
544 if (r_buffer.count > kMaxVideoBuffers) { 547 if (r_buffer.count > kMaxVideoBuffers) {
545 r_buffer.count = kMaxVideoBuffers; 548 r_buffer.count = kMaxVideoBuffers;
546 } 549 }
547 550
548 buffer_pool_size_ = r_buffer.count; 551 buffer_pool_size_ = r_buffer.count;
549 552
550 // Map the buffers. 553 // Map the buffers.
551 buffer_pool_ = new Buffer[r_buffer.count]; 554 buffer_pool_ = new Buffer[r_buffer.count];
552 for (unsigned int i = 0; i < r_buffer.count; i++) { 555 for (unsigned int i = 0; i < r_buffer.count; i++) {
553 v4l2_buffer buffer; 556 v4l2_buffer buffer;
554 memset(&buffer, 0, sizeof(buffer)); 557 memset(&buffer, 0, sizeof(buffer));
555 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 558 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
556 buffer.memory = V4L2_MEMORY_MMAP; 559 buffer.memory = V4L2_MEMORY_MMAP;
557 buffer.index = i; 560 buffer.index = i;
558 561
559 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) { 562 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QUERYBUF, &buffer)) < 0) {
560 return false; 563 return false;
561 } 564 }
562 565
563 // Some devices require mmap() to be called with both READ and WRITE. 566 // Some devices require mmap() to be called with both READ and WRITE.
564 // See crbug.com/178582. 567 // See crbug.com/178582.
565 buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, 568 buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
566 MAP_SHARED, device_fd_.get(), buffer.m.offset); 569 MAP_SHARED, device_fd_, buffer.m.offset);
567 if (buffer_pool_[i].start == MAP_FAILED) { 570 if (buffer_pool_[i].start == MAP_FAILED) {
568 return false; 571 return false;
569 } 572 }
570 buffer_pool_[i].length = buffer.length; 573 buffer_pool_[i].length = buffer.length;
571 // Enqueue the buffer in the drivers incoming queue. 574 // Enqueue the buffer in the drivers incoming queue.
572 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { 575 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QBUF, &buffer)) < 0) {
573 return false; 576 return false;
574 } 577 }
575 } 578 }
576 return true; 579 return true;
577 } 580 }
578 581
579 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() { 582 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() {
580 if (!buffer_pool_) 583 if (!buffer_pool_)
581 return; 584 return;
582 585
583 // Unmaps buffers. 586 // Unmaps buffers.
584 for (int i = 0; i < buffer_pool_size_; i++) { 587 for (int i = 0; i < buffer_pool_size_; i++) {
585 munmap(buffer_pool_[i].start, buffer_pool_[i].length); 588 munmap(buffer_pool_[i].start, buffer_pool_[i].length);
586 } 589 }
587 v4l2_requestbuffers r_buffer; 590 v4l2_requestbuffers r_buffer;
588 memset(&r_buffer, 0, sizeof(r_buffer)); 591 memset(&r_buffer, 0, sizeof(r_buffer));
589 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 592 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
590 r_buffer.memory = V4L2_MEMORY_MMAP; 593 r_buffer.memory = V4L2_MEMORY_MMAP;
591 r_buffer.count = 0; 594 r_buffer.count = 0;
592 595
593 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) { 596 if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer)) < 0) {
594 SetErrorState("Failed to reset buf."); 597 SetErrorState("Failed to reset buf.");
595 } 598 }
596 599
597 delete [] buffer_pool_; 600 delete [] buffer_pool_;
598 buffer_pool_ = NULL; 601 buffer_pool_ = NULL;
599 buffer_pool_size_ = 0; 602 buffer_pool_size_ = 0;
600 } 603 }
601 604
602 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 605 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
603 DCHECK(!v4l2_thread_.IsRunning() || 606 DCHECK(!v4l2_thread_.IsRunning() ||
604 v4l2_thread_.message_loop() == base::MessageLoop::current()); 607 v4l2_thread_.message_loop() == base::MessageLoop::current());
605 DVLOG(1) << reason; 608 DVLOG(1) << reason;
606 state_ = kError; 609 state_ = kError;
607 client_->OnError(reason); 610 client_->OnError(reason);
608 } 611 }
609 612
610 } // namespace media 613 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/linux/video_capture_device_linux.h ('k') | net/test/spawned_test_server/local_test_server.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698