hc
2023-02-13 e440ec23c5a540cdd3f7464e8779219be6fd3d95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
From 5fbece9fa1763af70c9e4346af2ac10b0dec0af7 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Mon, 1 Jul 2019 10:37:35 +0800
Subject: [PATCH 03/17] media: capture: linux: Support libv4l2 plugins
 
Allow using libv4l2 plugins for linux v4l2 capture devices.
 
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 media/capture/BUILD.gn                        | 14 +++++
 .../video/linux/v4l2_capture_device_impl.cc   | 52 ++++++++++++++++++-
 .../video/linux/v4l2_capture_device_impl.h    | 11 ++++
 3 files changed, 76 insertions(+), 1 deletion(-)
 
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index 3f80b62cb..3c6559339 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
@@ -18,6 +19,14 @@ group("capture") {
   ]
 }
 
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+
+  flags = [
+    "USE_LIBV4L2=$use_v4lplugin",
+  ]
+}
+
 component("capture_switches") {
   defines = [ "CAPTURE_IMPLEMENTATION" ]
   sources = [
@@ -266,6 +275,11 @@ component("capture_lib") {
       "video/linux/video_capture_device_linux.cc",
       "video/linux/video_capture_device_linux.h",
     ]
+    public_deps += [ ":buildflags" ]
+
+    if (use_v4lplugin) {
+      deps += [ "//media/gpu/v4l2:libv4l2_stubs" ]
+    }
   }
 
   if (is_chromeos_ash) {
diff --git a/media/capture/video/linux/v4l2_capture_device_impl.cc b/media/capture/video/linux/v4l2_capture_device_impl.cc
index c9040f5de..d05d1179e 100644
--- a/media/capture/video/linux/v4l2_capture_device_impl.cc
+++ b/media/capture/video/linux/v4l2_capture_device_impl.cc
@@ -10,19 +10,61 @@
 #include <sys/poll.h>
 #include <unistd.h>
 
+#if BUILDFLAG(USE_LIBV4L2)
+// Auto-generated for dlopen libv4l2 libraries
+#include "media/gpu/v4l2/v4l2_stubs.h"
+#include "third_party/v4l-utils/lib/include/libv4l2.h"
+
+#include "base/files/file_path.h"
+
+using media_gpu_v4l2::kModuleV4l2;
+using media_gpu_v4l2::InitializeStubs;
+using media_gpu_v4l2::StubPathMap;
+
+static const base::FilePath::CharType kV4l2Lib[] =
+    FILE_PATH_LITERAL("/usr/lib/libv4l2.so");
+#endif
+
 namespace media {
 
 V4L2CaptureDeviceImpl::~V4L2CaptureDeviceImpl() = default;
 
+V4L2CaptureDeviceImpl::V4L2CaptureDeviceImpl() {
+#if BUILDFLAG(USE_LIBV4L2)
+  StubPathMap paths;
+  paths[kModuleV4l2].push_back(kV4l2Lib);
+
+  has_libv4l2_ = InitializeStubs(paths);
+#endif
+}
+
 int V4L2CaptureDeviceImpl::open(const char* device_name, int flags) {
-  return ::open(device_name, flags);
+  int fd = ::open64(device_name, flags);
+  if (fd < 0)
+    return fd;
+
+#if BUILDFLAG(USE_LIBV4L2)
+  use_libv4l2_ = false;
+  if (has_libv4l2_ && v4l2_fd_open(fd, V4L2_DISABLE_CONVERSION) != -1) {
+    use_libv4l2_ = true;
+  }
+#endif
+  return fd;
 }
 
 int V4L2CaptureDeviceImpl::close(int fd) {
+#if BUILDFLAG(USE_LIBV4L2)
+  if (use_libv4l2_)
+    return v4l2_close(fd);
+#endif
   return ::close(fd);
 }
 
 int V4L2CaptureDeviceImpl::ioctl(int fd, int request, void* argp) {
+#if BUILDFLAG(USE_LIBV4L2)
+  if (use_libv4l2_)
+    return v4l2_ioctl(fd, request, argp);
+#endif
   return ::ioctl(fd, request, argp);
 }
 
@@ -32,10 +74,18 @@ void* V4L2CaptureDeviceImpl::mmap(void* start,
                                   int flags,
                                   int fd,
                                   off_t offset) {
+#if BUILDFLAG(USE_LIBV4L2)
+  if (use_libv4l2_)
+    return v4l2_mmap(start, length, prot, flags, fd, offset);
+#endif
   return ::mmap(start, length, prot, flags, fd, offset);
 }
 
 int V4L2CaptureDeviceImpl::munmap(void* start, size_t length) {
+#if BUILDFLAG(USE_LIBV4L2)
+  if (use_libv4l2_)
+    return v4l2_munmap(start, length);
+#endif
   return ::munmap(start, length);
 }
 
diff --git a/media/capture/video/linux/v4l2_capture_device_impl.h b/media/capture/video/linux/v4l2_capture_device_impl.h
index 936c8b093..f96c2d434 100644
--- a/media/capture/video/linux/v4l2_capture_device_impl.h
+++ b/media/capture/video/linux/v4l2_capture_device_impl.h
@@ -8,6 +8,7 @@
 #include <poll.h>
 #include <sys/fcntl.h>
 
+#include "media/capture/buildflags.h"
 #include "media/capture/capture_export.h"
 #include "media/capture/video/linux/v4l2_capture_device.h"
 
@@ -17,6 +18,8 @@ namespace media {
 // V4L2 APIs.
 class CAPTURE_EXPORT V4L2CaptureDeviceImpl : public V4L2CaptureDevice {
  public:
+  V4L2CaptureDeviceImpl();
+
   int open(const char* device_name, int flags) override;
   int close(int fd) override;
   int ioctl(int fd, int request, void* argp) override;
@@ -32,6 +35,14 @@ class CAPTURE_EXPORT V4L2CaptureDeviceImpl : public V4L2CaptureDevice {
 
  private:
   ~V4L2CaptureDeviceImpl() override;
+
+#if BUILDFLAG(USE_LIBV4L2)
+  // Has libv4l2.
+  bool has_libv4l2_;
+  // Use libv4l2 when operating |fd|.
+  bool use_libv4l2_;
+#endif
+
 };
 
 }  // namespace media
-- 
2.20.1