1From f62053a3a3cc31905586e657edcac18f4c6ad8e4 Mon Sep 17 00:00:00 2001
2From: Maksim Sisov <msisov@igalia.com>
3Date: Wed, 31 Jul 2019 09:56:24 +0300
4Subject: [PATCH 02/17] 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                       | 43 ++++++------
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, 118 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 30267d96c..0c8f78de1 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 0e55ef47e..2096dc619 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 defined(OS_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 defined(OS_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 defined(OS_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 a80cac212..1021af34a 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 defined(OS_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 0322bbf7f..e7a8743d4 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,24 +51,34 @@ 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_chromium.cc",
191-    "v4l2_video_decoder_delegate_vp9_chromium.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_decode_surface.cc",
201+      "v4l2_decode_surface.h",
202+      "v4l2_decode_surface_handler.h",
203+      "v4l2_slice_video_decode_accelerator.cc",
204+      "v4l2_slice_video_decode_accelerator.h",
205+      "v4l2_video_decoder_backend_stateless.cc",
206+      "v4l2_video_decoder_backend_stateless.h",
207+      "v4l2_video_decoder_delegate_h264.cc",
208+      "v4l2_video_decoder_delegate_h264.h",
209+      "v4l2_video_decoder_delegate_h264_legacy.cc",
210+      "v4l2_video_decoder_delegate_h264_legacy.h",
211+      "v4l2_video_decoder_delegate_vp8.cc",
212+      "v4l2_video_decoder_delegate_vp8.h",
213+      "v4l2_video_decoder_delegate_vp8_legacy.cc",
214+      "v4l2_video_decoder_delegate_vp8_legacy.h",
215+      "v4l2_video_decoder_delegate_vp9_chromium.cc",
216+      "v4l2_video_decoder_delegate_vp9_chromium.h",
217+      "v4l2_video_decoder_delegate_vp9_legacy.cc",
218+      "v4l2_video_decoder_delegate_vp9_legacy.h",
219+    ]
220+  }
221+
222   libs = [
223     "EGL",
224     "GLESv2",
225diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc
226index b64c9bd0f..92ec1b607 100644
227--- a/media/gpu/v4l2/generic_v4l2_device.cc
228+++ b/media/gpu/v4l2/generic_v4l2_device.cc
229@@ -441,7 +441,11 @@ bool GenericV4L2Device::OpenDevicePath(const std::string& path, Type type) {
230     return false;
231
232 #if BUILDFLAG(USE_LIBV4L2)
233+#if BUILDFLAG(USE_LINUX_V4L2)
234+  if (
235+#else
236   if (type == Type::kEncoder &&
237+#endif
238       HANDLE_EINTR(v4l2_fd_open(device_fd_.get(), V4L2_DISABLE_CONVERSION)) !=
239           -1) {
240     DVLOGF(3) << "Using libv4l2 for " << path;
241diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
242index ee99d095f..98a0d51fa 100644
243--- a/media/gpu/v4l2/v4l2_device.cc
244+++ b/media/gpu/v4l2/v4l2_device.cc
245@@ -853,7 +853,9 @@ void V4L2WritableBufferRef::SetConfigStore(uint32_t config_store) {
246   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
247   DCHECK(buffer_data_);
248
249+#if !BUILDFLAG(USE_LINUX_V4L2)
250   buffer_data_->v4l2_buffer_.config_store = config_store;
251+#endif
252 }
253
254 V4L2ReadableBuffer::V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer,
255@@ -996,10 +998,12 @@ V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev,
256     return;
257   }
258
259+#if !BUILDFLAG(USE_LINUX_V4L2)
260   if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
261     supports_requests_ = true;
262     DVLOGF(4) << "Queue supports request API.";
263   }
264+#endif
265 }
266
267 V4L2Queue::~V4L2Queue() {
268@@ -1527,6 +1531,23 @@ scoped_refptr<V4L2Device> V4L2Device::Create() {
269 // static
270 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
271                                                    bool slice_based) {
272+#if BUILDFLAG(USE_LINUX_V4L2)
273+  if (slice_based) {
274+    LOG(ERROR) << "Slice not supported";
275+    return 0;
276+  }
277+
278+  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
279+    return V4L2_PIX_FMT_H264;
280+  } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
281+    return V4L2_PIX_FMT_VP8;
282+  } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
283+    return V4L2_PIX_FMT_VP9;
284+  } else {
285+    DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
286+    return 0;
287+  }
288+#else
289   if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
290     if (slice_based)
291       return V4L2_PIX_FMT_H264_SLICE;
292@@ -1546,8 +1567,10 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
293     DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
294     return 0;
295   }
296+#endif
297 }
298
299+#if !BUILDFLAG(USE_LINUX_V4L2)
300 namespace {
301
302 VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
303@@ -1594,9 +1617,11 @@ VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
304 }
305
306 }  // namespace
307+#endif
308
309 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
310     uint32_t pix_fmt) {
311+#if !BUILDFLAG(USE_LINUX_V4L2)
312   auto get_supported_profiles = [this](
313                                     VideoCodec codec,
314                                     std::vector<VideoCodecProfile>* profiles) {
315@@ -1667,6 +1692,27 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
316       VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
317       return {};
318   }
319+#else
320+  std::vector<VideoCodecProfile> profiles;
321+  switch (pix_fmt) {
322+    case V4L2_PIX_FMT_H264:
323+      profiles = {
324+          H264PROFILE_BASELINE,
325+          H264PROFILE_MAIN,
326+          H264PROFILE_HIGH,
327+      };
328+      break;
329+    case V4L2_PIX_FMT_VP8:
330+      profiles = {VP8PROFILE_ANY};
331+      break;
332+    case V4L2_PIX_FMT_VP9:
333+      profiles = {VP9PROFILE_PROFILE0};
334+      break;
335+    default:
336+      VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
337+      return {};
338+  }
339+#endif
340
341   // Erase duplicated profiles.
342   std::sort(profiles.begin(), profiles.end());
343@@ -2334,10 +2380,14 @@ bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) {
344     return false;
345   }
346
347+#if !BUILDFLAG(USE_LINUX_V4L2)
348   ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL;
349   ctrls->request_fd = request_fd_.get();
350
351   return true;
352+#else
353+  return false;
354+#endif
355 }
356
357 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
358@@ -2349,10 +2399,14 @@ bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
359     return false;
360   }
361
362+#if !BUILDFLAG(USE_LINUX_V4L2)
363   buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD;
364   buffer->request_fd = request_fd_.get();
365
366   return true;
367+#else
368+  return false;
369+#endif
370 }
371
372 bool V4L2Request::Submit() {
373@@ -2363,7 +2417,11 @@ bool V4L2Request::Submit() {
374     return false;
375   }
376
377+#if !BUILDFLAG(USE_LINUX_V4L2)
378   return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0;
379+#else
380+  return false;
381+#endif
382 }
383
384 bool V4L2Request::IsCompleted() {
385@@ -2406,6 +2464,7 @@ bool V4L2Request::Reset() {
386     return false;
387   }
388
389+#if !BUILDFLAG(USE_LINUX_V4L2)
390   // Reinit the request to make sure we can use it for a new submission.
391   if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) {
392     VPLOGF(1) << "Failed to reinit request.";
393@@ -2413,6 +2472,9 @@ bool V4L2Request::Reset() {
394   }
395
396   return true;
397+#else
398+  return false;
399+#endif
400 }
401
402 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) {
403@@ -2487,6 +2549,7 @@ V4L2RequestsQueue::~V4L2RequestsQueue() {
404 absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
405   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
406
407+#if !BUILDFLAG(USE_LINUX_V4L2)
408   int request_fd;
409   int ret = HANDLE_EINTR(
410         ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd));
411@@ -2496,6 +2559,9 @@ absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
412   }
413
414   return base::ScopedFD(request_fd);
415+#else
416+  return absl::nullopt;
417+#endif
418 }
419
420 absl::optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() {
421diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc
422index 7534052f9..afde6b8e4 100644
423--- a/media/gpu/v4l2/v4l2_video_decoder.cc
424+++ b/media/gpu/v4l2/v4l2_video_decoder.cc
425@@ -27,7 +27,10 @@
426 #include "media/gpu/macros.h"
427 #include "media/gpu/v4l2/v4l2_status.h"
428 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h"
429+
430+#if !BUILDFLAG(USE_LINUX_V4L2)
431 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h"
432+#endif
433
434 namespace media {
435
436@@ -45,7 +48,9 @@ constexpr size_t kNumInputBuffers = 8;
437
438 // Input format V4L2 fourccs this class supports.
439 constexpr uint32_t kSupportedInputFourccs[] = {
440+#if !BUILDFLAG(USE_LINUX_V4L2)
441     V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
442+#endif
443     V4L2_PIX_FMT_H264,       V4L2_PIX_FMT_VP8,       V4L2_PIX_FMT_VP9,
444 };
445
446@@ -317,6 +322,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
447              << " and fourcc: " << FourccToString(input_format_fourcc);
448     backend_ = std::make_unique<V4L2StatefulVideoDecoderBackend>(
449         this, device_, profile_, decoder_task_runner_);
450+#if !BUILDFLAG(USE_LINUX_V4L2)
451   } else {
452     DCHECK_EQ(preferred_api_and_format.first, kStateless);
453     VLOGF(1) << "Using a stateless API for profile: "
454@@ -324,6 +330,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() {
455              << " and fourcc: " << FourccToString(input_format_fourcc);
456     backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>(
457         this, device_, profile_, decoder_task_runner_);
458+#endif
459   }
460
461   if (!backend_->Initialize()) {
462--
4632.20.1
464
465