1From dc95c012fb4105e73af1edd89061c73329324226 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/17] media: gpu: v4l2: Support V4L2 VDA with libv4l2 on 5 Linux 6 7Based on: 8https://github.com/OSSystems/meta-browser/pull/263/commits/60ceb28750ee1f73c9cc2bf7e9e20e1c37a03497 9 10Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 11--- 12 .../gpu_mjpeg_decode_accelerator_factory.cc | 3 +- 13 media/gpu/BUILD.gn | 1 + 14 media/gpu/args.gni | 3 + 15 .../gpu_video_decode_accelerator_factory.cc | 8 +++ 16 .../gpu_video_decode_accelerator_factory.h | 2 + 17 media/gpu/v4l2/BUILD.gn | 43 +++++++----- 18 media/gpu/v4l2/generic_v4l2_device.cc | 2 +- 19 media/gpu/v4l2/v4l2_device.cc | 70 +++++++++++++++++++ 20 media/gpu/v4l2/v4l2_video_decoder.cc | 7 ++ 21 9 files changed, 120 insertions(+), 19 deletions(-) 22 23diff --git a/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc b/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc 24index 020b12831..18feaf03b 100644 25--- a/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc 26+++ b/components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.cc 27@@ -13,7 +13,8 @@ 28 #include "media/base/media_switches.h" 29 #include "media/gpu/buildflags.h" 30 31-#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY) 32+#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY) && \ 33+ !BUILDFLAG(USE_LINUX_V4L2) 34 #define USE_V4L2_MJPEG_DECODE_ACCELERATOR 35 #endif 36 37diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn 38index 041652bb2..1e9f945ff 100644 39--- a/media/gpu/BUILD.gn 40+++ b/media/gpu/BUILD.gn 41@@ -20,6 +20,7 @@ buildflag_header("buildflags") { 42 "USE_VAAPI_IMAGE_CODECS=$use_vaapi_image_codecs", 43 "USE_V4L2_CODEC=$use_v4l2_codec", 44 "USE_LIBV4L2=$use_v4lplugin", 45+ "USE_LINUX_V4L2=$use_linux_v4l2_only", 46 "USE_VAAPI_X11=$use_vaapi_x11", 47 ] 48 } 49diff --git a/media/gpu/args.gni b/media/gpu/args.gni 50index 813657af1..65fb45c1d 100644 51--- a/media/gpu/args.gni 52+++ b/media/gpu/args.gni 53@@ -25,6 +25,9 @@ declare_args() { 54 # platforms which have v4l2 hardware encoder 55 use_v4l2_codec_aml = false 56 57+ # Indicates if Video4Linux2 codec is used for linux platform. 58+ use_linux_v4l2_only = false 59+ 60 # Indicates if VA-API-based hardware acceleration is to be used. This 61 # is typically the case on x86-based ChromeOS devices. 62 # VA-API should also be compiled by default on x11-using linux devices 63diff --git a/media/gpu/gpu_video_decode_accelerator_factory.cc b/media/gpu/gpu_video_decode_accelerator_factory.cc 64index 4fa596240..2f58f8f19 100644 65--- a/media/gpu/gpu_video_decode_accelerator_factory.cc 66+++ b/media/gpu/gpu_video_decode_accelerator_factory.cc 67@@ -30,7 +30,9 @@ 68 #elif BUILDFLAG(USE_V4L2_CODEC) && \ 69 (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)) 70 #include "media/gpu/v4l2/v4l2_device.h" 71+#if !BUILDFLAG(USE_LINUX_V4L2) 72 #include "media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h" 73+#endif 74 #include "media/gpu/v4l2/v4l2_video_decode_accelerator.h" 75 #include "ui/gl/gl_surface_egl.h" 76 #endif 77@@ -66,10 +68,12 @@ gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilitiesInternal( 78 GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles( 79 V4L2VideoDecodeAccelerator::GetSupportedProfiles(), 80 &capabilities.supported_profiles); 81+#if !BUILDFLAG(USE_LINUX_V4L2) 82 GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles( 83 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles(), 84 &capabilities.supported_profiles); 85 #endif 86+#endif 87 #elif BUILDFLAG(IS_MAC) 88 capabilities.supported_profiles = 89 VTVideoDecodeAccelerator::GetSupportedProfiles(workarounds); 90@@ -150,8 +154,10 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA( 91 #elif BUILDFLAG(USE_V4L2_CODEC) && \ 92 (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)) 93 &GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA, 94+#if !BUILDFLAG(USE_LINUX_V4L2) 95 &GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA, 96 #endif 97+#endif 98 99 #if BUILDFLAG(IS_MAC) 100 &GpuVideoDecodeAcceleratorFactory::CreateVTVDA, 101@@ -212,6 +218,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA( 102 return decoder; 103 } 104 105+#if !BUILDFLAG(USE_LINUX_V4L2) 106 std::unique_ptr<VideoDecodeAccelerator> 107 GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA( 108 const gpu::GpuDriverBugWorkarounds& /*workarounds*/, 109@@ -227,6 +234,7 @@ GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA( 110 return decoder; 111 } 112 #endif 113+#endif 114 115 #if BUILDFLAG(IS_MAC) 116 std::unique_ptr<VideoDecodeAccelerator> 117diff --git a/media/gpu/gpu_video_decode_accelerator_factory.h b/media/gpu/gpu_video_decode_accelerator_factory.h 118index d105fe6f8..43e9d1260 100644 119--- a/media/gpu/gpu_video_decode_accelerator_factory.h 120+++ b/media/gpu/gpu_video_decode_accelerator_factory.h 121@@ -105,11 +105,13 @@ class MEDIA_GPU_EXPORT GpuVideoDecodeAcceleratorFactory { 122 const gpu::GpuDriverBugWorkarounds& workarounds, 123 const gpu::GpuPreferences& gpu_preferences, 124 MediaLog* media_log) const; 125+#if !BUILDFLAG(USE_LINUX_V4L2) 126 std::unique_ptr<VideoDecodeAccelerator> CreateV4L2SliceVDA( 127 const gpu::GpuDriverBugWorkarounds& workarounds, 128 const gpu::GpuPreferences& gpu_preferences, 129 MediaLog* media_log) const; 130 #endif 131+#endif 132 #if BUILDFLAG(IS_MAC) 133 std::unique_ptr<VideoDecodeAccelerator> CreateVTVDA( 134 const gpu::GpuDriverBugWorkarounds& workarounds, 135diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn 136index 75c124c89..a73b9fb03 100644 137--- a/media/gpu/v4l2/BUILD.gn 138+++ b/media/gpu/v4l2/BUILD.gn 139@@ -27,9 +27,6 @@ source_set("v4l2") { 140 "buffer_affinity_tracker.h", 141 "generic_v4l2_device.cc", 142 "generic_v4l2_device.h", 143- "v4l2_decode_surface.cc", 144- "v4l2_decode_surface.h", 145- "v4l2_decode_surface_handler.h", 146 "v4l2_device.cc", 147 "v4l2_device.h", 148 "v4l2_device_poller.cc", 149@@ -38,8 +35,6 @@ source_set("v4l2") { 150 "v4l2_framerate_control.h", 151 "v4l2_image_processor_backend.cc", 152 "v4l2_image_processor_backend.h", 153- "v4l2_slice_video_decode_accelerator.cc", 154- "v4l2_slice_video_decode_accelerator.h", 155 "v4l2_stateful_workaround.cc", 156 "v4l2_stateful_workaround.h", 157 "v4l2_utils.cc", 158@@ -54,22 +49,36 @@ source_set("v4l2") { 159 "v4l2_video_decoder_backend.h", 160 "v4l2_video_decoder_backend_stateful.cc", 161 "v4l2_video_decoder_backend_stateful.h", 162- "v4l2_video_decoder_backend_stateless.cc", 163- "v4l2_video_decoder_backend_stateless.h", 164- "v4l2_video_decoder_delegate_h264.cc", 165- "v4l2_video_decoder_delegate_h264.h", 166- "v4l2_video_decoder_delegate_vp8.cc", 167- "v4l2_video_decoder_delegate_vp8.h", 168- "v4l2_video_decoder_delegate_vp9.cc", 169- "v4l2_video_decoder_delegate_vp9.h", 170 ] 171 172- if (is_chromeos) { 173+ if (!use_linux_v4l2_only) { 174 sources += [ 175- # AV1 delegate depends on header files only in ChromeOS SDK 176- "v4l2_video_decoder_delegate_av1.cc", 177- "v4l2_video_decoder_delegate_av1.h", 178+ "v4l2_decode_surface.cc", 179+ "v4l2_decode_surface.h", 180+ "v4l2_decode_surface_handler.h", 181+ "v4l2_slice_video_decode_accelerator.cc", 182+ "v4l2_slice_video_decode_accelerator.h", 183+ "v4l2_video_decoder_backend_stateless.cc", 184+ "v4l2_video_decoder_backend_stateless.h", 185+ "v4l2_video_decoder_delegate_h264.cc", 186+ "v4l2_video_decoder_delegate_h264.h", 187+ "v4l2_video_decoder_delegate_vp8.cc", 188+ "v4l2_video_decoder_delegate_vp8.h", 189+ "v4l2_video_decoder_delegate_vp9.cc", 190+ "v4l2_video_decoder_delegate_vp9.h", 191+ ] 192+ 193+ if (is_chromeos) { 194+ sources += [ 195+ # AV1 delegate depends on header files only in ChromeOS SDK 196+ "v4l2_video_decoder_delegate_av1.cc", 197+ "v4l2_video_decoder_delegate_av1.h", 198+ ] 199+ } 200+ } 201 202+ if (is_chromeos) { 203+ sources += [ 204 # TODO(crbug.com/901264): Encoders use hack for passing offset 205 # within a DMA-buf, which is not supported upstream. 206 "v4l2_video_encode_accelerator.cc", 207diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc 208index fa9a95b95..b71494c34 100644 209--- a/media/gpu/v4l2/generic_v4l2_device.cc 210+++ b/media/gpu/v4l2/generic_v4l2_device.cc 211@@ -434,7 +434,7 @@ bool GenericV4L2Device::OpenDevicePath(const std::string& path, Type type) { 212 return false; 213 214 if (V4L2Device::UseLibV4L2()) { 215- if (type == Type::kEncoder && 216+ if (/* type == Type::kEncoder && */ 217 HANDLE_EINTR(v4l2_fd_open(device_fd_.get(), V4L2_DISABLE_CONVERSION)) != 218 -1) { 219 DVLOGF(3) << "Using libv4l2 for " << path; 220diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc 221index e6d1b1927..d8e5526fe 100644 222--- a/media/gpu/v4l2/v4l2_device.cc 223+++ b/media/gpu/v4l2/v4l2_device.cc 224@@ -1019,10 +1019,12 @@ V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev, 225 return; 226 } 227 228+#if BUILDFLAG(IS_CHROMEOS) 229 if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) { 230 supports_requests_ = true; 231 DVLOGF(4) << "Queue supports request API."; 232 } 233+#endif 234 } 235 236 V4L2Queue::~V4L2Queue() { 237@@ -1166,9 +1168,13 @@ size_t V4L2Queue::AllocateBuffers(size_t count, 238 reqbufs.count = count; 239 reqbufs.type = type_; 240 reqbufs.memory = memory; 241+#if BUILDFLAG(IS_CHROMEOS) 242 reqbufs.flags = incoherent ? V4L2_MEMORY_FLAG_NON_COHERENT : 0; 243 DVQLOGF(3) << "Requesting " << count << " buffers."; 244 DVQLOGF(3) << "Incoherent flag is " << incoherent << "."; 245+#else 246+ DVQLOGF(3) << "Requesting " << count << " buffers."; 247+#endif 248 249 int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); 250 if (ret) { 251@@ -1227,7 +1233,9 @@ bool V4L2Queue::DeallocateBuffers() { 252 reqbufs.count = 0; 253 reqbufs.type = type_; 254 reqbufs.memory = memory_; 255+#if BUILDFLAG(IS_CHROMEOS) 256 reqbufs.flags = incoherent_ ? V4L2_MEMORY_FLAG_NON_COHERENT : 0; 257+#endif 258 259 int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); 260 if (ret) { 261@@ -1583,6 +1591,23 @@ std::string V4L2Device::GetDriverName() { 262 // static 263 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, 264 bool slice_based) { 265+#if BUILDFLAG(USE_LINUX_V4L2) 266+ if (slice_based) { 267+ LOG(ERROR) << "Slice not supported"; 268+ return 0; 269+ } 270+ 271+ if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) { 272+ return V4L2_PIX_FMT_H264; 273+ } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) { 274+ return V4L2_PIX_FMT_VP8; 275+ } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) { 276+ return V4L2_PIX_FMT_VP9; 277+ } else { 278+ DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile); 279+ return 0; 280+ } 281+#else 282 if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) { 283 if (slice_based) 284 return V4L2_PIX_FMT_H264_SLICE; 285@@ -1607,8 +1632,10 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, 286 DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile); 287 return 0; 288 } 289+#endif 290 } 291 292+#if !BUILDFLAG(USE_LINUX_V4L2) 293 namespace { 294 295 VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec, 296@@ -1667,9 +1694,11 @@ VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec, 297 } 298 299 } // namespace 300+#endif 301 302 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles( 303 uint32_t pix_fmt) { 304+#if !BUILDFLAG(USE_LINUX_V4L2) 305 auto get_supported_profiles = [this]( 306 VideoCodec codec, 307 std::vector<VideoCodecProfile>* profiles) { 308@@ -1753,6 +1782,27 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles( 309 VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt); 310 return {}; 311 } 312+#else 313+ std::vector<VideoCodecProfile> profiles; 314+ switch (pix_fmt) { 315+ case V4L2_PIX_FMT_H264: 316+ profiles = { 317+ H264PROFILE_BASELINE, 318+ H264PROFILE_MAIN, 319+ H264PROFILE_HIGH, 320+ }; 321+ break; 322+ case V4L2_PIX_FMT_VP8: 323+ profiles = {VP8PROFILE_ANY}; 324+ break; 325+ case V4L2_PIX_FMT_VP9: 326+ profiles = {VP9PROFILE_PROFILE0}; 327+ break; 328+ default: 329+ VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt); 330+ return {}; 331+ } 332+#endif 333 334 // Erase duplicated profiles. 335 std::sort(profiles.begin(), profiles.end()); 336@@ -2469,10 +2519,14 @@ bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) { 337 return false; 338 } 339 340+#if BUILDFLAG(IS_CHROMEOS) 341 ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL; 342 ctrls->request_fd = request_fd_.get(); 343 344 return true; 345+#else 346+ return false; 347+#endif 348 } 349 350 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) { 351@@ -2484,10 +2538,14 @@ bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) { 352 return false; 353 } 354 355+#if BUILDFLAG(IS_CHROMEOS) 356 buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD; 357 buffer->request_fd = request_fd_.get(); 358 359 return true; 360+#else 361+ return false; 362+#endif 363 } 364 365 bool V4L2Request::Submit() { 366@@ -2498,7 +2556,11 @@ bool V4L2Request::Submit() { 367 return false; 368 } 369 370+#if BUILDFLAG(IS_CHROMEOS) 371 return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0; 372+#else 373+ return false; 374+#endif 375 } 376 377 bool V4L2Request::IsCompleted() { 378@@ -2541,6 +2603,7 @@ bool V4L2Request::Reset() { 379 return false; 380 } 381 382+#if BUILDFLAG(IS_CHROMEOS) 383 // Reinit the request to make sure we can use it for a new submission. 384 if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) { 385 VPLOGF(1) << "Failed to reinit request."; 386@@ -2548,6 +2611,9 @@ bool V4L2Request::Reset() { 387 } 388 389 return true; 390+#else 391+ return false; 392+#endif 393 } 394 395 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) { 396@@ -2622,6 +2688,7 @@ V4L2RequestsQueue::~V4L2RequestsQueue() { 397 absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() { 398 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 399 400+#if BUILDFLAG(IS_CHROMEOS) 401 int request_fd; 402 int ret = HANDLE_EINTR( 403 ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd)); 404@@ -2631,6 +2698,9 @@ absl::optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() { 405 } 406 407 return base::ScopedFD(request_fd); 408+#else 409+ return absl::nullopt; 410+#endif 411 } 412 413 absl::optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() { 414diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc 415index 8ba46bc26..f6304210c 100644 416--- a/media/gpu/v4l2/v4l2_video_decoder.cc 417+++ b/media/gpu/v4l2/v4l2_video_decoder.cc 418@@ -28,7 +28,10 @@ 419 #include "media/gpu/macros.h" 420 #include "media/gpu/v4l2/v4l2_status.h" 421 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h" 422+ 423+#if !BUILDFLAG(USE_LINUX_V4L2) 424 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h" 425+#endif 426 427 namespace media { 428 429@@ -45,11 +48,13 @@ constexpr size_t kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p; 430 431 // Input format V4L2 fourccs this class supports. 432 constexpr uint32_t kSupportedInputFourccs[] = { 433+#if !BUILDFLAG(USE_LINUX_V4L2) 434 // V4L2 stateless formats 435 V4L2_PIX_FMT_H264_SLICE, 436 V4L2_PIX_FMT_VP8_FRAME, 437 V4L2_PIX_FMT_VP9_FRAME, 438 V4L2_PIX_FMT_AV1_FRAME, 439+#endif 440 // V4L2 stateful formats 441 V4L2_PIX_FMT_H264, 442 V4L2_PIX_FMT_VP8, 443@@ -336,6 +341,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() { 444 backend_ = std::make_unique<V4L2StatefulVideoDecoderBackend>( 445 this, device_, profile_, color_space_, low_delay_, 446 decoder_task_runner_); 447+#if !BUILDFLAG(USE_LINUX_V4L2) 448 } else { 449 DCHECK_EQ(preferred_api_and_format.first, kStateless); 450 VLOGF(1) << "Using a stateless API for profile: " 451@@ -343,6 +349,7 @@ V4L2Status V4L2VideoDecoder::InitializeBackend() { 452 << " and fourcc: " << FourccToString(input_format_fourcc); 453 backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>( 454 this, device_, profile_, color_space_, decoder_task_runner_); 455+#endif 456 } 457 458 if (!backend_->Initialize()) { 459-- 4602.20.1 461 462