gpu_video_encode_accelerator_factory.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/gpu/gpu_video_encode_accelerator_factory.h"
  5. #include "base/bind.h"
  6. #include "base/containers/cxx20_erase.h"
  7. #include "base/feature_list.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/threading/thread_task_runner_handle.h"
  10. #include "build/build_config.h"
  11. #include "gpu/config/gpu_driver_bug_workarounds.h"
  12. #include "gpu/config/gpu_preferences.h"
  13. #include "media/base/media_log.h"
  14. #include "media/base/media_switches.h"
  15. #include "media/base/media_util.h"
  16. #include "media/gpu/buildflags.h"
  17. #include "media/gpu/gpu_video_accelerator_util.h"
  18. #include "media/gpu/macros.h"
  19. #if BUILDFLAG(USE_V4L2_CODEC)
  20. #include "media/gpu/v4l2/v4l2_video_encode_accelerator.h"
  21. #endif
  22. #if BUILDFLAG(IS_ANDROID)
  23. #include "media/gpu/android/android_video_encode_accelerator.h"
  24. #include "media/gpu/android/ndk_video_encode_accelerator.h"
  25. #endif
  26. #if BUILDFLAG(IS_MAC)
  27. #include "media/gpu/mac/vt_video_encode_accelerator_mac.h"
  28. #endif
  29. #if BUILDFLAG(IS_WIN)
  30. #include "media/gpu/windows/media_foundation_video_encode_accelerator_win.h"
  31. #endif
  32. #if BUILDFLAG(USE_VAAPI)
  33. #include "media/gpu/vaapi/vaapi_video_encode_accelerator.h"
  34. #endif
  35. namespace media {
  36. namespace {
  37. #if BUILDFLAG(USE_V4L2_CODEC)
  38. std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA() {
  39. scoped_refptr<V4L2Device> device = V4L2Device::Create();
  40. if (!device)
  41. return nullptr;
  42. #if BUILDFLAG(IS_CHROMEOS)
  43. // TODO(crbug.com/901264): Encoders use hack for passing offset within
  44. // a DMA-buf, which is not supported upstream.
  45. return base::WrapUnique<VideoEncodeAccelerator>(
  46. new V4L2VideoEncodeAccelerator(std::move(device)));
  47. #else
  48. return nullptr;
  49. #endif
  50. }
  51. #endif
  52. #if BUILDFLAG(USE_VAAPI)
  53. std::unique_ptr<VideoEncodeAccelerator> CreateVaapiVEA() {
  54. return base::WrapUnique<VideoEncodeAccelerator>(
  55. new VaapiVideoEncodeAccelerator());
  56. }
  57. #endif
  58. #if BUILDFLAG(IS_ANDROID)
  59. std::unique_ptr<VideoEncodeAccelerator> CreateAndroidVEA() {
  60. if (NdkVideoEncodeAccelerator::IsSupported()) {
  61. return base::WrapUnique<VideoEncodeAccelerator>(
  62. new NdkVideoEncodeAccelerator(base::ThreadTaskRunnerHandle::Get()));
  63. } else {
  64. return base::WrapUnique<VideoEncodeAccelerator>(
  65. new AndroidVideoEncodeAccelerator());
  66. }
  67. }
  68. #endif
  69. #if BUILDFLAG(IS_MAC)
  70. std::unique_ptr<VideoEncodeAccelerator> CreateVTVEA() {
  71. return base::WrapUnique<VideoEncodeAccelerator>(
  72. new VTVideoEncodeAccelerator());
  73. }
  74. #endif
  75. #if BUILDFLAG(IS_WIN)
  76. // Creates a MediaFoundationVEA for Win 7 or later. If |compatible_with_win7| is
  77. // true, VEA is limited to a subset of features that is compatible with Win 7.
  78. std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA(
  79. const gpu::GpuPreferences& gpu_preferences,
  80. const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
  81. const gpu::GPUInfo::GPUDevice& gpu_device) {
  82. return base::WrapUnique<VideoEncodeAccelerator>(
  83. new MediaFoundationVideoEncodeAccelerator(
  84. gpu_preferences, gpu_workarounds, gpu_device.luid));
  85. }
  86. #endif
  87. using VEAFactoryFunction =
  88. base::RepeatingCallback<std::unique_ptr<VideoEncodeAccelerator>()>;
  89. std::vector<VEAFactoryFunction> GetVEAFactoryFunctions(
  90. const gpu::GpuPreferences& gpu_preferences,
  91. const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
  92. const gpu::GPUInfo::GPUDevice& gpu_device) {
  93. // Array of VEAFactoryFunctions potentially usable on the current platform.
  94. // This list is ordered by priority, from most to least preferred, if
  95. // applicable. This list is composed once and then reused.
  96. static std::vector<VEAFactoryFunction> vea_factory_functions;
  97. if (gpu_preferences.disable_accelerated_video_encode)
  98. return vea_factory_functions;
  99. if (!vea_factory_functions.empty())
  100. return vea_factory_functions;
  101. #if BUILDFLAG(USE_VAAPI)
  102. #if BUILDFLAG(IS_LINUX)
  103. if (base::FeatureList::IsEnabled(kVaapiVideoEncodeLinux))
  104. vea_factory_functions.push_back(base::BindRepeating(&CreateVaapiVEA));
  105. #else
  106. vea_factory_functions.push_back(base::BindRepeating(&CreateVaapiVEA));
  107. #endif
  108. #endif
  109. #if BUILDFLAG(USE_V4L2_CODEC)
  110. vea_factory_functions.push_back(base::BindRepeating(&CreateV4L2VEA));
  111. #endif
  112. #if BUILDFLAG(IS_ANDROID)
  113. vea_factory_functions.push_back(base::BindRepeating(&CreateAndroidVEA));
  114. #endif
  115. #if BUILDFLAG(IS_MAC)
  116. vea_factory_functions.push_back(base::BindRepeating(&CreateVTVEA));
  117. #endif
  118. #if BUILDFLAG(IS_WIN)
  119. vea_factory_functions.push_back(base::BindRepeating(
  120. &CreateMediaFoundationVEA, gpu_preferences, gpu_workarounds, gpu_device));
  121. #endif
  122. return vea_factory_functions;
  123. }
  124. VideoEncodeAccelerator::SupportedProfiles GetSupportedProfilesInternal(
  125. const gpu::GpuPreferences& gpu_preferences,
  126. const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
  127. const gpu::GPUInfo::GPUDevice& gpu_device,
  128. bool populate_extended_info) {
  129. if (gpu_preferences.disable_accelerated_video_encode)
  130. return VideoEncodeAccelerator::SupportedProfiles();
  131. VideoEncodeAccelerator::SupportedProfiles profiles;
  132. for (const auto& create_vea :
  133. GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) {
  134. auto vea = std::move(create_vea).Run();
  135. if (!vea)
  136. continue;
  137. auto vea_profiles = populate_extended_info
  138. ? vea->GetSupportedProfiles()
  139. : vea->GetSupportedProfilesLight();
  140. GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles,
  141. &profiles);
  142. }
  143. return profiles;
  144. }
  145. } // anonymous namespace
  146. // static
  147. MEDIA_GPU_EXPORT std::unique_ptr<VideoEncodeAccelerator>
  148. GpuVideoEncodeAcceleratorFactory::CreateVEA(
  149. const VideoEncodeAccelerator::Config& config,
  150. VideoEncodeAccelerator::Client* client,
  151. const gpu::GpuPreferences& gpu_preferences,
  152. const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
  153. const gpu::GPUInfo::GPUDevice& gpu_device,
  154. std::unique_ptr<MediaLog> media_log) {
  155. // NullMediaLog silently and safely does nothing.
  156. if (!media_log)
  157. media_log = std::make_unique<media::NullMediaLog>();
  158. for (const auto& create_vea :
  159. GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) {
  160. std::unique_ptr<VideoEncodeAccelerator> vea = create_vea.Run();
  161. if (!vea)
  162. continue;
  163. if (!vea->Initialize(config, client, media_log->Clone())) {
  164. DLOG(ERROR) << "VEA initialize failed (" << config.AsHumanReadableString()
  165. << ")";
  166. continue;
  167. }
  168. return vea;
  169. }
  170. return nullptr;
  171. }
  172. // static
  173. MEDIA_GPU_EXPORT VideoEncodeAccelerator::SupportedProfiles
  174. GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
  175. const gpu::GpuPreferences& gpu_preferences,
  176. const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
  177. const gpu::GPUInfo::GPUDevice& gpu_device,
  178. bool populate_extended_info) {
  179. // Cache the supported profiles so that they will not be computed more than
  180. // once per GPU process. It is assumed that |gpu_preferences| do not change
  181. // between calls.
  182. VideoEncodeAccelerator::SupportedProfiles* profiles_ptr = nullptr;
  183. if (populate_extended_info) {
  184. static auto profiles = GetSupportedProfilesInternal(
  185. gpu_preferences, gpu_workarounds, gpu_device, true);
  186. profiles_ptr = &profiles;
  187. } else {
  188. static auto profiles = GetSupportedProfilesInternal(
  189. gpu_preferences, gpu_workarounds, gpu_device, false);
  190. profiles_ptr = &profiles;
  191. }
  192. #if BUILDFLAG(USE_V4L2_CODEC)
  193. // V4L2-only: the encoder devices may not be visible at the time the GPU
  194. // process is starting. If the capabilities vector is empty, try to query the
  195. // devices again in the hope that they will have appeared in the meantime.
  196. // TODO(crbug.com/948147): trigger query when an device add/remove event
  197. // (e.g. via udev) has happened instead.
  198. if (profiles_ptr->empty()) {
  199. VLOGF(1) << "Supported profiles empty, querying again...";
  200. *profiles_ptr = GetSupportedProfilesInternal(
  201. gpu_preferences, gpu_workarounds, gpu_device, populate_extended_info);
  202. }
  203. #endif
  204. if (gpu_workarounds.disable_accelerated_vp8_encode) {
  205. base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
  206. return vea_profile.profile == VP8PROFILE_ANY;
  207. });
  208. }
  209. if (gpu_workarounds.disable_accelerated_vp9_encode) {
  210. base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
  211. return vea_profile.profile >= VP9PROFILE_PROFILE0 &&
  212. vea_profile.profile <= VP9PROFILE_PROFILE3;
  213. });
  214. }
  215. if (gpu_workarounds.disable_accelerated_h264_encode) {
  216. base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
  217. return vea_profile.profile >= H264PROFILE_MIN &&
  218. vea_profile.profile <= H264PROFILE_MAX;
  219. });
  220. }
  221. base::EraseIf(*profiles_ptr, [](const auto& vea_profile) {
  222. return vea_profile.profile >= HEVCPROFILE_MIN &&
  223. vea_profile.profile <= HEVCPROFILE_MAX;
  224. });
  225. return *profiles_ptr;
  226. }
  227. } // namespace media