1From 6e9d3aa5e8baa7b47901ba6fd15614fb39fe7fba Mon Sep 17 00:00:00 2001
2From: Maksim Sisov <msisov@igalia.com>
3Date: Wed, 31 Jul 2019 09:56:24 +0300
4Subject: [PATCH 01/17] Add support for V4L2 VDA and VEA on Linux
5
6Based on:
7https://github.com/OSSystems/meta-browser/pull/263/commits/60ceb28750ee1f73c9cc2bf7e9e20e1c37a03497
8
9Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
10---
11 .../gpu_mjpeg_decode_accelerator_factory.cc   |  3 +-
12 media/gpu/BUILD.gn                            |  1 +
13 media/gpu/args.gni                            |  3 +
14 .../gpu_video_decode_accelerator_factory.cc   |  8 +++
15 .../gpu_video_decode_accelerator_factory.h    |  2 +
16 media/gpu/v4l2/BUILD.gn                       | 38 ++++++----
17 media/gpu/v4l2/generic_v4l2_device.cc         |  2 +-
18 media/gpu/v4l2/v4l2_device.cc                 | 70 +++++++++++++++++++
19 media/gpu/v4l2/v4l2_video_decoder.cc          |  7 ++
20 9 files changed, 119 insertions(+), 15 deletions(-)
21
22diff --git a/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc b/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
23index 3772b8ef0..dece6b77f 100644
24--- a/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
25+++ b/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
26@@ -13,7 +13,8 @@
27 #include "media/base/media_switches.h"
28 #include "media/gpu/buildflags.h"
29
30-#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
31+#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY) && \
32+    !BUILDFLAG(USE_LINUX_V4L2)
33 #define USE_V4L2_MJPEG_DECODE_ACCELERATOR
34 #endif
35
36diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
37index 87b7f16fc..6e519acf2 100644
38--- a/media/gpu/BUILD.gn
39+++ b/media/gpu/BUILD.gn
40@@ -20,6 +20,7 @@ buildflag_header("buildflags") {
41     "USE_VAAPI_IMAGE_CODECS=$use_vaapi_image_codecs",
42     "USE_V4L2_CODEC=$use_v4l2_codec",
43     "USE_LIBV4L2=$use_v4lplugin",
44+    "USE_LINUX_V4L2=$use_linux_v4l2_only",
45     "USE_VAAPI_X11=$use_vaapi_x11",
46   ]
47 }
48diff --git a/media/gpu/args.gni b/media/gpu/args.gni
49index da3ea5a5d..e2c58e366 100644
50--- a/media/gpu/args.gni
51+++ b/media/gpu/args.gni
52@@ -20,6 +20,9 @@ declare_args() {
53   # platforms which have v4l2 hardware encoder / decoder.
54   use_v4l2_codec = false
55
56+  # Indicates if Video4Linux2 codec is used for linux platform.
57+  use_linux_v4l2_only = false
58+
59   # Indicates if Video4Linux2 AML encoder is used. This is used for AML
60   # platforms which have v4l2 hardware encoder
61   use_v4l2_codec_aml = false
62diff --git a/media/gpu/gpu_video_decode_accelerator_factory.cc b/media/gpu/gpu_video_decode_accelerator_factory.cc
63index 4785d49e8..d8305702a 100644
64--- a/media/gpu/gpu_video_decode_accelerator_factory.cc
65+++ b/media/gpu/gpu_video_decode_accelerator_factory.cc
66@@ -29,7 +29,9 @@
67 #include "ui/gl/gl_implementation.h"
68 #elif BUILDFLAG(USE_V4L2_CODEC)
69 #include "media/gpu/v4l2/v4l2_device.h"
70+#if !BUILDFLAG(USE_LINUX_V4L2)
71 #include "media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h"
72+#endif
73 #include "media/gpu/v4l2/v4l2_video_decode_accelerator.h"
74 #include "ui/gl/gl_surface_egl.h"
75 #endif
76@@ -64,10 +66,12 @@ gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilitiesInternal(
77   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
78       V4L2VideoDecodeAccelerator::GetSupportedProfiles(),
79       &capabilities.supported_profiles);
80+#if !BUILDFLAG(USE_LINUX_V4L2)
81   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
82       V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles(),
83       &capabilities.supported_profiles);
84 #endif
85+#endif
86 #elif BUILDFLAG(IS_MAC)
87   capabilities.supported_profiles =
88       VTVideoDecodeAccelerator::GetSupportedProfiles(workarounds);
89@@ -146,8 +150,10 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
90     &GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA,
91 #elif BUILDFLAG(USE_V4L2_CODEC)
92     &GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA,
93+#if !BUILDFLAG(USE_LINUX_V4L2)
94     &GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA,
95 #endif
96+#endif
97
98 #if BUILDFLAG(IS_MAC)
99     &GpuVideoDecodeAcceleratorFactory::CreateVTVDA,
100@@ -207,6 +213,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA(
101   return decoder;
102 }
103
104+#if !BUILDFLAG(USE_LINUX_V4L2)
105 std::unique_ptr<VideoDecodeAccelerator>
106 GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA(
107     const gpu::GpuDriverBugWorkarounds& /*workarounds*/,
108@@ -222,6 +229,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA(
109   return decoder;
110 }
111 #endif
112+#endif
113
114 #if BUILDFLAG(IS_MAC)
115 std::unique_ptr<VideoDecodeAccelerator>
116diff --git a/media/gpu/gpu_video_decode_accelerator_factory.h b/media/gpu/gpu_video_decode_accelerator_factory.h
117index b2e1390c5..5a714eb80 100644
118--- a/media/gpu/gpu_video_decode_accelerator_factory.h
119+++ b/media/gpu/gpu_video_decode_accelerator_factory.h
120@@ -104,11 +104,13 @@ class MEDIA_GPU_EXPORT GpuVideoDecodeAcceleratorFactory {
121       const gpu::GpuDriverBugWorkarounds& workarounds,
122       const gpu::GpuPreferences& gpu_preferences,
123       MediaLog* media_log) const;
124+#if !BUILDFLAG(USE_LINUX_V4L2)
125   std::unique_ptr<VideoDecodeAccelerator> CreateV4L2SliceVDA(
126       const gpu::GpuDriverBugWorkarounds& workarounds,
127       const gpu::GpuPreferences& gpu_preferences,
128       MediaLog* media_log) const;
129 #endif
130+#endif
131 #if BUILDFLAG(IS_MAC)
132   std::unique_ptr<VideoDecodeAccelerator> CreateVTVDA(
133       const gpu::GpuDriverBugWorkarounds& workarounds,
134diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn
135index 80ebde854..0f88f7454 100644
136--- a/media/gpu/v4l2/BUILD.gn
137+++ b/media/gpu/v4l2/BUILD.gn
138@@ -29,9 +29,6 @@ source_set("v4l2") {
139     "buffer_affinity_tracker.h",
140     "generic_v4l2_device.cc",
141     "generic_v4l2_device.h",
142-    "v4l2_decode_surface.cc",
143-    "v4l2_decode_surface.h",
144-    "v4l2_decode_surface_handler.h",
145     "v4l2_device.cc",
146     "v4l2_device.h",
147     "v4l2_device_poller.cc",
148@@ -40,8 +37,6 @@ source_set("v4l2") {
149     "v4l2_framerate_control.h",
150     "v4l2_image_processor_backend.cc",
151     "v4l2_image_processor_backend.h",
152-    "v4l2_slice_video_decode_accelerator.cc",
153-    "v4l2_slice_video_decode_accelerator.h",
154     "v4l2_stateful_workaround.cc",
155     "v4l2_stateful_workaround.h",
156     "v4l2_utils.cc",
157@@ -56,16 +51,33 @@ source_set("v4l2") {
158     "v4l2_video_decoder_backend.h",
159     "v4l2_video_decoder_backend_stateful.cc",
160     "v4l2_video_decoder_backend_stateful.h",
161-    "v4l2_video_decoder_backend_stateless.cc",
162-    "v4l2_video_decoder_backend_stateless.h",
163-    "v4l2_video_decoder_delegate_h264.cc",
164-    "v4l2_video_decoder_delegate_h264.h",
165-    "v4l2_video_decoder_delegate_vp8.cc",
166-    "v4l2_video_decoder_delegate_vp8.h",
167-    "v4l2_video_decoder_delegate_vp9.cc",
168-    "v4l2_video_decoder_delegate_vp9.h",
169   ]
170
171+  if (!use_linux_v4l2_only) {
172+    sources += [
173+      "v4l2_decode_surface.cc",
174+      "v4l2_decode_surface.h",
175+      "v4l2_decode_surface_handler.h",
176+      "v4l2_slice_video_decode_accelerator.cc",
177+      "v4l2_slice_video_decode_accelerator.h",
178+      "v4l2_video_decoder_backend_stateless.cc",
179+      "v4l2_video_decoder_backend_stateless.h",
180+      "v4l2_video_decoder_delegate_h264.cc",
181+      "v4l2_video_decoder_delegate_h264.h",
182+      "v4l2_video_decoder_delegate_vp8.cc",
183+      "v4l2_video_decoder_delegate_vp8.h",
184+      "v4l2_video_decoder_delegate_vp9.cc",
185+      "v4l2_video_decoder_delegate_vp9.h",
186+    ]
187+  } else if (!is_chromeos) {
188+    # HACK(crbug.com/901264): Enable these only when data_offset hack is
189+    # supported in downstream encoder.
190+    sources += [
191+      "v4l2_video_encode_accelerator.cc",
192+      "v4l2_video_encode_accelerator.h",
193+    ]
194+  }
195+
196   if (is_chromeos) {
197     sources += [
198       "v4l2_video_decoder_delegate_h264_legacy.cc",
199diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc
200index 475548bd7..184111288 100644
201--- a/media/gpu/v4l2/generic_v4l2_device.cc
202+++ b/media/gpu/v4l2/generic_v4l2_device.cc
203@@ -441,7 +441,7 @@ bool GenericV4L2Device::OpenDevicePath(const std::string& path, Type type) {
204     return false;
205
206 #if BUILDFLAG(USE_LIBV4L2)
207-  if (type == Type::kEncoder &&
208+  if (/* type == Type::kEncoder && */
209       HANDLE_EINTR(v4l2_fd_open(device_fd_.get(), V4L2_DISABLE_CONVERSION)) !=
210           -1) {
211     DVLOGF(3) << "Using libv4l2 for " << path;
212diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
213index d24013d2e..3669f7176 100644
214--- a/media/gpu/v4l2/v4l2_device.cc
215+++ b/media/gpu/v4l2/v4l2_device.cc
216@@ -1001,10 +1001,12 @@ V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev,
217     return;
218   }
219
220+#if BUILDFLAG(IS_CHROMEOS)
221   if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
222     supports_requests_ = true;
223     DVLOGF(4) << "Queue supports request API.";
224   }
225+#endif
226 }
227
228 V4L2Queue::~V4L2Queue() {
229@@ -1146,9 +1148,13 @@ size_t V4L2Queue::AllocateBuffers(size_t count,
230   reqbufs.count = count;
231   reqbufs.type = type_;
232   reqbufs.memory = memory;
233+#if BUILDFLAG(IS_CHROMEOS)
234   reqbufs.flags = incoherent ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
235   DVQLOGF(3) << "Requesting " << count << " buffers.";
236   DVQLOGF(3) << "Incoherent flag is " << incoherent << ".";
237+#else
238+  DVQLOGF(3) << "Requesting " << count << " buffers.";
239+#endif
240
241   int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
242   if (ret) {
243@@ -1206,7 +1212,9 @@ bool V4L2Queue::DeallocateBuffers() {
244   reqbufs.count = 0;
245   reqbufs.type = type_;
246   reqbufs.memory = memory_;
247+#if BUILDFLAG(IS_CHROMEOS)
248   reqbufs.flags = incoherent_ ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
249+#endif
250
251   int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
252   if (ret) {
253@@ -1551,6 +1559,23 @@ std::string V4L2Device::GetDriverName() {
254 // static
255 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
256                                                    bool slice_based) {
257+#if BUILDFLAG(USE_LINUX_V4L2)
258+  if (slice_based) {
259+    LOG(ERROR) << "Slice not supported";
260+    return 0;
261+  }
262+
263+  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
264+    return V4L2_PIX_FMT_H264;
265+  } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
266+    return V4L2_PIX_FMT_VP8;
267+  } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
268+    return V4L2_PIX_FMT_VP9;
269+  } else {
270+    DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
271+    return 0;
272+  }
273+#else
274   if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
275     if (slice_based)
276       return V4L2_PIX_FMT_H264_SLICE;
277@@ -1570,8 +1595,10 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
278     DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
279     return 0;
280   }
281+#endif
282 }
283
284+#if !BUILDFLAG(USE_LINUX_V4L2)
285 namespace {
286
287 VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
288@@ -1618,9 +1645,11 @@ VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
289 }
290
291 }  // namespace
292+#endif
293
294 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
295     uint32_t pix_fmt) {
296+#if !BUILDFLAG(USE_LINUX_V4L2)
297   auto get_supported_profiles = [this](
298                                     VideoCodec codec,
299                                     std::vector<VideoCodecProfile>* profiles) {
300@@ -1691,6 +1720,27 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
301       VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
302       return {};
303   }
304+#else
305+  std::vector<VideoCodecProfile> profiles;
306+  switch (pix_fmt) {
307+    case V4L2_PIX_FMT_H264:
308+      profiles = {
309+          H264PROFILE_BASELINE,
310+          H264PROFILE_MAIN,
311+          H264PROFILE_HIGH,
312+      };
313+      break;
314+    case V4L2_PIX_FMT_VP8:
315+      profiles = {VP8PROFILE_ANY};
316+      break;
317+    case V4L2_PIX_FMT_VP9:
318+      profiles = {VP9PROFILE_PROFILE0};
319+      break;
320+    default:
321+      VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
322+      return {};
323+  }
324+#endif
325
326   // Erase duplicated profiles.
327   std::sort(profiles.begin(), profiles.end());
328@@ -2403,10 +2453,14 @@ bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) {
329     return false;
330   }
331
332+#if BUILDFLAG(IS_CHROMEOS)
333   ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL;
334   ctrls->request_fd = request_fd_.get();
335
336   return true;
337+#else
338+  return false;
339+#endif
340 }
341
342 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
343@@ -2418,10 +2472,14 @@ bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
344     return false;
345   }
346
347+#if BUILDFLAG(IS_CHROMEOS)
348   buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD;
349   buffer->request_fd = request_fd_.get();
350
351   return true;
352+#else
353+  return false;
354+#endif
355 }
356
357 bool V4L2Request::Submit() {
358@@ -2432,7 +2490,11 @@ bool V4L2Request::Submit() {
359     return false;
360   }
361
362+#if BUILDFLAG(IS_CHROMEOS)
363   return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0;
364+#else
365+  return false;
366+#endif
367 }
368
369 bool V4L2Request::IsCompleted() {
370@@ -2475,6 +2537,7 @@ bool V4L2Request::Reset() {
371     return false;
372   }
373
374+#if BUILDFLAG(IS_CHROMEOS)
375   // Reinit the request to make sure we can use it for a new submission.
376   if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) {
377     VPLOGF(1) << "Failed to reinit request.";
378@@ -2482,6 +2545,9 @@ bool V4L2Request::Reset() {
379   }
380
381   return true;
382+#else
383+  return false;
384+#endif
385 }
386
387 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) {
388@@ -2556,6 +2622,7 @@ V4L2RequestsQueue::~V4L2RequestsQueue() {
389 absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
390   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
391
392+#if BUILDFLAG(IS_CHROMEOS)
393   int request_fd;
394   int ret = HANDLE_EINTR(
395         ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd));
396@@ -2565,6 +2632,9 @@ absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
397   }
398
399   return base::ScopedFD(request_fd);
400+#else
401+  return absl::nullopt;
402+#endif
403 }
404
405 absl::optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() {
406diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc
407index ac21ea7ce..d7cda20b4 100644
408--- a/media/gpu/v4l2/v4l2_video_decoder.cc
409+++ b/media/gpu/v4l2/v4l2_video_decoder.cc
410@@ -28,7 +28,10 @@
411 #include "media/gpu/macros.h"
412 #include "media/gpu/v4l2/v4l2_status.h"
413 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h"
414+
415+#if !BUILDFLAG(USE_LINUX_V4L2)
416 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h"
417+#endif
418
419 namespace media {
420
421@@ -46,7 +49,9 @@ constexpr size_t kNumInputBuffers = 8;
422
423 // Input format V4L2 fourccs this class supports.
424 constexpr uint32_t kSupportedInputFourccs[] = {
425+#if !BUILDFLAG(USE_LINUX_V4L2)
426     V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
427+#endif
428     V4L2_PIX_FMT_H264,       V4L2_PIX_FMT_VP8,       V4L2_PIX_FMT_VP9,
429 };
430
431@@ -322,6 +327,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
432              << " and fourcc: " << FourccToString(input_format_fourcc);
433     backend_ = std::make_unique<V4L2StatefulVideoDecoderBackend>(
434         this, device_, profile_, color_space_, decoder_task_runner_);
435+#if !BUILDFLAG(USE_LINUX_V4L2)
436   } else {
437     DCHECK_EQ(preferred_api_and_format.first, kStateless);
438     VLOGF(1) << "Using a stateless API for profile: "
439@@ -329,6 +335,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
440              << " and fourcc: " << FourccToString(input_format_fourcc);
441     backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>(
442         this, device_, profile_, color_space_, decoder_task_runner_);
443+#endif
444   }
445
446   if (!backend_->Initialize()) {
447--
4482.20.1
449
450