1From 8c13cc78f1deb0d3b22eb50021e57f73ed43173b 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/15] 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                       | 42 ++++++------
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, 115 insertions(+), 22 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 78d151fa6..101e2e4f9 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 6687b1186..951478638 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 65e5f58d1..bde4c169d 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_status.h",
176@@ -56,26 +51,31 @@ 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_chromium.cc",
193-    "v4l2_video_decoder_delegate_vp9_chromium.h",
194-    "v4l2_video_decoder_delegate_vp9_legacy.cc",
195-    "v4l2_video_decoder_delegate_vp9_legacy.h",
196     "v4l2_video_encode_accelerator.cc",
197     "v4l2_video_encode_accelerator.h",
198   ]
199
200+  if (!use_linux_v4l2_only) {
201+    sources += [
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_chromium.cc",
215+      "v4l2_video_decoder_delegate_vp9_chromium.h",
216+      "v4l2_video_decoder_delegate_vp9_legacy.cc",
217+      "v4l2_video_decoder_delegate_vp9_legacy.h",
218+    ]
219+  }
220+
221   libs = [
222     "EGL",
223     "GLESv2",
224diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc
225index a6fe9d914..becf30c9c 100644
226--- a/media/gpu/v4l2/generic_v4l2_device.cc
227+++ b/media/gpu/v4l2/generic_v4l2_device.cc
228@@ -440,7 +440,11 @@ bool GenericV4L2Device::OpenDevicePath(const std::string& path, Type type) {
229     return false;
230
231 #if BUILDFLAG(USE_LIBV4L2)
232+#if BUILDFLAG(USE_LINUX_V4L2)
233+  if (
234+#else
235   if (type == Type::kEncoder &&
236+#endif
237       HANDLE_EINTR(v4l2_fd_open(device_fd_.get(), V4L2_DISABLE_CONVERSION)) !=
238           -1) {
239     DVLOGF(3) << "Using libv4l2 for " << path;
240diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
241index de2800fda..866c79e4d 100644
242--- a/media/gpu/v4l2/v4l2_device.cc
243+++ b/media/gpu/v4l2/v4l2_device.cc
244@@ -853,7 +853,9 @@ void V4L2WritableBufferRef::SetConfigStore(uint32_t config_store) {
245   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
246   DCHECK(buffer_data_);
247
248+#if !BUILDFLAG(USE_LINUX_V4L2)
249   buffer_data_->v4l2_buffer_.config_store = config_store;
250+#endif
251 }
252
253 V4L2ReadableBuffer::V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer,
254@@ -996,10 +998,12 @@ V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev,
255     return;
256   }
257
258+#if !BUILDFLAG(USE_LINUX_V4L2)
259   if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
260     supports_requests_ = true;
261     DVLOGF(4) << "Queue supports request API.";
262   }
263+#endif
264 }
265
266 V4L2Queue::~V4L2Queue() {
267@@ -1539,6 +1543,23 @@ std::string V4L2Device::GetDriverName() {
268 // static
269 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
270                                                    bool slice_based) {
271+#if BUILDFLAG(USE_LINUX_V4L2)
272+  if (slice_based) {
273+    LOG(ERROR) << "Slice not supported";
274+    return 0;
275+  }
276+
277+  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
278+    return V4L2_PIX_FMT_H264;
279+  } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
280+    return V4L2_PIX_FMT_VP8;
281+  } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
282+    return V4L2_PIX_FMT_VP9;
283+  } else {
284+    DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
285+    return 0;
286+  }
287+#else
288   if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
289     if (slice_based)
290       return V4L2_PIX_FMT_H264_SLICE;
291@@ -1558,8 +1579,10 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
292     DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
293     return 0;
294   }
295+#endif
296 }
297
298+#if !BUILDFLAG(USE_LINUX_V4L2)
299 namespace {
300
301 VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
302@@ -1606,9 +1629,11 @@ VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
303 }
304
305 }  // namespace
306+#endif
307
308 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
309     uint32_t pix_fmt) {
310+#if !BUILDFLAG(USE_LINUX_V4L2)
311   auto get_supported_profiles = [this](
312                                     VideoCodec codec,
313                                     std::vector<VideoCodecProfile>* profiles) {
314@@ -1679,6 +1704,27 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
315       VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
316       return {};
317   }
318+#else
319+  std::vector<VideoCodecProfile> profiles;
320+  switch (pix_fmt) {
321+    case V4L2_PIX_FMT_H264:
322+      profiles = {
323+          H264PROFILE_BASELINE,
324+          H264PROFILE_MAIN,
325+          H264PROFILE_HIGH,
326+      };
327+      break;
328+    case V4L2_PIX_FMT_VP8:
329+      profiles = {VP8PROFILE_ANY};
330+      break;
331+    case V4L2_PIX_FMT_VP9:
332+      profiles = {VP9PROFILE_PROFILE0};
333+      break;
334+    default:
335+      VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
336+      return {};
337+  }
338+#endif
339
340   // Erase duplicated profiles.
341   std::sort(profiles.begin(), profiles.end());
342@@ -2346,10 +2392,14 @@ bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) {
343     return false;
344   }
345
346+#if !BUILDFLAG(USE_LINUX_V4L2)
347   ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL;
348   ctrls->request_fd = request_fd_.get();
349
350   return true;
351+#else
352+  return false;
353+#endif
354 }
355
356 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
357@@ -2361,10 +2411,14 @@ bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
358     return false;
359   }
360
361+#if !BUILDFLAG(USE_LINUX_V4L2)
362   buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD;
363   buffer->request_fd = request_fd_.get();
364
365   return true;
366+#else
367+  return false;
368+#endif
369 }
370
371 bool V4L2Request::Submit() {
372@@ -2375,7 +2429,11 @@ bool V4L2Request::Submit() {
373     return false;
374   }
375
376+#if !BUILDFLAG(USE_LINUX_V4L2)
377   return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0;
378+#else
379+  return false;
380+#endif
381 }
382
383 bool V4L2Request::IsCompleted() {
384@@ -2418,6 +2476,7 @@ bool V4L2Request::Reset() {
385     return false;
386   }
387
388+#if !BUILDFLAG(USE_LINUX_V4L2)
389   // Reinit the request to make sure we can use it for a new submission.
390   if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) {
391     VPLOGF(1) << "Failed to reinit request.";
392@@ -2425,6 +2484,9 @@ bool V4L2Request::Reset() {
393   }
394
395   return true;
396+#else
397+  return false;
398+#endif
399 }
400
401 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) {
402@@ -2499,6 +2561,7 @@ V4L2RequestsQueue::~V4L2RequestsQueue() {
403 absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
404   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
405
406+#if !BUILDFLAG(USE_LINUX_V4L2)
407   int request_fd;
408   int ret = HANDLE_EINTR(
409         ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd));
410@@ -2508,6 +2571,9 @@ absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
411   }
412
413   return base::ScopedFD(request_fd);
414+#else
415+  return absl::nullopt;
416+#endif
417 }
418
419 absl::optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() {
420diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc
421index 057b28663..1df3f1a5c 100644
422--- a/media/gpu/v4l2/v4l2_video_decoder.cc
423+++ b/media/gpu/v4l2/v4l2_video_decoder.cc
424@@ -28,7 +28,10 @@
425 #include "media/gpu/macros.h"
426 #include "media/gpu/v4l2/v4l2_status.h"
427 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h"
428+
429+#if !BUILDFLAG(USE_LINUX_V4L2)
430 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h"
431+#endif
432
433 namespace media {
434
435@@ -46,7 +49,9 @@ constexpr size_t kNumInputBuffers = 8;
436
437 // Input format V4L2 fourccs this class supports.
438 constexpr uint32_t kSupportedInputFourccs[] = {
439+#if !BUILDFLAG(USE_LINUX_V4L2)
440     V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
441+#endif
442     V4L2_PIX_FMT_H264,       V4L2_PIX_FMT_VP8,       V4L2_PIX_FMT_VP9,
443 };
444
445@@ -320,6 +325,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
446              << " and fourcc: " << FourccToString(input_format_fourcc);
447     backend_ = std::make_unique<V4L2StatefulVideoDecoderBackend>(
448         this, device_, profile_, color_space_, decoder_task_runner_);
449+#if !BUILDFLAG(USE_LINUX_V4L2)
450   } else {
451     DCHECK_EQ(preferred_api_and_format.first, kStateless);
452     VLOGF(1) << "Using a stateless API for profile: "
453@@ -327,6 +333,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
454              << " and fourcc: " << FourccToString(input_format_fourcc);
455     backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>(
456         this, device_, profile_, color_space_, decoder_task_runner_);
457+#endif
458   }
459
460   if (!backend_->Initialize()) {
461--
4622.20.1
463
464