1From 6b68dd8ef6cd64487be9a6503cd82a409a31656c 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/14] Add support for V4L2VDA on Linux
5
6This patch enables hardware assisted video decoding via the
7Chromium V4L2VDA. Including changes when Linux is used. In
8order to use this, use_linux_v4l2_only flag should be set
9to true.
10
11Signed-off-by: Ryo Kodama <ryo.kodama.vz@renesas.com>
12
13fixup! avoid building not declared formats
14
15"FRAME", "_SLICE",  "V4L2_PIX_FMT_VP9" are not defined in mainline
16 Linux headers. This patch avoids building these formats.
17
18Signed-off-by: Ryo Kodama <ryo.kodama.vz@renesas.com>
19
20fixup! add V4L2_PIX_FMT_VP9 support back again as it is now
21included in mainline Linux kernel. This allows VP9 codec
22to work with upstream kernel and v4l2 vda. Tested on db820c
23with Venus v4l2 driver.
24
25Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
26Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
27Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
28---
29 .../gpu_mjpeg_decode_accelerator_factory.cc   |  3 +-
30 media/gpu/BUILD.gn                            |  1 +
31 media/gpu/args.gni                            |  4 ++
32 .../gpu_video_decode_accelerator_factory.cc   |  8 +++
33 .../gpu_video_decode_accelerator_factory.h    |  2 +
34 media/gpu/v4l2/BUILD.gn                       | 41 ++++++------
35 media/gpu/v4l2/generic_v4l2_device.cc         |  4 ++
36 media/gpu/v4l2/v4l2_device.cc                 | 66 +++++++++++++++++++
37 media/gpu/v4l2/v4l2_video_decoder.cc          |  7 ++
38 9 files changed, 116 insertions(+), 20 deletions(-)
39
40diff --git a/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc b/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
41index 3772b8ef0..dece6b77f 100644
42--- a/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
43+++ b/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
44@@ -13,7 +13,8 @@
45 #include "media/base/media_switches.h"
46 #include "media/gpu/buildflags.h"
47
48-#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
49+#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY) && \
50+    !BUILDFLAG(USE_LINUX_V4L2)
51 #define USE_V4L2_MJPEG_DECODE_ACCELERATOR
52 #endif
53
54diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
55index 52c22c3fd..8ca11e1c8 100644
56--- a/media/gpu/BUILD.gn
57+++ b/media/gpu/BUILD.gn
58@@ -20,6 +20,7 @@ buildflag_header("buildflags") {
59     "USE_VAAPI_IMAGE_CODECS=$use_vaapi_image_codecs",
60     "USE_V4L2_CODEC=$use_v4l2_codec",
61     "USE_LIBV4L2=$use_v4lplugin",
62+    "USE_LINUX_V4L2=$use_linux_v4l2_only",
63     "USE_VAAPI_X11=$use_vaapi_x11",
64   ]
65 }
66diff --git a/media/gpu/args.gni b/media/gpu/args.gni
67index bb2ff0797..da20cff79 100644
68--- a/media/gpu/args.gni
69+++ b/media/gpu/args.gni
70@@ -21,6 +21,10 @@ declare_args() {
71   # platforms which have v4l2 hardware encoder / decoder.
72   use_v4l2_codec = false
73
74+  # Indicates that only definitions available in the mainline linux kernel
75+  # will be used.
76+  use_linux_v4l2_only = false
77+
78   # Indicates if Video4Linux2 AML encoder is used. This is used for AML
79   # platforms which have v4l2 hardware encoder
80   use_v4l2_codec_aml = false
81diff --git a/media/gpu/gpu_video_decode_accelerator_factory.cc b/media/gpu/gpu_video_decode_accelerator_factory.cc
82index 98f1e2ee7..b7cfffabb 100644
83--- a/media/gpu/gpu_video_decode_accelerator_factory.cc
84+++ b/media/gpu/gpu_video_decode_accelerator_factory.cc
85@@ -29,7 +29,9 @@
86 #include "ui/gl/gl_implementation.h"
87 #elif BUILDFLAG(USE_V4L2_CODEC)
88 #include "media/gpu/v4l2/v4l2_device.h"
89+#if !BUILDFLAG(USE_LINUX_V4L2)
90 #include "media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h"
91+#endif
92 #include "media/gpu/v4l2/v4l2_video_decode_accelerator.h"
93 #include "ui/gl/gl_surface_egl.h"
94 #endif
95@@ -64,10 +66,12 @@ gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilitiesInternal(
96   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
97       V4L2VideoDecodeAccelerator::GetSupportedProfiles(),
98       &capabilities.supported_profiles);
99+#if !BUILDFLAG(USE_LINUX_V4L2)
100   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
101       V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles(),
102       &capabilities.supported_profiles);
103 #endif
104+#endif
105 #elif BUILDFLAG(IS_MAC)
106   capabilities.supported_profiles =
107       VTVideoDecodeAccelerator::GetSupportedProfiles(workarounds);
108@@ -146,8 +150,10 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
109     &GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA,
110 #elif BUILDFLAG(USE_V4L2_CODEC)
111     &GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA,
112+#if !BUILDFLAG(USE_LINUX_V4L2)
113     &GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA,
114 #endif
115+#endif
116
117 #if BUILDFLAG(IS_MAC)
118     &GpuVideoDecodeAcceleratorFactory::CreateVTVDA,
119@@ -207,6 +213,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA(
120   return decoder;
121 }
122
123+#if !BUILDFLAG(USE_LINUX_V4L2)
124 std::unique_ptr<VideoDecodeAccelerator>
125 GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA(
126     const gpu::GpuDriverBugWorkarounds& /*workarounds*/,
127@@ -222,6 +229,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA(
128   return decoder;
129 }
130 #endif
131+#endif
132
133 #if BUILDFLAG(IS_MAC)
134 std::unique_ptr<VideoDecodeAccelerator>
135diff --git a/media/gpu/gpu_video_decode_accelerator_factory.h b/media/gpu/gpu_video_decode_accelerator_factory.h
136index b2e1390c5..5a714eb80 100644
137--- a/media/gpu/gpu_video_decode_accelerator_factory.h
138+++ b/media/gpu/gpu_video_decode_accelerator_factory.h
139@@ -104,11 +104,13 @@ class MEDIA_GPU_EXPORT GpuVideoDecodeAcceleratorFactory {
140       const gpu::GpuDriverBugWorkarounds& workarounds,
141       const gpu::GpuPreferences& gpu_preferences,
142       MediaLog* media_log) const;
143+#if !BUILDFLAG(USE_LINUX_V4L2)
144   std::unique_ptr<VideoDecodeAccelerator> CreateV4L2SliceVDA(
145       const gpu::GpuDriverBugWorkarounds& workarounds,
146       const gpu::GpuPreferences& gpu_preferences,
147       MediaLog* media_log) const;
148 #endif
149+#endif
150 #if BUILDFLAG(IS_MAC)
151   std::unique_ptr<VideoDecodeAccelerator> CreateVTVDA(
152       const gpu::GpuDriverBugWorkarounds& workarounds,
153diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn
154index 50d81e483..3a47d1166 100644
155--- a/media/gpu/v4l2/BUILD.gn
156+++ b/media/gpu/v4l2/BUILD.gn
157@@ -28,9 +28,6 @@ source_set("v4l2") {
158     "buffer_affinity_tracker.h",
159     "generic_v4l2_device.cc",
160     "generic_v4l2_device.h",
161-    "v4l2_decode_surface.cc",
162-    "v4l2_decode_surface.h",
163-    "v4l2_decode_surface_handler.h",
164     "v4l2_device.cc",
165     "v4l2_device.h",
166     "v4l2_device_poller.cc",
167@@ -39,8 +36,6 @@ source_set("v4l2") {
168     "v4l2_framerate_control.h",
169     "v4l2_image_processor_backend.cc",
170     "v4l2_image_processor_backend.h",
171-    "v4l2_slice_video_decode_accelerator.cc",
172-    "v4l2_slice_video_decode_accelerator.h",
173     "v4l2_stateful_workaround.cc",
174     "v4l2_stateful_workaround.h",
175     "v4l2_utils.cc",
176@@ -55,24 +50,32 @@ source_set("v4l2") {
177     "v4l2_video_decoder_backend.h",
178     "v4l2_video_decoder_backend_stateful.cc",
179     "v4l2_video_decoder_backend_stateful.h",
180-    "v4l2_video_decoder_backend_stateless.cc",
181-    "v4l2_video_decoder_backend_stateless.h",
182-    "v4l2_video_decoder_delegate_h264.cc",
183-    "v4l2_video_decoder_delegate_h264.h",
184-    "v4l2_video_decoder_delegate_h264_legacy.cc",
185-    "v4l2_video_decoder_delegate_h264_legacy.h",
186-    "v4l2_video_decoder_delegate_vp8.cc",
187-    "v4l2_video_decoder_delegate_vp8.h",
188-    "v4l2_video_decoder_delegate_vp8_legacy.cc",
189-    "v4l2_video_decoder_delegate_vp8_legacy.h",
190-    "v4l2_video_decoder_delegate_vp9.cc",
191-    "v4l2_video_decoder_delegate_vp9.h",
192-    "v4l2_video_decoder_delegate_vp9_legacy.cc",
193-    "v4l2_video_decoder_delegate_vp9_legacy.h",
194     "v4l2_video_encode_accelerator.cc",
195     "v4l2_video_encode_accelerator.h",
196   ]
197
198+  if (!use_linux_v4l2_only) {
199+    sources += [
200+      "v4l2_slice_video_decode_accelerator.cc",
201+      "v4l2_slice_video_decode_accelerator.h",
202+      "v4l2_video_decoder_backend_stateless.cc",
203+      "v4l2_video_decoder_backend_stateless.h",
204+      "v4l2_video_decoder_delegate_h264.cc",
205+      "v4l2_video_decoder_delegate_h264.h",
206+      "v4l2_video_decoder_delegate_h264_legacy.cc",
207+      "v4l2_video_decoder_delegate_h264_legacy.h",
208+      "v4l2_video_decoder_delegate_vp8.cc",
209+      "v4l2_video_decoder_delegate_vp8.h",
210+      "v4l2_video_decoder_delegate_vp8_legacy.cc",
211+      "v4l2_video_decoder_delegate_vp8_legacy.h",
212+      "v4l2_video_decoder_delegate_vp9.cc",
213+      "v4l2_video_decoder_delegate_vp9.h",
214+      "v4l2_video_decoder_delegate_vp9_legacy.cc",
215+      "v4l2_video_decoder_delegate_vp9_legacy.h",
216+    ]
217+  }
218+
219+
220   libs = [
221     "EGL",
222     "GLESv2",
223diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc
224index a6fe9d914..becf30c9c 100644
225--- a/media/gpu/v4l2/generic_v4l2_device.cc
226+++ b/media/gpu/v4l2/generic_v4l2_device.cc
227@@ -440,7 +440,11 @@ bool GenericV4L2Device::OpenDevicePath(const std::string& path, Type type) {
228     return false;
229
230 #if BUILDFLAG(USE_LIBV4L2)
231+#if BUILDFLAG(USE_LINUX_V4L2)
232+  if (
233+#else
234   if (type == Type::kEncoder &&
235+#endif
236       HANDLE_EINTR(v4l2_fd_open(device_fd_.get(), V4L2_DISABLE_CONVERSION)) !=
237           -1) {
238     DVLOGF(3) << "Using libv4l2 for " << path;
239diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
240index de2800fda..866c79e4d 100644
241--- a/media/gpu/v4l2/v4l2_device.cc
242+++ b/media/gpu/v4l2/v4l2_device.cc
243@@ -853,7 +853,9 @@ void V4L2WritableBufferRef::SetConfigStore(uint32_t config_store) {
244   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
245   DCHECK(buffer_data_);
246
247+#if !BUILDFLAG(USE_LINUX_V4L2)
248   buffer_data_->v4l2_buffer_.config_store = config_store;
249+#endif
250 }
251
252 V4L2ReadableBuffer::V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer,
253@@ -996,10 +998,12 @@ V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev,
254     return;
255   }
256
257+#if !BUILDFLAG(USE_LINUX_V4L2)
258   if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
259     supports_requests_ = true;
260     DVLOGF(4) << "Queue supports request API.";
261   }
262+#endif
263 }
264
265 V4L2Queue::~V4L2Queue() {
266@@ -1539,6 +1543,23 @@ std::string V4L2Device::GetDriverName() {
267 // static
268 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
269                                                    bool slice_based) {
270+#if BUILDFLAG(USE_LINUX_V4L2)
271+  if (slice_based) {
272+    LOG(ERROR) << "Slice not supported";
273+    return 0;
274+  }
275+
276+  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
277+    return V4L2_PIX_FMT_H264;
278+  } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
279+    return V4L2_PIX_FMT_VP8;
280+  } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
281+    return V4L2_PIX_FMT_VP9;
282+  } else {
283+    DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
284+    return 0;
285+  }
286+#else
287   if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
288     if (slice_based)
289       return V4L2_PIX_FMT_H264_SLICE;
290@@ -1558,8 +1579,10 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
291     DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
292     return 0;
293   }
294+#endif
295 }
296
297+#if !BUILDFLAG(USE_LINUX_V4L2)
298 namespace {
299
300 VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
301@@ -1606,9 +1629,11 @@ VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
302 }
303
304 }  // namespace
305+#endif
306
307 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
308     uint32_t pix_fmt) {
309+#if !BUILDFLAG(USE_LINUX_V4L2)
310   auto get_supported_profiles = [this](
311                                     VideoCodec codec,
312                                     std::vector<VideoCodecProfile>* profiles) {
313@@ -1679,6 +1704,27 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
314       VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
315       return {};
316   }
317+#else
318+  std::vector<VideoCodecProfile> profiles;
319+  switch (pix_fmt) {
320+    case V4L2_PIX_FMT_H264:
321+      profiles = {
322+          H264PROFILE_BASELINE,
323+          H264PROFILE_MAIN,
324+          H264PROFILE_HIGH,
325+      };
326+      break;
327+    case V4L2_PIX_FMT_VP8:
328+      profiles = {VP8PROFILE_ANY};
329+      break;
330+    case V4L2_PIX_FMT_VP9:
331+      profiles = {VP9PROFILE_PROFILE0};
332+      break;
333+    default:
334+      VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
335+      return {};
336+  }
337+#endif
338
339   // Erase duplicated profiles.
340   std::sort(profiles.begin(), profiles.end());
341@@ -2346,10 +2392,14 @@ bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) {
342     return false;
343   }
344
345+#if !BUILDFLAG(USE_LINUX_V4L2)
346   ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL;
347   ctrls->request_fd = request_fd_.get();
348
349   return true;
350+#else
351+  return false;
352+#endif
353 }
354
355 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
356@@ -2361,10 +2411,14 @@ bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
357     return false;
358   }
359
360+#if !BUILDFLAG(USE_LINUX_V4L2)
361   buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD;
362   buffer->request_fd = request_fd_.get();
363
364   return true;
365+#else
366+  return false;
367+#endif
368 }
369
370 bool V4L2Request::Submit() {
371@@ -2375,7 +2429,11 @@ bool V4L2Request::Submit() {
372     return false;
373   }
374
375+#if !BUILDFLAG(USE_LINUX_V4L2)
376   return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0;
377+#else
378+  return false;
379+#endif
380 }
381
382 bool V4L2Request::IsCompleted() {
383@@ -2418,6 +2476,7 @@ bool V4L2Request::Reset() {
384     return false;
385   }
386
387+#if !BUILDFLAG(USE_LINUX_V4L2)
388   // Reinit the request to make sure we can use it for a new submission.
389   if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) {
390     VPLOGF(1) << "Failed to reinit request.";
391@@ -2425,6 +2484,9 @@ bool V4L2Request::Reset() {
392   }
393
394   return true;
395+#else
396+  return false;
397+#endif
398 }
399
400 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) {
401@@ -2499,6 +2561,7 @@ V4L2RequestsQueue::~V4L2RequestsQueue() {
402 absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
403   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
404
405+#if !BUILDFLAG(USE_LINUX_V4L2)
406   int request_fd;
407   int ret = HANDLE_EINTR(
408         ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd));
409@@ -2508,6 +2571,9 @@ absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
410   }
411
412   return base::ScopedFD(request_fd);
413+#else
414+  return absl::nullopt;
415+#endif
416 }
417
418 absl::optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() {
419diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc
420index 7f4c9f244..e887fb896 100644
421--- a/media/gpu/v4l2/v4l2_video_decoder.cc
422+++ b/media/gpu/v4l2/v4l2_video_decoder.cc
423@@ -27,7 +27,10 @@
424 #include "media/gpu/macros.h"
425 #include "media/gpu/v4l2/v4l2_status.h"
426 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h"
427+
428+#if !BUILDFLAG(USE_LINUX_V4L2)
429 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h"
430+#endif
431
432 namespace media {
433
434@@ -45,7 +48,9 @@ constexpr size_t kNumInputBuffers = 8;
435
436 // Input format V4L2 fourccs this class supports.
437 constexpr uint32_t kSupportedInputFourccs[] = {
438+#if !BUILDFLAG(USE_LINUX_V4L2)
439     V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
440+#endif
441     V4L2_PIX_FMT_H264,       V4L2_PIX_FMT_VP8,       V4L2_PIX_FMT_VP9,
442 };
443
444@@ -319,6 +324,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
445              << " and fourcc: " << FourccToString(input_format_fourcc);
446     backend_ = std::make_unique<V4L2StatefulVideoDecoderBackend>(
447         this, device_, profile_, color_space_, decoder_task_runner_);
448+#if !BUILDFLAG(USE_LINUX_V4L2)
449   } else {
450     DCHECK_EQ(preferred_api_and_format.first, kStateless);
451     VLOGF(1) << "Using a stateless API for profile: "
452@@ -326,6 +332,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
453              << " and fourcc: " << FourccToString(input_format_fourcc);
454     backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>(
455         this, device_, profile_, color_space_, decoder_task_runner_);
456+#endif
457   }
458
459   if (!backend_->Initialize()) {
460--
4612.20.1
462
463