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/capture/video/linux/video_capture_device_linux.h"
7 #if defined(OS_OPENBSD)
8 #include <sys/videoio.h>
10 #include <linux/videodev2.h>
15 #include "base/bind.h"
16 #include "base/strings/stringprintf.h"
17 #include "media/capture/video/linux/v4l2_capture_delegate.h"
21 // USB VID and PID are both 4 bytes long.
22 static const size_t kVidPidSize
= 4;
24 // /sys/class/video4linux/video{N}/device is a symlink to the corresponding
25 // USB device info directory.
26 static const char kVidPathTemplate
[] =
27 "/sys/class/video4linux/%s/device/../idVendor";
28 static const char kPidPathTemplate
[] =
29 "/sys/class/video4linux/%s/device/../idProduct";
31 static bool ReadIdFile(const std::string
& path
, std::string
* id
) {
32 char id_buf
[kVidPidSize
];
33 FILE* file
= fopen(path
.c_str(), "rb");
36 const bool success
= fread(id_buf
, kVidPidSize
, 1, file
) == 1;
40 id
->append(id_buf
, kVidPidSize
);
44 // Translates Video4Linux pixel formats to Chromium pixel formats.
47 VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(uint32 v4l2_fourcc
) {
48 return V4L2CaptureDelegate::V4l2FourCcToChromiumPixelFormat(v4l2_fourcc
);
51 // Gets a list of usable Four CC formats prioritized.
53 std::list
<uint32_t> VideoCaptureDeviceLinux::GetListOfUsableFourCCs(
55 return V4L2CaptureDelegate::GetListOfUsableFourCcs(favour_mjpeg
);
58 const std::string
VideoCaptureDevice::Name::GetModel() const {
59 // |unique_id| is of the form "/dev/video2". |file_name| is "video2".
60 const std::string dev_dir
= "/dev/";
61 DCHECK_EQ(0, unique_id_
.compare(0, dev_dir
.length(), dev_dir
));
62 const std::string file_name
=
63 unique_id_
.substr(dev_dir
.length(), unique_id_
.length());
65 const std::string vidPath
=
66 base::StringPrintf(kVidPathTemplate
, file_name
.c_str());
67 const std::string pidPath
=
68 base::StringPrintf(kPidPathTemplate
, file_name
.c_str());
71 if (!ReadIdFile(vidPath
, &usb_id
))
74 if (!ReadIdFile(pidPath
, &usb_id
))
80 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name
& device_name
)
81 : v4l2_thread_("V4L2CaptureThread"), device_name_(device_name
) {
84 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
85 // Check if the thread is running.
86 // This means that the device has not been StopAndDeAllocate()d properly.
87 DCHECK(!v4l2_thread_
.IsRunning());
91 void VideoCaptureDeviceLinux::AllocateAndStart(
92 const VideoCaptureParams
& params
,
93 scoped_ptr
<VideoCaptureDevice::Client
> client
) {
94 DCHECK(!capture_impl_
);
95 if (v4l2_thread_
.IsRunning())
96 return; // Wrong state.
99 const int line_frequency
=
100 TranslatePowerLineFrequencyToV4L2(GetPowerLineFrequency(params
));
101 capture_impl_
= V4L2CaptureDelegate::CreateV4L2CaptureDelegate(
102 device_name_
, v4l2_thread_
.task_runner(), line_frequency
);
103 if (!capture_impl_
) {
104 client
->OnError("Failed to create VideoCaptureDelegate");
107 v4l2_thread_
.message_loop()->PostTask(
109 base::Bind(&V4L2CaptureDelegate::AllocateAndStart
, capture_impl_
,
110 params
.requested_format
.frame_size
.width(),
111 params
.requested_format
.frame_size
.height(),
112 params
.requested_format
.frame_rate
, base::Passed(&client
)));
115 void VideoCaptureDeviceLinux::StopAndDeAllocate() {
116 if (!v4l2_thread_
.IsRunning())
117 return; // Wrong state.
118 v4l2_thread_
.message_loop()->PostTask(
120 base::Bind(&V4L2CaptureDelegate::StopAndDeAllocate
, capture_impl_
));
123 capture_impl_
= NULL
;
126 void VideoCaptureDeviceLinux::SetRotation(int rotation
) {
127 if (v4l2_thread_
.IsRunning()) {
128 v4l2_thread_
.message_loop()->PostTask(
130 base::Bind(&V4L2CaptureDelegate::SetRotation
, capture_impl_
, rotation
));
135 int VideoCaptureDeviceLinux::TranslatePowerLineFrequencyToV4L2(int frequency
) {
137 case static_cast<int>(media::PowerLineFrequency::FREQUENCY_50HZ
):
138 return V4L2_CID_POWER_LINE_FREQUENCY_50HZ
;
139 case static_cast<int>(media::PowerLineFrequency::FREQUENCY_60HZ
):
140 return V4L2_CID_POWER_LINE_FREQUENCY_60HZ
;
142 // If we have no idea of the frequency, at least try and set it to AUTO.
143 return V4L2_CID_POWER_LINE_FREQUENCY_AUTO
;