1 // Copyright 2016 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 
5 #include "media/mojo/services/gpu_mojo_media_client.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/feature_list.h"
11 #include "base/memory/ptr_util.h"
12 #include "gpu/ipc/service/gpu_channel.h"
13 #include "media/base/audio_decoder.h"
14 #include "media/base/cdm_factory.h"
15 #include "media/base/fallback_video_decoder.h"
16 #include "media/base/media_switches.h"
17 #include "media/base/video_decoder.h"
18 #include "media/gpu/gpu_video_accelerator_util.h"
19 #include "media/gpu/gpu_video_decode_accelerator_factory.h"
20 #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
21 #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
22 #include "media/gpu/ipc/service/vda_video_decoder.h"
23 #include "media/mojo/mojom/video_decoder.mojom.h"
24 #include "media/video/video_decode_accelerator.h"
25 
26 #if defined(OS_ANDROID)
27 #include "base/memory/ptr_util.h"
28 #include "media/base/android/android_cdm_factory.h"
29 #include "media/filters/android/media_codec_audio_decoder.h"
30 #include "media/gpu/android/android_video_surface_chooser_impl.h"
31 #include "media/gpu/android/codec_allocator.h"
32 #include "media/gpu/android/direct_shared_image_video_provider.h"
33 #include "media/gpu/android/maybe_render_early_manager.h"
34 #include "media/gpu/android/media_codec_video_decoder.h"
35 #include "media/gpu/android/pooled_shared_image_video_provider.h"
36 #include "media/gpu/android/video_frame_factory_impl.h"
37 #include "media/mojo/mojom/media_drm_storage.mojom.h"
38 #include "media/mojo/mojom/provision_fetcher.mojom.h"
39 #include "media/mojo/services/mojo_media_drm_storage.h"
40 #include "media/mojo/services/mojo_provision_fetcher.h"
41 #endif  // defined(OS_ANDROID)
42 
43 #if defined(OS_WIN)
44 #include "media/gpu/windows/d3d11_video_decoder.h"
45 #include "ui/gl/gl_angle_util_win.h"
46 #endif  // defined(OS_WIN)
47 
48 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
49 #include "media/gpu/chromeos/chromeos_video_decoder_factory.h"
50 #include "media/gpu/chromeos/mailbox_video_frame_converter.h"
51 #include "media/gpu/chromeos/platform_video_frame_pool.h"
52 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
53 
54 #if defined(OS_ANDROID)
55 #include "media/mojo/services/android_mojo_util.h"
56 using media::android_mojo_util::CreateProvisionFetcher;
57 using media::android_mojo_util::CreateMediaDrmStorage;
58 #endif  // defined(OS_ANDROID)
59 
60 namespace media {
61 
62 namespace {
63 
64 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_MACOSX) || \
65     defined(OS_WIN) || defined(OS_LINUX) || defined(OS_BSD)
GetCommandBufferStub(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,base::UnguessableToken channel_token,int32_t route_id)66 gpu::CommandBufferStub* GetCommandBufferStub(
67     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
68     base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
69     base::UnguessableToken channel_token,
70     int32_t route_id) {
71   DCHECK(gpu_task_runner->BelongsToCurrentThread());
72   if (!media_gpu_channel_manager)
73     return nullptr;
74 
75   gpu::GpuChannel* channel =
76       media_gpu_channel_manager->LookupChannel(channel_token);
77   if (!channel)
78     return nullptr;
79 
80   gpu::CommandBufferStub* stub = channel->LookupCommandBuffer(route_id);
81   if (!stub)
82     return nullptr;
83 
84   // Only allow stubs that have a ContextGroup, that is, the GLES2 ones. Later
85   // code assumes the ContextGroup is valid.
86   if (!stub->decoder_context()->GetContextGroup())
87     return nullptr;
88 
89   return stub;
90 }
91 #endif
92 
93 #if defined(OS_WIN)
94 // Return a callback to get the D3D11 device for D3D11VideoDecoder.  Since it
95 // only supports the ANGLE device right now, that's what we return.
GetD3D11DeviceCallback()96 D3D11VideoDecoder::GetD3D11DeviceCB GetD3D11DeviceCallback() {
97   return base::BindRepeating(
98       []() { return gl::QueryD3D11DeviceObjectFromANGLE(); });
99 }
100 #endif
101 
102 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
103 // Return true if we switch to use new HW-accelerated video decoder.
IsNewAcceleratedVideoDecoderUsed(const gpu::GpuPreferences & gpu_preferences)104 bool IsNewAcceleratedVideoDecoderUsed(
105     const gpu::GpuPreferences& gpu_preferences) {
106   return !gpu_preferences.force_disable_new_accelerated_video_decoder &&
107          base::FeatureList::IsEnabled(kChromeosVideoDecoder);
108 }
109 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
110 
111 }  // namespace
112 
GpuMojoMediaClient(const gpu::GpuPreferences & gpu_preferences,const gpu::GpuDriverBugWorkarounds & gpu_workarounds,const gpu::GpuFeatureInfo & gpu_feature_info,scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,gpu::GpuMemoryBufferFactory * gpu_memory_buffer_factory,AndroidOverlayMojoFactoryCB android_overlay_factory_cb,CdmProxyFactoryCB cdm_proxy_factory_cb)113 GpuMojoMediaClient::GpuMojoMediaClient(
114     const gpu::GpuPreferences& gpu_preferences,
115     const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
116     const gpu::GpuFeatureInfo& gpu_feature_info,
117     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
118     base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
119     gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
120     AndroidOverlayMojoFactoryCB android_overlay_factory_cb,
121     CdmProxyFactoryCB cdm_proxy_factory_cb)
122     : gpu_preferences_(gpu_preferences),
123       gpu_workarounds_(gpu_workarounds),
124       gpu_feature_info_(gpu_feature_info),
125       gpu_task_runner_(std::move(gpu_task_runner)),
126       media_gpu_channel_manager_(std::move(media_gpu_channel_manager)),
127       android_overlay_factory_cb_(std::move(android_overlay_factory_cb)),
128 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
129       gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
130 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
131       cdm_proxy_factory_cb_(std::move(cdm_proxy_factory_cb)) {
132 }
133 
134 GpuMojoMediaClient::~GpuMojoMediaClient() = default;
135 
CreateAudioDecoder(scoped_refptr<base::SingleThreadTaskRunner> task_runner)136 std::unique_ptr<AudioDecoder> GpuMojoMediaClient::CreateAudioDecoder(
137     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
138 #if defined(OS_ANDROID)
139   return std::make_unique<MediaCodecAudioDecoder>(task_runner);
140 #else
141   return nullptr;
142 #endif  // defined(OS_ANDROID)
143 }
144 
145 SupportedVideoDecoderConfigMap
GetSupportedVideoDecoderConfigs()146 GpuMojoMediaClient::GetSupportedVideoDecoderConfigs() {
147 #if defined(OS_ANDROID)
148   static SupportedVideoDecoderConfigMap supported_configs{
149       {VideoDecoderImplementation::kDefault,
150        MediaCodecVideoDecoder::GetSupportedConfigs()},
151   };
152   return supported_configs;
153 #else
154   SupportedVideoDecoderConfigMap supported_config_map;
155 
156 #if defined(OS_WIN)
157   // Start with the configurations supported by D3D11VideoDecoder.
158   // VdaVideoDecoder is still used as a fallback.
159 
160   if (base::FeatureList::IsEnabled(kD3D11VideoDecoder)) {
161     if (!d3d11_supported_configs_) {
162       d3d11_supported_configs_ =
163           D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
164               gpu_preferences_, gpu_workarounds_, GetD3D11DeviceCallback());
165     }
166     supported_config_map[VideoDecoderImplementation::kAlternate] =
167         *d3d11_supported_configs_;
168   }
169 
170 #elif BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
171   if (IsNewAcceleratedVideoDecoderUsed(gpu_preferences_)) {
172     if (!cros_supported_configs_) {
173       cros_supported_configs_ =
174           ChromeosVideoDecoderFactory::GetSupportedConfigs();
175     }
176     supported_config_map[VideoDecoderImplementation::kDefault] =
177         *cros_supported_configs_;
178     return supported_config_map;
179   }
180 #endif
181 
182 #if defined(OS_WIN)
183   if (gpu_workarounds_.disable_dxva_video_decoder) {
184     // If DXVA isn't supported, then return without any supported configs for
185     // the |kDefault| decoder.
186     return supported_config_map;
187   }
188 #endif  // defined(OS_WIN)
189 
190   auto& default_configs =
191       supported_config_map[VideoDecoderImplementation::kDefault];
192 
193   // VdaVideoDecoder will be used to wrap a VDA. Add the configs supported
194   // by the VDA implementation.
195   // TODO(sandersd): Move conversion code into VdaVideoDecoder.
196   VideoDecodeAccelerator::Capabilities capabilities =
197       GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
198           GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
199               gpu_preferences_, gpu_workarounds_));
200   bool allow_encrypted =
201       capabilities.flags &
202       VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS;
203   SupportedVideoDecoderConfigs supported_configs = ConvertFromSupportedProfiles(
204       capabilities.supported_profiles, allow_encrypted);
205   default_configs.insert(default_configs.end(), supported_configs.begin(),
206                          supported_configs.end());
207 
208   return supported_config_map;
209 #endif  // defined(OS_ANDROID)
210 }
211 
CreateVideoDecoder(scoped_refptr<base::SingleThreadTaskRunner> task_runner,MediaLog * media_log,mojom::CommandBufferIdPtr command_buffer_id,VideoDecoderImplementation implementation,RequestOverlayInfoCB request_overlay_info_cb,const gfx::ColorSpace & target_color_space)212 std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
213     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
214     MediaLog* media_log,
215     mojom::CommandBufferIdPtr command_buffer_id,
216     VideoDecoderImplementation implementation,
217     RequestOverlayInfoCB request_overlay_info_cb,
218     const gfx::ColorSpace& target_color_space) {
219   // All implementations require a command buffer.
220   if (!command_buffer_id)
221     return nullptr;
222 
223   std::unique_ptr<VideoDecoder> video_decoder;
224 
225   switch (implementation) {
226     case VideoDecoderImplementation::kDefault: {
227 #if defined(OS_ANDROID)
228       auto get_stub_cb = base::Bind(
229           &GetCommandBufferStub, gpu_task_runner_, media_gpu_channel_manager_,
230           command_buffer_id->channel_token, command_buffer_id->route_id);
231       std::unique_ptr<SharedImageVideoProvider> image_provider;
232       image_provider = std::make_unique<DirectSharedImageVideoProvider>(
233           gpu_task_runner_, get_stub_cb);
234       if (base::FeatureList::IsEnabled(kUsePooledSharedImageVideoProvider)) {
235         // Wrap |image_provider| in a pool.
236         image_provider = PooledSharedImageVideoProvider::Create(
237             gpu_task_runner_, get_stub_cb, std::move(image_provider));
238       }
239       // TODO(liberato): Create this only if we're using Vulkan, else it's
240       // ignored.  If we can tell that here, then VideoFrameFactory can use it
241       // as a signal about whether it's supposed to get YCbCrInfo rather than
242       // requiring the provider to set |is_vulkan| in the ImageRecord.
243       auto ycbcr_helper =
244           YCbCrHelper::Create(gpu_task_runner_, std::move(get_stub_cb));
245       video_decoder = std::make_unique<MediaCodecVideoDecoder>(
246           gpu_preferences_, gpu_feature_info_, media_log->Clone(),
247           DeviceInfo::GetInstance(),
248           CodecAllocator::GetInstance(gpu_task_runner_),
249           std::make_unique<AndroidVideoSurfaceChooserImpl>(
250               DeviceInfo::GetInstance()->IsSetOutputSurfaceSupported()),
251           android_overlay_factory_cb_, std::move(request_overlay_info_cb),
252           std::make_unique<VideoFrameFactoryImpl>(
253               gpu_task_runner_, gpu_preferences_, std::move(image_provider),
254               MaybeRenderEarlyManager::Create(gpu_task_runner_),
255               std::move(ycbcr_helper)));
256 
257 #elif BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
258       if (IsNewAcceleratedVideoDecoderUsed(gpu_preferences_)) {
259         auto frame_pool = std::make_unique<PlatformVideoFramePool>(
260             gpu_memory_buffer_factory_);
261         auto frame_converter = MailboxVideoFrameConverter::Create(
262             base::BindRepeating(&PlatformVideoFramePool::UnwrapFrame,
263                                 base::Unretained(frame_pool.get())),
264             gpu_task_runner_,
265             base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
266                                 media_gpu_channel_manager_,
267                                 command_buffer_id->channel_token,
268                                 command_buffer_id->route_id));
269         video_decoder = ChromeosVideoDecoderFactory::Create(
270             task_runner, std::move(frame_pool), std::move(frame_converter),
271             gpu_memory_buffer_factory_);
272       } else {
273         video_decoder = VdaVideoDecoder::Create(
274             task_runner, gpu_task_runner_, media_log->Clone(),
275             target_color_space, gpu_preferences_, gpu_workarounds_,
276             base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
277                                 media_gpu_channel_manager_,
278                                 command_buffer_id->channel_token,
279                                 command_buffer_id->route_id));
280       }
281 
282 #elif defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX) || defined(OS_BSD)
283 #if defined(OS_WIN)
284       // Don't instantiate the DXVA decoder if it's not supported.
285       if (gpu_workarounds_.disable_dxva_video_decoder)
286         return nullptr;
287 #endif  // defined(OS_WIN)
288       video_decoder = VdaVideoDecoder::Create(
289           task_runner, gpu_task_runner_, media_log->Clone(), target_color_space,
290           gpu_preferences_, gpu_workarounds_,
291           base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
292                               media_gpu_channel_manager_,
293                               command_buffer_id->channel_token,
294                               command_buffer_id->route_id));
295 #endif  // defined(OS_ANDROID)
296     } break;
297 
298     case VideoDecoderImplementation::kAlternate:
299 #if defined(OS_WIN)
300       if (base::FeatureList::IsEnabled(kD3D11VideoDecoder)) {
301         // If nothing has cached the configs yet, then do so now.
302         if (!d3d11_supported_configs_)
303           GetSupportedVideoDecoderConfigs();
304 
305         video_decoder = D3D11VideoDecoder::Create(
306             gpu_task_runner_, media_log->Clone(), gpu_preferences_,
307             gpu_workarounds_,
308             base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
309                                 media_gpu_channel_manager_,
310                                 command_buffer_id->channel_token,
311                                 command_buffer_id->route_id),
312             GetD3D11DeviceCallback(), *d3d11_supported_configs_);
313       }
314 #endif  // defined(OS_WIN)
315   break;
316   };  // switch
317 
318   // |video_decoder| may be null if we don't support |implementation|.
319   return video_decoder;
320 }
321 
CreateCdmFactory(service_manager::mojom::InterfaceProvider * interface_provider)322 std::unique_ptr<CdmFactory> GpuMojoMediaClient::CreateCdmFactory(
323     service_manager::mojom::InterfaceProvider* interface_provider) {
324 #if defined(OS_ANDROID)
325   return std::make_unique<AndroidCdmFactory>(
326       base::BindRepeating(&CreateProvisionFetcher, interface_provider),
327       base::BindRepeating(&CreateMediaDrmStorage, interface_provider));
328 #else
329   return nullptr;
330 #endif  // defined(OS_ANDROID)
331 }
332 
333 #if BUILDFLAG(ENABLE_CDM_PROXY)
CreateCdmProxy(const base::Token & cdm_guid)334 std::unique_ptr<CdmProxy> GpuMojoMediaClient::CreateCdmProxy(
335     const base::Token& cdm_guid) {
336   if (cdm_proxy_factory_cb_)
337     return cdm_proxy_factory_cb_.Run(cdm_guid);
338 
339   return nullptr;
340 }
341 #endif  // BUILDFLAG(ENABLE_CDM_PROXY)
342 
343 }  // namespace media
344