Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / capture / video / linux / video_capture_device_linux.cc
blob487199ea0401cde7b438b401e10ff7ca0c5a457a
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>
9 #else
10 #include <linux/videodev2.h>
11 #endif
13 #include <list>
15 #include "base/bind.h"
16 #include "base/strings/stringprintf.h"
17 #include "media/capture/video/linux/v4l2_capture_delegate.h"
19 namespace media {
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");
34 if (!file)
35 return false;
36 const bool success = fread(id_buf, kVidPidSize, 1, file) == 1;
37 fclose(file);
38 if (!success)
39 return false;
40 id->append(id_buf, kVidPidSize);
41 return true;
44 // Translates Video4Linux pixel formats to Chromium pixel formats.
45 // static
46 VideoPixelFormat
47 VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(uint32 v4l2_fourcc) {
48 return V4L2CaptureDelegate::V4l2FourCcToChromiumPixelFormat(v4l2_fourcc);
51 // Gets a list of usable Four CC formats prioritized.
52 // static
53 std::list<uint32_t> VideoCaptureDeviceLinux::GetListOfUsableFourCCs(
54 bool favour_mjpeg) {
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());
70 std::string usb_id;
71 if (!ReadIdFile(vidPath, &usb_id))
72 return "";
73 usb_id.append(":");
74 if (!ReadIdFile(pidPath, &usb_id))
75 return "";
77 return 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());
88 v4l2_thread_.Stop();
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.
97 v4l2_thread_.Start();
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");
105 return;
107 v4l2_thread_.message_loop()->PostTask(
108 FROM_HERE,
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(
119 FROM_HERE,
120 base::Bind(&V4L2CaptureDelegate::StopAndDeAllocate, capture_impl_));
121 v4l2_thread_.Stop();
123 capture_impl_ = NULL;
126 void VideoCaptureDeviceLinux::SetRotation(int rotation) {
127 if (v4l2_thread_.IsRunning()) {
128 v4l2_thread_.message_loop()->PostTask(
129 FROM_HERE,
130 base::Bind(&V4L2CaptureDelegate::SetRotation, capture_impl_, rotation));
134 // static
135 int VideoCaptureDeviceLinux::TranslatePowerLineFrequencyToV4L2(int frequency) {
136 switch (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;
141 default:
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;
147 } // namespace media