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