123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/gpu/gpu_video_encode_accelerator_factory.h"
- #include "base/bind.h"
- #include "base/containers/cxx20_erase.h"
- #include "base/feature_list.h"
- #include "base/memory/ptr_util.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "build/build_config.h"
- #include "gpu/config/gpu_driver_bug_workarounds.h"
- #include "gpu/config/gpu_preferences.h"
- #include "media/base/media_log.h"
- #include "media/base/media_switches.h"
- #include "media/base/media_util.h"
- #include "media/gpu/buildflags.h"
- #include "media/gpu/gpu_video_accelerator_util.h"
- #include "media/gpu/macros.h"
- #if BUILDFLAG(USE_V4L2_CODEC)
- #include "media/gpu/v4l2/v4l2_video_encode_accelerator.h"
- #endif
- #if BUILDFLAG(IS_ANDROID)
- #include "media/gpu/android/android_video_encode_accelerator.h"
- #include "media/gpu/android/ndk_video_encode_accelerator.h"
- #endif
- #if BUILDFLAG(IS_MAC)
- #include "media/gpu/mac/vt_video_encode_accelerator_mac.h"
- #endif
- #if BUILDFLAG(IS_WIN)
- #include "media/gpu/windows/media_foundation_video_encode_accelerator_win.h"
- #endif
- #if BUILDFLAG(USE_VAAPI)
- #include "media/gpu/vaapi/vaapi_video_encode_accelerator.h"
- #endif
- namespace media {
- namespace {
- #if BUILDFLAG(USE_V4L2_CODEC)
- std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA() {
- scoped_refptr<V4L2Device> device = V4L2Device::Create();
- if (!device)
- return nullptr;
- #if BUILDFLAG(IS_CHROMEOS)
- // TODO(crbug.com/901264): Encoders use hack for passing offset within
- // a DMA-buf, which is not supported upstream.
- return base::WrapUnique<VideoEncodeAccelerator>(
- new V4L2VideoEncodeAccelerator(std::move(device)));
- #else
- return nullptr;
- #endif
- }
- #endif
- #if BUILDFLAG(USE_VAAPI)
- std::unique_ptr<VideoEncodeAccelerator> CreateVaapiVEA() {
- return base::WrapUnique<VideoEncodeAccelerator>(
- new VaapiVideoEncodeAccelerator());
- }
- #endif
- #if BUILDFLAG(IS_ANDROID)
- std::unique_ptr<VideoEncodeAccelerator> CreateAndroidVEA() {
- if (NdkVideoEncodeAccelerator::IsSupported()) {
- return base::WrapUnique<VideoEncodeAccelerator>(
- new NdkVideoEncodeAccelerator(base::ThreadTaskRunnerHandle::Get()));
- } else {
- return base::WrapUnique<VideoEncodeAccelerator>(
- new AndroidVideoEncodeAccelerator());
- }
- }
- #endif
- #if BUILDFLAG(IS_MAC)
- std::unique_ptr<VideoEncodeAccelerator> CreateVTVEA() {
- return base::WrapUnique<VideoEncodeAccelerator>(
- new VTVideoEncodeAccelerator());
- }
- #endif
- #if BUILDFLAG(IS_WIN)
- // Creates a MediaFoundationVEA for Win 7 or later. If |compatible_with_win7| is
- // true, VEA is limited to a subset of features that is compatible with Win 7.
- std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA(
- const gpu::GpuPreferences& gpu_preferences,
- const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- const gpu::GPUInfo::GPUDevice& gpu_device) {
- return base::WrapUnique<VideoEncodeAccelerator>(
- new MediaFoundationVideoEncodeAccelerator(
- gpu_preferences, gpu_workarounds, gpu_device.luid));
- }
- #endif
- using VEAFactoryFunction =
- base::RepeatingCallback<std::unique_ptr<VideoEncodeAccelerator>()>;
- std::vector<VEAFactoryFunction> GetVEAFactoryFunctions(
- const gpu::GpuPreferences& gpu_preferences,
- const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- const gpu::GPUInfo::GPUDevice& gpu_device) {
- // Array of VEAFactoryFunctions potentially usable on the current platform.
- // This list is ordered by priority, from most to least preferred, if
- // applicable. This list is composed once and then reused.
- static std::vector<VEAFactoryFunction> vea_factory_functions;
- if (gpu_preferences.disable_accelerated_video_encode)
- return vea_factory_functions;
- if (!vea_factory_functions.empty())
- return vea_factory_functions;
- #if BUILDFLAG(USE_VAAPI)
- #if BUILDFLAG(IS_LINUX)
- if (base::FeatureList::IsEnabled(kVaapiVideoEncodeLinux))
- vea_factory_functions.push_back(base::BindRepeating(&CreateVaapiVEA));
- #else
- vea_factory_functions.push_back(base::BindRepeating(&CreateVaapiVEA));
- #endif
- #endif
- #if BUILDFLAG(USE_V4L2_CODEC)
- vea_factory_functions.push_back(base::BindRepeating(&CreateV4L2VEA));
- #endif
- #if BUILDFLAG(IS_ANDROID)
- vea_factory_functions.push_back(base::BindRepeating(&CreateAndroidVEA));
- #endif
- #if BUILDFLAG(IS_MAC)
- vea_factory_functions.push_back(base::BindRepeating(&CreateVTVEA));
- #endif
- #if BUILDFLAG(IS_WIN)
- vea_factory_functions.push_back(base::BindRepeating(
- &CreateMediaFoundationVEA, gpu_preferences, gpu_workarounds, gpu_device));
- #endif
- return vea_factory_functions;
- }
- VideoEncodeAccelerator::SupportedProfiles GetSupportedProfilesInternal(
- const gpu::GpuPreferences& gpu_preferences,
- const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- const gpu::GPUInfo::GPUDevice& gpu_device,
- bool populate_extended_info) {
- if (gpu_preferences.disable_accelerated_video_encode)
- return VideoEncodeAccelerator::SupportedProfiles();
- VideoEncodeAccelerator::SupportedProfiles profiles;
- for (const auto& create_vea :
- GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) {
- auto vea = std::move(create_vea).Run();
- if (!vea)
- continue;
- auto vea_profiles = populate_extended_info
- ? vea->GetSupportedProfiles()
- : vea->GetSupportedProfilesLight();
- GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles,
- &profiles);
- }
- return profiles;
- }
- } // anonymous namespace
- // static
- MEDIA_GPU_EXPORT std::unique_ptr<VideoEncodeAccelerator>
- GpuVideoEncodeAcceleratorFactory::CreateVEA(
- const VideoEncodeAccelerator::Config& config,
- VideoEncodeAccelerator::Client* client,
- const gpu::GpuPreferences& gpu_preferences,
- const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- const gpu::GPUInfo::GPUDevice& gpu_device,
- std::unique_ptr<MediaLog> media_log) {
- // NullMediaLog silently and safely does nothing.
- if (!media_log)
- media_log = std::make_unique<media::NullMediaLog>();
- for (const auto& create_vea :
- GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) {
- std::unique_ptr<VideoEncodeAccelerator> vea = create_vea.Run();
- if (!vea)
- continue;
- if (!vea->Initialize(config, client, media_log->Clone())) {
- DLOG(ERROR) << "VEA initialize failed (" << config.AsHumanReadableString()
- << ")";
- continue;
- }
- return vea;
- }
- return nullptr;
- }
- // static
- MEDIA_GPU_EXPORT VideoEncodeAccelerator::SupportedProfiles
- GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
- const gpu::GpuPreferences& gpu_preferences,
- const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- const gpu::GPUInfo::GPUDevice& gpu_device,
- bool populate_extended_info) {
- // Cache the supported profiles so that they will not be computed more than
- // once per GPU process. It is assumed that |gpu_preferences| do not change
- // between calls.
- VideoEncodeAccelerator::SupportedProfiles* profiles_ptr = nullptr;
- if (populate_extended_info) {
- static auto profiles = GetSupportedProfilesInternal(
- gpu_preferences, gpu_workarounds, gpu_device, true);
- profiles_ptr = &profiles;
- } else {
- static auto profiles = GetSupportedProfilesInternal(
- gpu_preferences, gpu_workarounds, gpu_device, false);
- profiles_ptr = &profiles;
- }
- #if BUILDFLAG(USE_V4L2_CODEC)
- // V4L2-only: the encoder devices may not be visible at the time the GPU
- // process is starting. If the capabilities vector is empty, try to query the
- // devices again in the hope that they will have appeared in the meantime.
- // TODO(crbug.com/948147): trigger query when an device add/remove event
- // (e.g. via udev) has happened instead.
- if (profiles_ptr->empty()) {
- VLOGF(1) << "Supported profiles empty, querying again...";
- *profiles_ptr = GetSupportedProfilesInternal(
- gpu_preferences, gpu_workarounds, gpu_device, populate_extended_info);
- }
- #endif
- if (gpu_workarounds.disable_accelerated_vp8_encode) {
- base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
- return vea_profile.profile == VP8PROFILE_ANY;
- });
- }
- if (gpu_workarounds.disable_accelerated_vp9_encode) {
- base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
- return vea_profile.profile >= VP9PROFILE_PROFILE0 &&
- vea_profile.profile <= VP9PROFILE_PROFILE3;
- });
- }
- if (gpu_workarounds.disable_accelerated_h264_encode) {
- base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
- return vea_profile.profile >= H264PROFILE_MIN &&
- vea_profile.profile <= H264PROFILE_MAX;
- });
- }
- base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
- return vea_profile.profile >= HEVCPROFILE_MIN &&
- vea_profile.profile <= HEVCPROFILE_MAX;
- });
- return *profiles_ptr;
- }
- } // namespace media
|