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