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