1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/mojo/services/gpu_mojo_media_client.h"
9 #include "base/feature_list.h"
10 #include "base/functional/bind.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/metrics/histogram_functions.h"
13 #include "base/task/sequenced_task_runner.h"
14 #include "base/task/single_thread_task_runner.h"
15 #include "build/build_config.h"
16 #include "build/chromeos_buildflags.h"
17 #include "gpu/ipc/service/gpu_channel.h"
18 #include "media/base/audio_decoder.h"
19 #include "media/base/audio_encoder.h"
20 #include "media/base/cdm_factory.h"
21 #include "media/base/media_log.h"
22 #include "media/base/media_switches.h"
23 #include "media/base/media_util.h"
24 #include "media/base/video_decoder.h"
25 #include "media/gpu/gpu_video_accelerator_util.h"
26 #include "media/gpu/gpu_video_decode_accelerator_factory.h"
27 #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
28 #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
29 #include "media/mojo/mojom/video_decoder.mojom.h"
30 #include "media/video/video_decode_accelerator.h"
31 #include "third_party/abseil-cpp/absl/types/optional.h"
37 gpu::CommandBufferStub* GetCommandBufferStub(
38 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
39 base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
40 base::UnguessableToken channel_token,
42 DCHECK(gpu_task_runner->BelongsToCurrentThread());
43 if (!media_gpu_channel_manager)
46 gpu::GpuChannel* channel =
47 media_gpu_channel_manager->LookupChannel(channel_token);
51 gpu::CommandBufferStub* stub = channel->LookupCommandBuffer(route_id);
55 // Only allow stubs that have a ContextGroup, that is, the GLES2 ones. Later
56 // code assumes the ContextGroup is valid.
57 if (!stub->decoder_context()->GetContextGroup())
63 SupportedVideoDecoderConfigs GetVDAVideoDecoderConfigs(
64 const gpu::GpuPreferences& gpu_preferences,
65 const gpu::GpuDriverBugWorkarounds& gpu_workarounds) {
66 VideoDecodeAccelerator::Capabilities capabilities =
67 GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
68 GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
69 gpu_preferences, gpu_workarounds));
70 return ConvertFromSupportedProfiles(
71 capabilities.supported_profiles,
73 VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS);
78 VideoDecoderTraits::~VideoDecoderTraits() = default;
79 VideoDecoderTraits::VideoDecoderTraits(
80 scoped_refptr<base::SequencedTaskRunner> task_runner,
81 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
82 std::unique_ptr<MediaLog> media_log,
83 RequestOverlayInfoCB request_overlay_info_cb,
84 const gfx::ColorSpace* target_color_space,
85 gpu::GpuPreferences gpu_preferences,
86 gpu::GpuFeatureInfo gpu_feature_info,
87 gpu::GPUInfo gpu_info,
88 const gpu::GpuDriverBugWorkarounds* gpu_workarounds,
89 gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
90 GetConfigCacheCB get_cached_configs_cb,
91 GetCommandBufferStubCB get_command_buffer_stub_cb,
92 AndroidOverlayMojoFactoryCB android_overlay_factory_cb,
93 mojo::PendingRemote<stable::mojom::StableVideoDecoder> oop_video_decoder,
94 base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager)
95 : task_runner(std::move(task_runner)),
96 gpu_task_runner(std::move(gpu_task_runner)),
97 media_log(std::move(media_log)),
98 request_overlay_info_cb(request_overlay_info_cb),
99 target_color_space(target_color_space),
100 gpu_preferences(gpu_preferences),
101 gpu_feature_info(gpu_feature_info),
103 gpu_workarounds(gpu_workarounds),
104 gpu_memory_buffer_factory(gpu_memory_buffer_factory),
105 get_cached_configs_cb(std::move(get_cached_configs_cb)),
106 get_command_buffer_stub_cb(std::move(get_command_buffer_stub_cb)),
107 android_overlay_factory_cb(std::move(android_overlay_factory_cb)),
108 oop_video_decoder(std::move(oop_video_decoder)),
109 media_gpu_channel_manager(media_gpu_channel_manager) {}
111 GpuMojoMediaClient::GpuMojoMediaClient(
112 const gpu::GpuPreferences& gpu_preferences,
113 const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
114 const gpu::GpuFeatureInfo& gpu_feature_info,
115 const gpu::GPUInfo& gpu_info,
116 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
117 base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
118 gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
119 AndroidOverlayMojoFactoryCB android_overlay_factory_cb)
120 : gpu_preferences_(gpu_preferences),
121 gpu_workarounds_(gpu_workarounds),
122 gpu_feature_info_(gpu_feature_info),
124 gpu_task_runner_(std::move(gpu_task_runner)),
125 media_gpu_channel_manager_(std::move(media_gpu_channel_manager)),
126 android_overlay_factory_cb_(std::move(android_overlay_factory_cb)),
127 gpu_memory_buffer_factory_(gpu_memory_buffer_factory) {
128 base::UmaHistogramEnumeration("Media.GPU.VideoDecoderType",
129 GetDecoderImplementationType());
132 GpuMojoMediaClient::~GpuMojoMediaClient() = default;
134 std::unique_ptr<AudioDecoder> GpuMojoMediaClient::CreateAudioDecoder(
135 scoped_refptr<base::SequencedTaskRunner> task_runner,
136 std::unique_ptr<MediaLog> media_log) {
137 return CreatePlatformAudioDecoder(std::move(task_runner),
138 std::move(media_log));
141 std::unique_ptr<AudioEncoder> GpuMojoMediaClient::CreateAudioEncoder(
142 scoped_refptr<base::SequencedTaskRunner> task_runner) {
143 return base::FeatureList::IsEnabled(kPlatformAudioEncoder)
144 ? CreatePlatformAudioEncoder(std::move(task_runner))
148 VideoDecoderType GpuMojoMediaClient::GetDecoderImplementationType() {
149 return GetPlatformDecoderImplementationType(gpu_workarounds_,
150 gpu_preferences_, gpu_info_);
153 SupportedVideoDecoderConfigs
154 GpuMojoMediaClient::GetSupportedVideoDecoderConfigs() {
155 if (!supported_config_cache_) {
156 supported_config_cache_ = GetSupportedVideoDecoderConfigsStatic(
157 media_gpu_channel_manager_, gpu_preferences_, gpu_workarounds_,
160 // Once per GPU process record accelerator information. Profile support is
161 // often just manufactured and not tested, so just record the base codec.
162 bool has_accelerated_h264 = false;
163 bool has_accelerated_h265 = false;
164 bool has_accelerated_vp9 = false;
165 bool has_accelerated_av1 = false;
166 if (supported_config_cache_) {
167 for (const auto& config : *supported_config_cache_) {
168 if (config.profile_min >= H264PROFILE_MIN &&
169 config.profile_max <= H264PROFILE_MAX) {
170 has_accelerated_h264 = true;
171 } else if (config.profile_min >= VP9PROFILE_MIN &&
172 config.profile_max <= VP9PROFILE_MAX) {
173 has_accelerated_vp9 = true;
174 } else if (config.profile_min >= AV1PROFILE_MIN &&
175 config.profile_max <= AV1PROFILE_MAX) {
176 has_accelerated_av1 = true;
177 } else if ((config.profile_min >= HEVCPROFILE_MIN &&
178 config.profile_max <= HEVCPROFILE_MAX) ||
179 (config.profile_min >= HEVCPROFILE_EXT_MIN &&
180 config.profile_max <= HEVCPROFILE_EXT_MAX)) {
181 has_accelerated_h265 = true;
186 base::UmaHistogramBoolean("Media.HasAcceleratedVideoDecode.H264",
187 has_accelerated_h264);
188 base::UmaHistogramBoolean("Media.HasAcceleratedVideoDecode.H265",
189 has_accelerated_h265);
190 base::UmaHistogramBoolean("Media.HasAcceleratedVideoDecode.VP9",
191 has_accelerated_vp9);
192 base::UmaHistogramBoolean("Media.HasAcceleratedVideoDecode.AV1",
193 has_accelerated_av1);
195 return supported_config_cache_.value_or(SupportedVideoDecoderConfigs{});
198 absl::optional<SupportedVideoDecoderConfigs>
199 GpuMojoMediaClient::GetSupportedVideoDecoderConfigsStatic(
200 base::WeakPtr<MediaGpuChannelManager> manager,
201 const gpu::GpuPreferences& gpu_preferences,
202 const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
203 const gpu::GPUInfo& gpu_info) {
204 return GetPlatformSupportedVideoDecoderConfigs(
205 manager, gpu_workarounds, gpu_preferences, gpu_info,
206 base::BindOnce(&GetVDAVideoDecoderConfigs, gpu_preferences,
210 #if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
211 void GpuMojoMediaClient::NotifyDecoderSupportKnown(
212 mojo::PendingRemote<stable::mojom::StableVideoDecoder> oop_video_decoder,
214 void(mojo::PendingRemote<stable::mojom::StableVideoDecoder>)> cb) {
215 #if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
216 // TODO(b/195769334): this call should ideally be guarded only by
217 // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER) because eventually, the GPU process
218 // should not need to know what video acceleration API is used. Until then, we
219 // must guard this with (USE_VAAPI || USE_V4L2_CODEC) to be able to compile
220 // Linux/CrOS builds that don't use either API (e.g., linux-x64-castos).
221 NotifyPlatformDecoderSupport(gpu_preferences_, gpu_info_,
222 std::move(oop_video_decoder), std::move(cb));
224 DCHECK(!oop_video_decoder);
225 std::move(cb).Run(std::move(oop_video_decoder));
226 #endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
228 #endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
230 std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
231 scoped_refptr<base::SequencedTaskRunner> task_runner,
233 mojom::CommandBufferIdPtr command_buffer_id,
234 RequestOverlayInfoCB request_overlay_info_cb,
235 const gfx::ColorSpace& target_color_space,
236 mojo::PendingRemote<stable::mojom::StableVideoDecoder> oop_video_decoder) {
237 // All implementations require a command buffer.
238 if (!command_buffer_id)
240 std::unique_ptr<MediaLog> log =
241 media_log ? media_log->Clone() : std::make_unique<media::NullMediaLog>();
242 auto get_stub_cb = base::BindRepeating(
243 &GetCommandBufferStub, gpu_task_runner_, media_gpu_channel_manager_,
244 command_buffer_id->channel_token, command_buffer_id->route_id);
245 VideoDecoderTraits traits(
246 task_runner, gpu_task_runner_, std::move(log),
247 std::move(request_overlay_info_cb), &target_color_space, gpu_preferences_,
248 gpu_feature_info_, gpu_info_, &gpu_workarounds_,
249 gpu_memory_buffer_factory_,
250 // CreatePlatformVideoDecoder does not keep a reference to |traits|
251 // so this bound method will not outlive |this|
252 base::BindRepeating(&GpuMojoMediaClient::GetSupportedVideoDecoderConfigs,
253 base::Unretained(this)),
254 get_stub_cb, android_overlay_factory_cb_, std::move(oop_video_decoder),
255 media_gpu_channel_manager_);
257 return CreatePlatformVideoDecoder(traits);
260 std::unique_ptr<CdmFactory> GpuMojoMediaClient::CreateCdmFactory(
261 mojom::FrameInterfaceFactory* frame_interfaces) {
262 return CreatePlatformCdmFactory(frame_interfaces);