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
3 // found in the LICENSE file.
5 #include "media/video/capture/linux/video_capture_device_linux.h"
9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h>
12 #include <linux/videodev2.h>
14 #include <sys/ioctl.h>
16 #if defined(OS_TIZEN_MOBILE)
25 #include "base/bind.h"
26 #include "base/file_util.h"
27 #include "base/files/file_enumerator.h"
28 #include "base/native_library.h"
29 #include "base/strings/stringprintf.h"
33 base::NativeLibrary mfld_library = NULL;
35 void* mfld_functions = NULL;
37 typedef void (*mfld_wrapper_default_link_functions_init_t)(void* functions);
39 typedef void (*mfld_libmfld_cam_init_t)(void* functions);
41 typedef int (*mfld_cam_driver_init_t)(int fd, const char* sensor_id);
43 typedef int (*mfld_cam_set_capture_fmt_t)(int fd,
48 typedef int (*mfld_cam_driver_set_mipi_interrupt_t)(int fd, int enable);
50 typedef int (*mfld_cam_driver_deinit_t)(int fd);
52 #define MFLD_DEFINE_SYM(name) mfld_##name##_t mfld_##name = NULL
53 MFLD_DEFINE_SYM(wrapper_default_link_functions_init);
54 MFLD_DEFINE_SYM(libmfld_cam_init);
55 MFLD_DEFINE_SYM(cam_driver_init);
56 MFLD_DEFINE_SYM(cam_set_capture_fmt);
57 MFLD_DEFINE_SYM(cam_driver_set_mipi_interrupt);
58 MFLD_DEFINE_SYM(cam_driver_deinit);
60 #define MFLD_BIND_SYM(name) \
62 mfld_##name = reinterpret_cast<mfld_##name##_t>( \
63 base::GetFunctionPointerFromNativeLibrary(mfld_library, #name)); \
65 DVLOG(1) << "Failed to bind symbol "#name; \
66 base::UnloadNativeLibrary(mfld_library); \
67 mfld_library = NULL; \
72 void mfld_driver_initialize(void* functions) {
73 static bool is_initialized = false;
79 is_initialized = true;
80 mfld_library = base::LoadNativeLibrary(
81 base::FilePath("libgstatomisphal-0.10.so.0"), &error);
83 DVLOG(4) << "Failed to load mfld camera driver: " << error;
86 MFLD_BIND_SYM(wrapper_default_link_functions_init);
87 MFLD_BIND_SYM(libmfld_cam_init);
88 MFLD_BIND_SYM(cam_driver_init);
89 MFLD_BIND_SYM(cam_set_capture_fmt);
90 MFLD_BIND_SYM(cam_driver_set_mipi_interrupt);
91 MFLD_BIND_SYM(cam_driver_deinit);
92 mfld_wrapper_default_link_functions_init(functions);
93 mfld_libmfld_cam_init(functions);
96 enum { kCameraSensorSecondary, kCameraSensorPrimary };
98 #if defined(OS_TIZEN_MOBILE)
99 GstV4l2MFLDAdvCI mfld_adv_ci;
106 // Max number of video buffers VideoCaptureDeviceLinux can allocate.
107 enum { kMaxVideoBuffers = 2 };
108 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw.
109 enum { kCaptureTimeoutUs = 200000 };
110 // The number of continuous timeouts tolerated before treated as error.
111 enum { kContinuousTimeoutLimit = 10 };
112 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask
113 // if an event is triggered (select) but no video frame is read.
114 enum { kCaptureSelectWaitMs = 10 };
115 // MJPEG is prefered if the width or height is larger than this.
116 enum { kMjpegWidth = 640 };
117 enum { kMjpegHeight = 480 };
118 // Typical framerate, in fps
119 enum { kTypicalFramerate = 30 };
121 // V4L2 color formats VideoCaptureDeviceLinux support.
122 static const int32 kV4l2RawFmts[] = {
127 // USB VID and PID are both 4 bytes long.
128 static const size_t kVidPidSize = 4;
130 // /sys/class/video4linux/video{N}/device is a symlink to the corresponding
131 // USB device info directory.
132 static const char kVidPathTemplate[] =
133 "/sys/class/video4linux/%s/device/../idVendor";
134 static const char kPidPathTemplate[] =
135 "/sys/class/video4linux/%s/device/../idProduct";
137 // This function translates Video4Linux pixel formats to Chromium pixel formats,
138 // should only support those listed in GetListOfUsableFourCCs.
139 static VideoPixelFormat V4l2ColorToVideoCaptureColorFormat(
141 VideoPixelFormat result = PIXEL_FORMAT_UNKNOWN;
142 switch (v4l2_fourcc) {
143 case V4L2_PIX_FMT_YUV420:
144 result = PIXEL_FORMAT_I420;
146 case V4L2_PIX_FMT_YUYV:
147 result = PIXEL_FORMAT_YUY2;
149 case V4L2_PIX_FMT_MJPEG:
150 case V4L2_PIX_FMT_JPEG:
151 result = PIXEL_FORMAT_MJPEG;
154 DVLOG(1) << "Unsupported pixel format " << std::hex << v4l2_fourcc;
159 static void GetListOfUsableFourCCs(bool favour_mjpeg, std::list<int>* fourccs) {
160 for (size_t i = 0; i < arraysize(kV4l2RawFmts); ++i)
161 fourccs->push_back(kV4l2RawFmts[i]);
163 fourccs->push_front(V4L2_PIX_FMT_MJPEG);
165 fourccs->push_back(V4L2_PIX_FMT_MJPEG);
167 // JPEG works as MJPEG on some gspca webcams from field reports.
168 // Put it as the least preferred format.
169 fourccs->push_back(V4L2_PIX_FMT_JPEG);
172 static bool HasUsableFormats(int fd) {
173 v4l2_fmtdesc fmtdesc;
174 std::list<int> usable_fourccs;
176 GetListOfUsableFourCCs(false, &usable_fourccs);
178 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
179 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
181 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
182 if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
183 fmtdesc.pixelformat) != usable_fourccs.end())
191 void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
194 #if defined(OS_TIZEN_MOBILE)
195 mfld_functions = &mfld_adv_ci;
197 mfld_driver_initialize(mfld_functions);
199 // Empty the name list.
200 device_names->clear();
202 base::FilePath path("/dev/");
203 const char* device_wildcards = mfld_library ? "video0" : "video*";
204 base::FileEnumerator enumerator(
205 path, false, base::FileEnumerator::FILES, device_wildcards);
207 while (!enumerator.Next().empty()) {
208 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
210 std::string unique_id = path.value() + info.GetName().value();
211 if ((fd = open(unique_id.c_str() , O_RDONLY)) < 0) {
212 // Failed to open this device.
215 // Test if this is a V4L2 capture device.
217 if ((ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) &&
218 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
219 // Here chromium was expecting any capture, but not output video device.
220 // Unfortunately on Tizen camera is both a capture and output device.
221 if (!mfld_library && (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))
223 // This is a V4L2 video capture device
224 if (HasUsableFormats(fd)) {
225 Name device_name(base::StringPrintf("%s", cap.card), unique_id);
226 device_names->push_back(device_name);
228 DVLOG(1) << "No usable formats reported by " << info.GetName().value();
235 void VideoCaptureDevice::GetDeviceSupportedFormats(
237 VideoCaptureCapabilities* formats) {
239 if (device.id().empty())
242 VideoCaptureCapabilities capture_formats;
243 if ((fd = open(device.id().c_str(), O_RDONLY)) < 0) {
244 // Failed to open this device.
250 VideoCaptureCapability capture_format;
251 // Retrieve the caps one by one, first get colorspace, then sizes, then
252 // framerates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference.
253 v4l2_fmtdesc pixel_format = {};
254 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
255 while (ioctl(fd, VIDIOC_ENUM_FMT, &pixel_format) == 0) {
256 capture_format.color =
257 V4l2ColorToVideoCaptureColorFormat((int32)pixel_format.pixelformat);
258 if (capture_format.color == PIXEL_FORMAT_UNKNOWN) continue;
260 v4l2_frmsizeenum frame_size = {};
261 frame_size.pixel_format = pixel_format.pixelformat;
262 while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0) {
263 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
264 capture_format.width = frame_size.discrete.width;
265 capture_format.height = frame_size.discrete.height;
266 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
267 // TODO(mcasas): see http://crbug.com/249953, support these devices.
269 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
270 // TODO(mcasas): see http://crbug.com/249953, support these devices.
273 v4l2_frmivalenum frame_interval = {};
274 frame_interval.pixel_format = pixel_format.pixelformat;
275 frame_interval.width = frame_size.discrete.width;
276 frame_interval.height = frame_size.discrete.height;
277 while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval) == 0) {
278 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
279 if (frame_interval.discrete.numerator != 0) {
280 capture_format.frame_rate =
281 static_cast<float>(frame_interval.discrete.denominator) /
282 static_cast<float>(frame_interval.discrete.numerator);
284 capture_format.frame_rate = 0;
286 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
287 // TODO(mcasas): see http://crbug.com/249953, support these devices.
290 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
291 // TODO(mcasas): see http://crbug.com/249953, support these devices.
295 formats->push_back(capture_format);
296 ++frame_interval.index;
300 ++pixel_format.index;
307 static bool ReadIdFile(const std::string path, std::string* id) {
308 char id_buf[kVidPidSize];
309 FILE* file = fopen(path.c_str(), "rb");
312 const bool success = fread(id_buf, kVidPidSize, 1, file) == 1;
316 id->append(id_buf, kVidPidSize);
320 const std::string VideoCaptureDevice::Name::GetModel() const {
321 // |unique_id| is of the form "/dev/video2". |file_name| is "video2".
322 const std::string dev_dir = "/dev/";
323 DCHECK_EQ(0, unique_id_.compare(0, dev_dir.length(), dev_dir));
324 const std::string file_name =
325 unique_id_.substr(dev_dir.length(), unique_id_.length());
327 const std::string vidPath =
328 base::StringPrintf(kVidPathTemplate, file_name.c_str());
329 const std::string pidPath =
330 base::StringPrintf(kPidPathTemplate, file_name.c_str());
333 if (!ReadIdFile(vidPath, &usb_id))
336 if (!ReadIdFile(pidPath, &usb_id))
342 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
343 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
347 // Test opening the device driver. This is to make sure it is available.
348 // We will reopen it again in our worker thread when someone
349 // allocates the camera.
350 int fd = open(device_name.id().c_str(), O_RDONLY);
352 DVLOG(1) << "Cannot open device";
361 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
363 device_name_(device_name),
365 v4l2_thread_("V4L2Thread"),
367 buffer_pool_size_(0),
370 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
372 // Check if the thread is running.
373 // This means that the device have not been DeAllocated properly.
374 DCHECK(!v4l2_thread_.IsRunning());
377 if (device_fd_ >= 0) {
382 void VideoCaptureDeviceLinux::AllocateAndStart(
383 const VideoCaptureCapability& capture_format,
384 scoped_ptr<VideoCaptureDevice::Client> client) {
385 if (v4l2_thread_.IsRunning()) {
386 return; // Wrong state.
388 v4l2_thread_.Start();
389 v4l2_thread_.message_loop()->PostTask(
391 base::Bind(&VideoCaptureDeviceLinux::OnAllocateAndStart,
392 base::Unretained(this),
393 capture_format.width,
394 capture_format.height,
395 capture_format.frame_rate,
396 base::Passed(&client)));
399 void VideoCaptureDeviceLinux::StopAndDeAllocate() {
400 if (!v4l2_thread_.IsRunning()) {
401 return; // Wrong state.
403 v4l2_thread_.message_loop()->PostTask(
405 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
406 base::Unretained(this)));
408 // Make sure no buffers are still allocated.
409 // This can happen (theoretically) if an error occurs when trying to stop
411 DeAllocateVideoBuffers();
414 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
417 scoped_ptr<Client> client) {
418 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
420 client_ = client.Pass();
422 // Need to open camera with O_RDWR after Linux kernel 3.3.
423 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) {
424 SetErrorState("Failed to open V4L2 device driver.");
428 // Test if this is a V4L2 capture device.
430 bool is_capture_device = (ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) &&
431 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE);
432 bool is_output_device = cap.capabilities & V4L2_CAP_VIDEO_OUTPUT;
433 if (!is_capture_device || (!mfld_library && is_output_device)) {
434 // This is not a V4L2 video capture device.
437 SetErrorState("This is not a V4L2 video capture device");
442 int camera_sensor = kCameraSensorSecondary;
443 if (ioctl(device_fd_, VIDIOC_S_INPUT, &camera_sensor) < 0) {
444 SetErrorState("Cannot select camera sensor");
447 struct v4l2_input input;
448 memset(&input, 0, sizeof(input));
449 input.index = camera_sensor;
450 if (ioctl(device_fd_, VIDIOC_ENUMINPUT, &input) < 0) {
451 SetErrorState("Cannot enumerate camera input");
454 char* name = reinterpret_cast<char *>(input.name);
455 if (char* space = strchr(name, ' '))
456 name[space - name] = '\0';
457 if (mfld_cam_driver_init(device_fd_, name)) {
458 SetErrorState("Cannot initialize libmfldcam");
461 struct v4l2_control control;
462 memset(&control, 0, sizeof(control));
463 control.id = V4L2_CID_VFLIP;
465 if (ioctl(device_fd_, VIDIOC_S_CTRL, &control) < 0) {
466 SetErrorState("Cannot set vflip");
469 control.id = V4L2_CID_HFLIP;
471 if (ioctl(device_fd_, VIDIOC_S_CTRL, &control) < 0) {
472 SetErrorState("Cannot set hflip");
475 control.id = V4L2_CID_POWER_LINE_FREQUENCY;
476 // CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ
478 if (ioctl(device_fd_, VIDIOC_S_CTRL, &control) < 0) {
479 SetErrorState("Cannot set power line frequency");;
483 // Get supported video formats in preferred order.
484 // For large resolutions, favour mjpeg over raw formats.
485 std::list<int> v4l2_formats;
486 GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight,
489 v4l2_fmtdesc fmtdesc;
490 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
491 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
493 // Enumerate image formats.
494 std::list<int>::iterator best = v4l2_formats.end();
495 while (ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
496 best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat);
500 if (best == v4l2_formats.end()) {
501 SetErrorState("Failed to find a supported camera format.");
505 // Set format and frame size now.
506 v4l2_format video_fmt;
507 memset(&video_fmt, 0, sizeof(video_fmt));
508 video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
509 video_fmt.fmt.pix.sizeimage = 0;
510 video_fmt.fmt.pix.width = width;
511 video_fmt.fmt.pix.height = height;
512 video_fmt.fmt.pix.pixelformat = *best;
514 if (ioctl(device_fd_, VIDIOC_S_FMT, &video_fmt) < 0) {
515 SetErrorState("Failed to set camera format");
520 mfld_cam_set_capture_fmt(device_fd_, width, height, *best);
522 // Set capture framerate in the form of capture interval.
523 v4l2_streamparm streamparm;
524 memset(&streamparm, 0, sizeof(v4l2_streamparm));
525 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
526 // The following line checks that the driver knows about framerate get/set.
527 if (ioctl(device_fd_, VIDIOC_G_PARM, &streamparm) >= 0) {
528 // Now check if the device is able to accept a capture framerate set.
529 if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
530 streamparm.parm.capture.timeperframe.numerator = 1;
531 streamparm.parm.capture.timeperframe.denominator =
532 (frame_rate) ? frame_rate : kTypicalFramerate;
534 if (ioctl(device_fd_, VIDIOC_S_PARM, &streamparm) < 0) {
535 SetErrorState("Failed to set camera framerate");
538 DVLOG(2) << "Actual camera driverframerate: "
539 << streamparm.parm.capture.timeperframe.denominator << "/"
540 << streamparm.parm.capture.timeperframe.numerator;
543 // TODO(mcasas): what should be done if the camera driver does not allow
544 // framerate configuration, or the actual one is different from the desired?
546 // Store our current width and height.
547 VideoCaptureCapability current_settings;
548 current_settings.color = V4l2ColorToVideoCaptureColorFormat(
549 video_fmt.fmt.pix.pixelformat);
550 current_settings.width = video_fmt.fmt.pix.width;
551 current_settings.height = video_fmt.fmt.pix.height;
552 current_settings.frame_rate = frame_rate;
554 // Report the resulting frame size to the client.
555 client_->OnFrameInfo(current_settings);
558 if (!AllocateVideoBuffers()) {
559 // Error, We can not recover.
560 SetErrorState("Allocate buffer failed");
565 mfld_cam_driver_set_mipi_interrupt(device_fd_, 1);
568 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
569 if (ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) {
570 SetErrorState("VIDIOC_STREAMON failed");
575 // Post task to start fetching frames from v4l2.
576 v4l2_thread_.message_loop()->PostTask(
578 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
579 base::Unretained(this)));
582 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() {
583 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
585 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
586 if (ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) {
587 SetErrorState("VIDIOC_STREAMOFF failed");
592 mfld_cam_driver_set_mipi_interrupt(device_fd_, 0);
594 // We don't dare to deallocate the buffers if we can't stop
595 // the capture device.
596 DeAllocateVideoBuffers();
599 mfld_cam_driver_deinit(device_fd_);
601 // We need to close and open the device if we want to change the settings
602 // Otherwise VIDIOC_S_FMT will return error
610 void VideoCaptureDeviceLinux::OnCaptureTask() {
611 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
613 if (state_ != kCapturing) {
619 FD_SET(device_fd_, &r_set);
623 timeout.tv_usec = kCaptureTimeoutUs;
625 // First argument to select is the highest numbered file descriptor +1.
626 // Refer to http://linux.die.net/man/2/select for more information.
627 int result = select(device_fd_ + 1, &r_set, NULL, NULL, &timeout);
628 // Check if select have failed.
630 // EINTR is a signal. This is not really an error.
631 if (errno != EINTR) {
632 SetErrorState("Select failed");
635 v4l2_thread_.message_loop()->PostDelayedTask(
637 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
638 base::Unretained(this)),
639 base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs));
642 // Check if select timeout.
645 if (timeout_count_ >= kContinuousTimeoutLimit) {
646 SetErrorState(base::StringPrintf(
647 "Continuous timeout %d times", timeout_count_));
655 // Check if the driver have filled a buffer.
656 if (FD_ISSET(device_fd_, &r_set)) {
658 memset(&buffer, 0, sizeof(buffer));
659 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
660 buffer.memory = V4L2_MEMORY_MMAP;
662 if (ioctl(device_fd_, VIDIOC_DQBUF, &buffer) == 0) {
663 client_->OnIncomingCapturedFrame(
664 static_cast<uint8*> (buffer_pool_[buffer.index].start),
665 buffer.bytesused, base::Time::Now(), 0, false, false);
667 // Enqueue the buffer again.
668 if (ioctl(device_fd_, VIDIOC_QBUF, &buffer) == -1) {
669 SetErrorState(base::StringPrintf(
670 "Failed to enqueue capture buffer errno %d", errno));
673 SetErrorState(base::StringPrintf(
674 "Failed to dequeue capture buffer errno %d", errno));
679 v4l2_thread_.message_loop()->PostTask(
681 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
682 base::Unretained(this)));
685 bool VideoCaptureDeviceLinux::AllocateVideoBuffers() {
686 v4l2_requestbuffers r_buffer;
687 memset(&r_buffer, 0, sizeof(r_buffer));
689 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
690 r_buffer.memory = V4L2_MEMORY_MMAP;
691 r_buffer.count = kMaxVideoBuffers;
693 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
697 if (r_buffer.count > kMaxVideoBuffers) {
698 r_buffer.count = kMaxVideoBuffers;
701 buffer_pool_size_ = r_buffer.count;
704 buffer_pool_ = new Buffer[r_buffer.count];
705 for (unsigned int i = 0; i < r_buffer.count; i++) {
707 memset(&buffer, 0, sizeof(buffer));
708 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
709 buffer.memory = V4L2_MEMORY_MMAP;
712 if (ioctl(device_fd_, VIDIOC_QUERYBUF, &buffer) < 0) {
716 // Some devices require mmap() to be called with both READ and WRITE.
717 // See crbug.com/178582.
718 buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
719 MAP_SHARED, device_fd_, buffer.m.offset);
720 if (buffer_pool_[i].start == MAP_FAILED) {
723 buffer_pool_[i].length = buffer.length;
724 // Enqueue the buffer in the drivers incoming queue.
725 if (ioctl(device_fd_, VIDIOC_QBUF, &buffer) < 0) {
732 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() {
737 for (int i = 0; i < buffer_pool_size_; i++) {
738 munmap(buffer_pool_[i].start, buffer_pool_[i].length);
740 v4l2_requestbuffers r_buffer;
741 memset(&r_buffer, 0, sizeof(r_buffer));
742 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
743 r_buffer.memory = V4L2_MEMORY_MMAP;
746 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
747 SetErrorState("Failed to reset buf.");
750 delete [] buffer_pool_;
752 buffer_pool_size_ = 0;
755 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
756 DCHECK(!v4l2_thread_.IsRunning() ||
757 v4l2_thread_.message_loop() == base::MessageLoop::current());