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