1From be3074eaa6255f8579e6830f22d78a405207e4c2 Mon Sep 17 00:00:00 2001
2From: Maksim Sisov <msisov@igalia.com>
3Date: Wed, 31 Jul 2019 09:56:24 +0300
4Subject: [PATCH 04/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 chromium/media/gpu/BUILD.gn                   |  1 +
31 chromium/media/gpu/args.gni                   |  4 ++
32 .../gpu_video_decode_accelerator_factory.cc   |  8 +++
33 .../gpu_video_decode_accelerator_factory.h    |  2 +
34 chromium/media/gpu/v4l2/BUILD.gn              | 39 +++++-----
35 .../media/gpu/v4l2/generic_v4l2_device.cc     |  4 ++
36 chromium/media/gpu/v4l2/v4l2_device.cc        | 72 +++++++++++++++++++
37 chromium/media/gpu/v4l2/v4l2_video_decoder.cc |  7 ++
38 9 files changed, 122 insertions(+), 18 deletions(-)
39
40diff --git a/chromium/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc b/chromium/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
41index 6f319e889..4f8f0b7d0 100644
42--- a/chromium/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc
43+++ b/chromium/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/chromium/media/gpu/BUILD.gn b/chromium/media/gpu/BUILD.gn
55index b1a84b1ad..1edccb7ab 100644
56--- a/chromium/media/gpu/BUILD.gn
57+++ b/chromium/media/gpu/BUILD.gn
58@@ -18,6 +18,7 @@ buildflag_header("buildflags") {
59     "USE_VAAPI=$use_vaapi",
60     "USE_V4L2_CODEC=$use_v4l2_codec",
61     "USE_LIBV4L2=$use_v4lplugin",
62+    "USE_LINUX_V4L2=$use_linux_v4l2_only",
63   ]
64 }
65
66diff --git a/chromium/media/gpu/args.gni b/chromium/media/gpu/args.gni
67index 2a87b9980..7e905aebb 100644
68--- a/chromium/media/gpu/args.gni
69+++ b/chromium/media/gpu/args.gni
70@@ -10,6 +10,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/chromium/media/gpu/gpu_video_decode_accelerator_factory.cc b/chromium/media/gpu/gpu_video_decode_accelerator_factory.cc
82index a24ee0fe3..b085ebbbe 100644
83--- a/chromium/media/gpu/gpu_video_decode_accelerator_factory.cc
84+++ b/chromium/media/gpu/gpu_video_decode_accelerator_factory.cc
85@@ -26,7 +26,9 @@
86 #endif
87 #if 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@@ -63,10 +65,12 @@ gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilitiesInternal(
96   vda_profiles = V4L2VideoDecodeAccelerator::GetSupportedProfiles();
97   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
98       vda_profiles, &capabilities.supported_profiles);
99+#if !BUILDFLAG(USE_LINUX_V4L2)
100   vda_profiles = V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles();
101   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
102       vda_profiles, &capabilities.supported_profiles);
103 #endif
104+#endif
105 #if BUILDFLAG(USE_VAAPI)
106   vda_profiles = VaapiVideoDecodeAccelerator::GetSupportedProfiles(workarounds);
107   GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
108@@ -147,8 +151,10 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
109 #endif
110 #if BUILDFLAG(USE_V4L2_CODEC)
111     &GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA,
112+#if !BUILDFLAG(USE_LINUX_V4L2)
113     &GpuVideoDecodeAcceleratorFactory::CreateV4L2SVDA,
114 #endif
115+#endif
116 #if defined(OS_MAC)
117     &GpuVideoDecodeAcceleratorFactory::CreateVTVDA,
118 #endif
119@@ -196,6 +202,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA(
120   return decoder;
121 }
122
123+#if !BUILDFLAG(USE_LINUX_V4L2)
124 std::unique_ptr<VideoDecodeAccelerator>
125 GpuVideoDecodeAcceleratorFactory::CreateV4L2SVDA(
126     const gpu::GpuDriverBugWorkarounds& workarounds,
127@@ -211,6 +218,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2SVDA(
128   return decoder;
129 }
130 #endif
131+#endif
132
133 #if BUILDFLAG(USE_VAAPI)
134 std::unique_ptr<VideoDecodeAccelerator>
135diff --git a/chromium/media/gpu/gpu_video_decode_accelerator_factory.h b/chromium/media/gpu/gpu_video_decode_accelerator_factory.h
136index b2721b7d1..613906486 100644
137--- a/chromium/media/gpu/gpu_video_decode_accelerator_factory.h
138+++ b/chromium/media/gpu/gpu_video_decode_accelerator_factory.h
139@@ -92,11 +92,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> CreateV4L2SVDA(
145       const gpu::GpuDriverBugWorkarounds& workarounds,
146       const gpu::GpuPreferences& gpu_preferences,
147       MediaLog* media_log) const;
148 #endif
149+#endif
150 #if BUILDFLAG(USE_VAAPI)
151   std::unique_ptr<VideoDecodeAccelerator> CreateVaapiVDA(
152       const gpu::GpuDriverBugWorkarounds& workarounds,
153diff --git a/chromium/media/gpu/v4l2/BUILD.gn b/chromium/media/gpu/v4l2/BUILD.gn
154index 9a999e43a..9cf40f5c5 100644
155--- a/chromium/media/gpu/v4l2/BUILD.gn
156+++ b/chromium/media/gpu/v4l2/BUILD.gn
157@@ -27,21 +27,12 @@ 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     "v4l2_device_poller.h",
168-    "v4l2_h264_accelerator.cc",
169-    "v4l2_h264_accelerator.h",
170-    "v4l2_h264_accelerator_legacy.cc",
171-    "v4l2_h264_accelerator_legacy.h",
172     "v4l2_image_processor_backend.cc",
173     "v4l2_image_processor_backend.h",
174-    "v4l2_slice_video_decode_accelerator.cc",
175-    "v4l2_slice_video_decode_accelerator.h",
176     "v4l2_stateful_workaround.cc",
177     "v4l2_stateful_workaround.h",
178     "v4l2_vda_helpers.cc",
179@@ -54,18 +45,32 @@ source_set("v4l2") {
180     "v4l2_video_decoder_backend.h",
181     "v4l2_video_decoder_backend_stateful.cc",
182     "v4l2_video_decoder_backend_stateful.h",
183-    "v4l2_video_decoder_backend_stateless.cc",
184-    "v4l2_video_decoder_backend_stateless.h",
185     "v4l2_video_encode_accelerator.cc",
186     "v4l2_video_encode_accelerator.h",
187-    "v4l2_vp8_accelerator.cc",
188-    "v4l2_vp8_accelerator.h",
189-    "v4l2_vp8_accelerator_legacy.cc",
190-    "v4l2_vp8_accelerator_legacy.h",
191-    "v4l2_vp9_accelerator_legacy.cc",
192-    "v4l2_vp9_accelerator_legacy.h",
193   ]
194
195+  if (!use_linux_v4l2_only) {
196+    sources += [
197+      "v4l2_decode_surface.cc",
198+      "v4l2_decode_surface.h",
199+      "v4l2_decode_surface_handler.h",
200+      "v4l2_h264_accelerator.cc",
201+      "v4l2_h264_accelerator.h",
202+      "v4l2_h264_accelerator_legacy.cc",
203+      "v4l2_h264_accelerator_legacy.h",
204+      "v4l2_slice_video_decode_accelerator.cc",
205+      "v4l2_slice_video_decode_accelerator.h",
206+      "v4l2_video_decoder_backend_stateless.cc",
207+      "v4l2_video_decoder_backend_stateless.h",
208+      "v4l2_vp8_accelerator.cc",
209+      "v4l2_vp8_accelerator.h",
210+      "v4l2_vp8_accelerator_legacy.cc",
211+      "v4l2_vp8_accelerator_legacy.h",
212+      "v4l2_vp9_accelerator_legacy.cc",
213+      "v4l2_vp9_accelerator_legacy.h",
214+    ]
215+  }
216+
217   libs = [
218     "EGL",
219     "GLESv2",
220diff --git a/chromium/media/gpu/v4l2/generic_v4l2_device.cc b/chromium/media/gpu/v4l2/generic_v4l2_device.cc
221index 6742dc14c..f0f103458 100644
222--- a/chromium/media/gpu/v4l2/generic_v4l2_device.cc
223+++ b/chromium/media/gpu/v4l2/generic_v4l2_device.cc
224@@ -415,7 +415,11 @@ bool GenericV4L2Device::OpenDevicePath(const std::string& path, Type type) {
225     return false;
226
227 #if BUILDFLAG(USE_LIBV4L2)
228+#if BUILDFLAG(USE_LINUX_V4L2)
229+  if (
230+#else
231   if (type == Type::kEncoder &&
232+#endif
233       HANDLE_EINTR(v4l2_fd_open(device_fd_.get(), V4L2_DISABLE_CONVERSION)) !=
234           -1) {
235     DVLOGF(3) << "Using libv4l2 for " << path;
236diff --git a/chromium/media/gpu/v4l2/v4l2_device.cc b/chromium/media/gpu/v4l2/v4l2_device.cc
237index 9dd1c87aa..f9cc4fbb4 100644
238--- a/chromium/media/gpu/v4l2/v4l2_device.cc
239+++ b/chromium/media/gpu/v4l2/v4l2_device.cc
240@@ -784,7 +784,9 @@ void V4L2WritableBufferRef::SetConfigStore(uint32_t config_store) {
241   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
242   DCHECK(buffer_data_);
243
244+#if !BUILDFLAG(USE_LINUX_V4L2)
245   buffer_data_->v4l2_buffer_.config_store = config_store;
246+#endif
247 }
248
249 V4L2ReadableBuffer::V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer,
250@@ -927,10 +929,12 @@ V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev,
251     return;
252   }
253
254+#if !BUILDFLAG(USE_LINUX_V4L2)
255   if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
256     supports_requests_ = true;
257     DVLOGF(4) << "Queue supports request API.";
258   }
259+#endif
260 }
261
262 V4L2Queue::~V4L2Queue() {
263@@ -1465,6 +1469,23 @@ scoped_refptr<V4L2Device> V4L2Device::Create() {
264 // static
265 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
266                                                    bool slice_based) {
267+#if BUILDFLAG(USE_LINUX_V4L2)
268+  if (slice_based) {
269+    LOG(ERROR) << "Slice not supported";
270+    return 0;
271+  }
272+
273+  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
274+    return V4L2_PIX_FMT_H264;
275+  } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
276+    return V4L2_PIX_FMT_VP8;
277+  } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
278+    return V4L2_PIX_FMT_VP9;
279+  } else {
280+    LOG(ERROR) << "Unknown profile: " << GetProfileName(profile);
281+    return 0;
282+  }
283+#else
284   if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
285     if (slice_based)
286       return V4L2_PIX_FMT_H264_SLICE;
287@@ -1484,8 +1505,10 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
288     LOG(ERROR) << "Unknown profile: " << GetProfileName(profile);
289     return 0;
290   }
291+#endif
292 }
293
294+#if !BUILDFLAG(USE_LINUX_V4L2)
295 // static
296 VideoCodecProfile V4L2Device::V4L2ProfileToVideoCodecProfile(VideoCodec codec,
297                                                              uint32_t profile) {
298@@ -1534,10 +1557,12 @@ VideoCodecProfile V4L2Device::V4L2ProfileToVideoCodecProfile(VideoCodec codec,
299   VLOGF(2) << "Unknown profile: " << profile;
300   return VIDEO_CODEC_PROFILE_UNKNOWN;
301 }
302+#endif
303
304 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
305     uint32_t pix_fmt,
306     bool is_encoder) {
307+#if !BUILDFLAG(USE_LINUX_V4L2)
308   auto get_supported_profiles = [this](
309                                     VideoCodec codec,
310                                     std::vector<VideoCodecProfile>* profiles) {
311@@ -1608,6 +1633,27 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
312       VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
313       return {};
314   }
315+#else
316+  std::vector<VideoCodecProfile> profiles;
317+  switch (pix_fmt) {
318+    case V4L2_PIX_FMT_H264:
319+      profiles = {
320+          H264PROFILE_BASELINE,
321+          H264PROFILE_MAIN,
322+          H264PROFILE_HIGH,
323+      };
324+      break;
325+    case V4L2_PIX_FMT_VP8:
326+      profiles = {VP8PROFILE_ANY};
327+      break;
328+    case V4L2_PIX_FMT_VP9:
329+      profiles = {VP9PROFILE_PROFILE0};
330+      break;
331+    default:
332+      VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
333+      return {};
334+  }
335+#endif
336
337   // Erase duplicated profiles.
338   std::sort(profiles.begin(), profiles.end());
339@@ -1632,6 +1678,12 @@ uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) {
340     case V4L2_PIX_FMT_RGB32:
341       return DRM_FORMAT_ARGB8888;
342
343+#if !BUILDFLAG(USE_LINUX_V4L2)
344+    case V4L2_PIX_FMT_MT21C:
345+    case V4L2_PIX_FMT_MT21:
346+      return DRM_FORMAT_MT21;
347+#endif
348+
349     default:
350       DVLOGF(1) << "Unrecognized format " << FourccToString(format);
351       return 0;
352@@ -2311,10 +2363,14 @@ bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) {
353     return false;
354   }
355
356+#if !BUILDFLAG(USE_LINUX_V4L2)
357   ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL;
358   ctrls->request_fd = request_fd_.get();
359
360   return true;
361+#else
362+  return false;
363+#endif
364 }
365
366 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
367@@ -2326,10 +2382,14 @@ bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
368     return false;
369   }
370
371+#if !BUILDFLAG(USE_LINUX_V4L2)
372   buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD;
373   buffer->request_fd = request_fd_.get();
374
375   return true;
376+#else
377+  return false;
378+#endif
379 }
380
381 bool V4L2Request::Submit() {
382@@ -2340,7 +2400,11 @@ bool V4L2Request::Submit() {
383     return false;
384   }
385
386+#if !BUILDFLAG(USE_LINUX_V4L2)
387   return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0;
388+#else
389+  return false;
390+#endif
391 }
392
393 bool V4L2Request::IsCompleted() {
394@@ -2383,6 +2447,7 @@ bool V4L2Request::Reset() {
395     return false;
396   }
397
398+#if !BUILDFLAG(USE_LINUX_V4L2)
399   // Reinit the request to make sure we can use it for a new submission.
400   if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) {
401     VPLOGF(1) << "Failed to reinit request.";
402@@ -2390,6 +2455,9 @@ bool V4L2Request::Reset() {
403   }
404
405   return true;
406+#else
407+  return false;
408+#endif
409 }
410
411 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) {
412@@ -2464,6 +2532,7 @@ V4L2RequestsQueue::~V4L2RequestsQueue() {
413 base::Optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
414   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
415
416+#if !BUILDFLAG(USE_LINUX_V4L2)
417   int request_fd;
418   int ret = HANDLE_EINTR(
419         ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd));
420@@ -2473,6 +2542,9 @@ base::Optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
421   }
422
423   return base::ScopedFD(request_fd);
424+#else
425+  return base::nullopt;
426+#endif
427 }
428
429 base::Optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() {
430diff --git a/chromium/media/gpu/v4l2/v4l2_video_decoder.cc b/chromium/media/gpu/v4l2/v4l2_video_decoder.cc
431index c0963ed40..5b3dd3af2 100644
432--- a/chromium/media/gpu/v4l2/v4l2_video_decoder.cc
433+++ b/chromium/media/gpu/v4l2/v4l2_video_decoder.cc
434@@ -19,7 +19,10 @@
435 #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
436 #include "media/gpu/macros.h"
437 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h"
438+
439+#if !BUILDFLAG(USE_LINUX_V4L2)
440 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h"
441+#endif
442
443 namespace media {
444
445@@ -35,7 +38,9 @@ constexpr size_t kNumInputBuffers = 16;
446
447 // Input format V4L2 fourccs this class supports.
448 constexpr uint32_t kSupportedInputFourccs[] = {
449+#if !BUILDFLAG(USE_LINUX_V4L2)
450     V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
451+#endif
452     V4L2_PIX_FMT_H264,       V4L2_PIX_FMT_VP8,       V4L2_PIX_FMT_VP9,
453 };
454
455@@ -204,10 +209,12 @@ void V4L2VideoDecoder::Initialize(const VideoDecoderConfig& config,
456     backend_ = std::make_unique<V4L2StatefulVideoDecoderBackend>(
457         this, device_, profile, decoder_task_runner_);
458     input_format_fourcc = input_format_fourcc_stateful;
459+#if !BUILDFLAG(USE_LINUX_V4L2)
460   } else if (input_format_fourcc_stateless) {
461     backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>(
462         this, device_, profile, decoder_task_runner_);
463     input_format_fourcc = input_format_fourcc_stateless;
464+#endif
465   } else {
466     VLOGF(1) << "No backend capable of taking this profile.";
467     std::move(init_cb).Run(StatusCode::kV4l2FailedResourceAllocation);
468--
4692.20.1
470
471