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