1 // Copyright 2013 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 "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h"
6 
7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h>
9 
10 #include "base/bind.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/memory/unsafe_shared_memory_region.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/unguessable_token.h"
16 #include "build/build_config.h"
17 #include "components/viz/common/gpu/context_provider.h"
18 #include "content/child/child_thread_impl.h"
19 #include "content/public/common/content_features.h"
20 #include "content/public/common/service_names.mojom.h"
21 #include "content/renderer/render_thread_impl.h"
22 #include "gpu/command_buffer/client/context_support.h"
23 #include "gpu/command_buffer/client/gles2_interface.h"
24 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
25 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
26 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
27 #include "gpu/ipc/client/gpu_channel_host.h"
28 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
29 #include "media/base/bind_to_current_loop.h"
30 #include "media/gpu/gpu_video_accelerator_util.h"
31 #include "media/gpu/ipc/common/media_messages.h"
32 #include "media/mojo/buildflags.h"
33 #include "media/mojo/clients/mojo_video_decoder.h"
34 #include "media/mojo/clients/mojo_video_encode_accelerator.h"
35 #include "media/video/video_encode_accelerator.h"
36 #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
37 #include "third_party/skia/include/core/SkTypes.h"
38 
39 namespace content {
40 
41 namespace {
42 
43 // This enum values match ContextProviderPhase in histograms.xml
44 enum ContextProviderPhase {
45   CONTEXT_PROVIDER_ACQUIRED = 0,
46   CONTEXT_PROVIDER_RELEASED = 1,
47   CONTEXT_PROVIDER_RELEASED_MAX_VALUE = CONTEXT_PROVIDER_RELEASED,
48 };
49 
RecordContextProviderPhaseUmaEnum(const ContextProviderPhase phase)50 void RecordContextProviderPhaseUmaEnum(const ContextProviderPhase phase) {
51   UMA_HISTOGRAM_ENUMERATION("Media.GPU.HasEverLostContext", phase,
52                             CONTEXT_PROVIDER_RELEASED_MAX_VALUE + 1);
53 }
54 
55 }  // namespace
56 
57 GpuVideoAcceleratorFactoriesImpl::Notifier::Notifier() = default;
58 GpuVideoAcceleratorFactoriesImpl::Notifier::~Notifier() = default;
59 
Register(base::OnceClosure callback)60 void GpuVideoAcceleratorFactoriesImpl::Notifier::Register(
61     base::OnceClosure callback) {
62   if (is_notified_) {
63     std::move(callback).Run();
64     return;
65   }
66   callbacks_.push_back(std::move(callback));
67 }
68 
Notify()69 void GpuVideoAcceleratorFactoriesImpl::Notifier::Notify() {
70   DCHECK(!is_notified_);
71   is_notified_ = true;
72   for (auto& callback : callbacks_)
73     std::move(callback).Run();
74   callbacks_.clear();
75 }
76 
77 // static
78 std::unique_ptr<GpuVideoAcceleratorFactoriesImpl>
Create(scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,const scoped_refptr<base::SequencedTaskRunner> & main_thread_task_runner,const scoped_refptr<base::SequencedTaskRunner> & task_runner,const scoped_refptr<viz::ContextProviderCommandBuffer> & context_provider,bool enable_video_gpu_memory_buffers,bool enable_media_stream_gpu_memory_buffers,bool enable_video_accelerator,mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory_remote,mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_remote)79 GpuVideoAcceleratorFactoriesImpl::Create(
80     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
81     const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner,
82     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
83     const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider,
84     bool enable_video_gpu_memory_buffers,
85     bool enable_media_stream_gpu_memory_buffers,
86     bool enable_video_accelerator,
87     mojo::PendingRemote<media::mojom::InterfaceFactory>
88         interface_factory_remote,
89     mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
90         vea_provider_remote) {
91   RecordContextProviderPhaseUmaEnum(
92       ContextProviderPhase::CONTEXT_PROVIDER_ACQUIRED);
93   return base::WrapUnique(new GpuVideoAcceleratorFactoriesImpl(
94       std::move(gpu_channel_host), main_thread_task_runner, task_runner,
95       context_provider, enable_video_gpu_memory_buffers,
96       enable_media_stream_gpu_memory_buffers, enable_video_accelerator,
97       std::move(interface_factory_remote), std::move(vea_provider_remote)));
98 }
99 
GpuVideoAcceleratorFactoriesImpl(scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,const scoped_refptr<base::SequencedTaskRunner> & main_thread_task_runner,const scoped_refptr<base::SequencedTaskRunner> & task_runner,const scoped_refptr<viz::ContextProviderCommandBuffer> & context_provider,bool enable_video_gpu_memory_buffers,bool enable_media_stream_gpu_memory_buffers,bool enable_video_accelerator,mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory_remote,mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_remote)100 GpuVideoAcceleratorFactoriesImpl::GpuVideoAcceleratorFactoriesImpl(
101     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
102     const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner,
103     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
104     const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider,
105     bool enable_video_gpu_memory_buffers,
106     bool enable_media_stream_gpu_memory_buffers,
107     bool enable_video_accelerator,
108     mojo::PendingRemote<media::mojom::InterfaceFactory>
109         interface_factory_remote,
110     mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
111         vea_provider_remote)
112     : main_thread_task_runner_(main_thread_task_runner),
113       task_runner_(task_runner),
114       gpu_channel_host_(std::move(gpu_channel_host)),
115       context_provider_(context_provider),
116       enable_video_gpu_memory_buffers_(enable_video_gpu_memory_buffers),
117       enable_media_stream_gpu_memory_buffers_(
118           enable_media_stream_gpu_memory_buffers),
119       video_accelerator_enabled_(enable_video_accelerator),
120       gpu_memory_buffer_manager_(
121           RenderThreadImpl::current()->GetGpuMemoryBufferManager()) {
122   DCHECK(main_thread_task_runner_);
123   DCHECK(gpu_channel_host_);
124 
125   task_runner_->PostTask(
126       FROM_HERE,
127       base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner,
128                      base::Unretained(this),
129                      std::move(interface_factory_remote),
130                      std::move(vea_provider_remote)));
131 }
132 
~GpuVideoAcceleratorFactoriesImpl()133 GpuVideoAcceleratorFactoriesImpl::~GpuVideoAcceleratorFactoriesImpl() {}
134 
BindOnTaskRunner(mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory_remote,mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_remote)135 void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner(
136     mojo::PendingRemote<media::mojom::InterfaceFactory>
137         interface_factory_remote,
138     mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
139         vea_provider_remote) {
140   DCHECK(task_runner_->RunsTasksInCurrentSequence());
141   DCHECK(context_provider_);
142 
143   interface_factory_.Bind(std::move(interface_factory_remote));
144   vea_provider_.Bind(std::move(vea_provider_remote));
145 
146   if (context_provider_->BindToCurrentThread() !=
147       gpu::ContextResult::kSuccess) {
148     OnDecoderSupportFailed();
149     OnEncoderSupportFailed();
150     OnContextLost();
151     return;
152   }
153 
154   context_provider_->AddObserver(this);
155 
156   if (video_accelerator_enabled_) {
157     {
158       // TODO(crbug.com/709631): This should be removed.
159       base::AutoLock lock(supported_profiles_lock_);
160       supported_vea_profiles_ =
161           media::GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
162               gpu_channel_host_->gpu_info()
163                   .video_encode_accelerator_supported_profiles);
164     }
165 
166     vea_provider_.set_disconnect_handler(base::BindOnce(
167         &GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed,
168         base::Unretained(this)));
169     vea_provider_->GetVideoEncodeAcceleratorSupportedProfiles(
170         base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::
171                            OnGetVideoEncodeAcceleratorSupportedProfiles,
172                        base::Unretained(this)));
173   } else {
174     OnEncoderSupportFailed();
175   }
176 
177 #if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
178   // Note: This is a bit of a hack, since we don't specify the implementation
179   // before asking for the map of supported configs.  We do this because it
180   // (a) saves an ipc call, and (b) makes the return of those configs atomic.
181   // Otherwise, we might have received configs for kDefault but not yet
182   // kAlternate, for example.
183   interface_factory_->CreateVideoDecoder(
184       video_decoder_.BindNewPipeAndPassReceiver());
185   video_decoder_.set_disconnect_handler(
186       base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed,
187                      base::Unretained(this)));
188   video_decoder_->GetSupportedConfigs(base::BindOnce(
189       &GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs,
190       base::Unretained(this)));
191 #else
192   OnDecoderSupportFailed();
193 #endif  // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
194 }
195 
IsDecoderSupportKnown()196 bool GpuVideoAcceleratorFactoriesImpl::IsDecoderSupportKnown() {
197   base::AutoLock lock(supported_profiles_lock_);
198   return decoder_support_notifier_.is_notified();
199 }
200 
NotifyDecoderSupportKnown(base::OnceClosure callback)201 void GpuVideoAcceleratorFactoriesImpl::NotifyDecoderSupportKnown(
202     base::OnceClosure callback) {
203   base::AutoLock lock(supported_profiles_lock_);
204   decoder_support_notifier_.Register(
205       media::BindToCurrentLoop(std::move(callback)));
206 }
207 
OnSupportedDecoderConfigs(const media::SupportedVideoDecoderConfigMap & supported_configs)208 void GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs(
209     const media::SupportedVideoDecoderConfigMap& supported_configs) {
210   base::AutoLock lock(supported_profiles_lock_);
211   video_decoder_.reset();
212   supported_decoder_configs_ = supported_configs;
213   decoder_support_notifier_.Notify();
214 }
215 
OnDecoderSupportFailed()216 void GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed() {
217   base::AutoLock lock(supported_profiles_lock_);
218   video_decoder_.reset();
219   if (decoder_support_notifier_.is_notified())
220     return;
221   supported_decoder_configs_ = media::SupportedVideoDecoderConfigMap();
222   decoder_support_notifier_.Notify();
223 }
224 
IsEncoderSupportKnown()225 bool GpuVideoAcceleratorFactoriesImpl::IsEncoderSupportKnown() {
226   base::AutoLock lock(supported_profiles_lock_);
227   return encoder_support_notifier_.is_notified();
228 }
229 
NotifyEncoderSupportKnown(base::OnceClosure callback)230 void GpuVideoAcceleratorFactoriesImpl::NotifyEncoderSupportKnown(
231     base::OnceClosure callback) {
232   base::AutoLock lock(supported_profiles_lock_);
233   encoder_support_notifier_.Register(
234       media::BindToCurrentLoop(std::move(callback)));
235 }
236 
237 void GpuVideoAcceleratorFactoriesImpl::
OnGetVideoEncodeAcceleratorSupportedProfiles(const media::VideoEncodeAccelerator::SupportedProfiles & supported_profiles)238     OnGetVideoEncodeAcceleratorSupportedProfiles(
239         const media::VideoEncodeAccelerator::SupportedProfiles&
240             supported_profiles) {
241   base::AutoLock lock(supported_profiles_lock_);
242   supported_vea_profiles_ = supported_profiles;
243   encoder_support_notifier_.Notify();
244 }
245 
OnEncoderSupportFailed()246 void GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed() {
247   base::AutoLock lock(supported_profiles_lock_);
248   if (encoder_support_notifier_.is_notified())
249     return;
250   supported_vea_profiles_ = media::VideoEncodeAccelerator::SupportedProfiles();
251   encoder_support_notifier_.Notify();
252 }
253 
CheckContextLost()254 bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() {
255   DCHECK(task_runner_->RunsTasksInCurrentSequence());
256   if (context_provider_lost_on_media_thread_)
257     return true;
258   if (context_provider_->ContextGL()->GetGraphicsResetStatusKHR() !=
259       GL_NO_ERROR) {
260     OnContextLost();
261     return true;
262   }
263   return false;
264 }
265 
DestroyContext()266 void GpuVideoAcceleratorFactoriesImpl::DestroyContext() {
267   DCHECK(task_runner_->RunsTasksInCurrentSequence());
268   DCHECK(context_provider_lost_on_media_thread_);
269 
270   if (!context_provider_)
271     return;
272 
273   context_provider_->RemoveObserver(this);
274   context_provider_ = nullptr;
275   RecordContextProviderPhaseUmaEnum(
276       ContextProviderPhase::CONTEXT_PROVIDER_RELEASED);
277 }
278 
IsGpuVideoAcceleratorEnabled()279 bool GpuVideoAcceleratorFactoriesImpl::IsGpuVideoAcceleratorEnabled() {
280   return video_accelerator_enabled_;
281 }
282 
GetChannelToken()283 base::UnguessableToken GpuVideoAcceleratorFactoriesImpl::GetChannelToken() {
284   DCHECK(task_runner_->RunsTasksInCurrentSequence());
285   if (CheckContextLost())
286     return base::UnguessableToken();
287 
288   if (channel_token_.is_empty()) {
289     context_provider_->GetCommandBufferProxy()->channel()->Send(
290         new GpuCommandBufferMsg_GetChannelToken(&channel_token_));
291   }
292 
293   return channel_token_;
294 }
295 
GetCommandBufferRouteId()296 int32_t GpuVideoAcceleratorFactoriesImpl::GetCommandBufferRouteId() {
297   DCHECK(task_runner_->RunsTasksInCurrentSequence());
298   if (CheckContextLost())
299     return 0;
300   return context_provider_->GetCommandBufferProxy()->route_id();
301 }
302 
303 media::GpuVideoAcceleratorFactories::Supported
IsDecoderConfigSupported(media::VideoDecoderImplementation implementation,const media::VideoDecoderConfig & config)304 GpuVideoAcceleratorFactoriesImpl::IsDecoderConfigSupported(
305     media::VideoDecoderImplementation implementation,
306     const media::VideoDecoderConfig& config) {
307   // There is no support for alpha channel hardware decoding yet.
308   if (config.alpha_mode() == media::VideoDecoderConfig::AlphaMode::kHasAlpha) {
309     DVLOG(1) << "Alpha transparency formats are not supported.";
310     return Supported::kFalse;
311   }
312 
313   base::AutoLock lock(supported_profiles_lock_);
314 
315   // If GetSupportedConfigs() has not completed (or was never started), report
316   // that all configs are supported. Clients will find out that configs are not
317   // supported when VideoDecoder::Initialize() fails.
318   if (!supported_decoder_configs_)
319     return Supported::kUnknown;
320 
321   auto iter = supported_decoder_configs_->find(implementation);
322   // If the decoder implementation wasn't listed, then fail.  This means that
323   // there is no such decoder implementation.
324   if (iter == supported_decoder_configs_->end())
325     return Supported::kFalse;
326 
327   // Iterate over the supported configs for |impl|.
328   for (const auto& supported : iter->second) {
329     if (supported.Matches(config))
330       return Supported::kTrue;
331   }
332   return Supported::kFalse;
333 }
334 
335 std::unique_ptr<media::VideoDecoder>
CreateVideoDecoder(media::MediaLog * media_log,media::VideoDecoderImplementation implementation,media::RequestOverlayInfoCB request_overlay_info_cb)336 GpuVideoAcceleratorFactoriesImpl::CreateVideoDecoder(
337     media::MediaLog* media_log,
338     media::VideoDecoderImplementation implementation,
339     media::RequestOverlayInfoCB request_overlay_info_cb) {
340   DCHECK(video_accelerator_enabled_);
341   DCHECK(task_runner_->RunsTasksInCurrentSequence());
342   DCHECK(interface_factory_.is_bound());
343 
344 #if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
345   if (CheckContextLost())
346     return nullptr;
347 
348   mojo::PendingRemote<media::mojom::VideoDecoder> video_decoder;
349   interface_factory_->CreateVideoDecoder(
350       video_decoder.InitWithNewPipeAndPassReceiver());
351   return std::make_unique<media::MojoVideoDecoder>(
352       task_runner_, this, media_log, std::move(video_decoder), implementation,
353       std::move(request_overlay_info_cb), rendering_color_space_);
354 #else
355   return nullptr;
356 #endif  // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
357 }
358 
359 std::unique_ptr<media::VideoEncodeAccelerator>
CreateVideoEncodeAccelerator()360 GpuVideoAcceleratorFactoriesImpl::CreateVideoEncodeAccelerator() {
361   DCHECK(video_accelerator_enabled_);
362   DCHECK(task_runner_->RunsTasksInCurrentSequence());
363   DCHECK(vea_provider_.is_bound());
364   if (CheckContextLost())
365     return nullptr;
366 
367   base::AutoLock lock(supported_profiles_lock_);
368   // When |supported_vea_profiles_| is empty, no hw encoder is available or
369   // we have not yet gotten the supported profiles.
370   if (!supported_vea_profiles_) {
371     DVLOG(2) << "VEA's profiles have not yet been gotten";
372   } else if (supported_vea_profiles_->empty()) {
373     // There is no profile supported by VEA.
374     return nullptr;
375   }
376 
377   mojo::PendingRemote<media::mojom::VideoEncodeAccelerator> vea;
378   vea_provider_->CreateVideoEncodeAccelerator(
379       vea.InitWithNewPipeAndPassReceiver());
380 
381   if (!vea)
382     return nullptr;
383 
384   return std::unique_ptr<media::VideoEncodeAccelerator>(
385       new media::MojoVideoEncodeAccelerator(
386           std::move(vea),
387           supported_vea_profiles_.value_or(
388               media::VideoEncodeAccelerator::SupportedProfiles())));
389 }
390 
391 std::unique_ptr<gfx::GpuMemoryBuffer>
CreateGpuMemoryBuffer(const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage)392 GpuVideoAcceleratorFactoriesImpl::CreateGpuMemoryBuffer(
393     const gfx::Size& size,
394     gfx::BufferFormat format,
395     gfx::BufferUsage usage) {
396   return gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
397       size, format, usage, gpu::kNullSurfaceHandle);
398 }
ShouldUseGpuMemoryBuffersForVideoFrames(bool for_media_stream) const399 bool GpuVideoAcceleratorFactoriesImpl::ShouldUseGpuMemoryBuffersForVideoFrames(
400     bool for_media_stream) const {
401   return for_media_stream ? enable_media_stream_gpu_memory_buffers_
402                           : enable_video_gpu_memory_buffers_;
403 }
404 
ImageTextureTarget(gfx::BufferFormat format)405 unsigned GpuVideoAcceleratorFactoriesImpl::ImageTextureTarget(
406     gfx::BufferFormat format) {
407   DCHECK(context_provider_);
408   return gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
409                                      format,
410                                      context_provider_->ContextCapabilities());
411 }
412 
413 media::GpuVideoAcceleratorFactories::OutputFormat
VideoFrameOutputFormat(media::VideoPixelFormat pixel_format)414 GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(
415     media::VideoPixelFormat pixel_format) {
416   DCHECK(task_runner_->RunsTasksInCurrentSequence());
417   if (CheckContextLost())
418     return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
419 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
420   // TODO(sugoi): This configuration is currently used only for testing ChromeOS
421   // on Linux and doesn't support hardware acceleration. OSMesa did not support
422   // any hardware acceleration here, so this was never an issue, but SwiftShader
423   // revealed this issue. See https://crbug.com/859946
424   if (gpu_channel_host_->gpu_info().gl_renderer.find("SwiftShader") !=
425       std::string::npos) {
426     return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
427   }
428 #endif
429   auto capabilities = context_provider_->ContextCapabilities();
430   const size_t bit_depth = media::BitDepth(pixel_format);
431   if (bit_depth > 8) {
432 #if !defined(OS_MAC)
433     // TODO(crbug.com/1101041): Enable P010 support for macOS.
434     if (capabilities.image_ycbcr_p010 && bit_depth == 10)
435       return media::GpuVideoAcceleratorFactories::OutputFormat::P010;
436 
437     // If high bit depth rendering is enabled, bail here, otherwise try and use
438     // XR30 storage, and if not and we support RG textures, use those, albeit at
439     // a reduced bit depth of 8 bits per component.
440     // TODO(mcasas): continue working on this, avoiding dropping information as
441     // long as the hardware may support it https://crbug.com/798485.
442     if (rendering_color_space_.IsHDR())
443       return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
444 #endif
445 
446 #if !defined(OS_WIN)
447     // TODO(mcasas): enable Win https://crbug.com/803451.
448     // TODO(mcasas): remove the |bit_depth| check when libyuv supports more than
449     // just x010ToAR30 conversions, https://crbug.com/libyuv/751.
450     if (bit_depth == 10) {
451       if (capabilities.image_ar30)
452         return media::GpuVideoAcceleratorFactories::OutputFormat::XR30;
453       else if (capabilities.image_ab30)
454         return media::GpuVideoAcceleratorFactories::OutputFormat::XB30;
455     }
456 #endif
457     if (capabilities.texture_rg)
458       return media::GpuVideoAcceleratorFactories::OutputFormat::I420;
459     return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
460   }
461 
462   if (pixel_format == media::PIXEL_FORMAT_I420A) {
463 #if SK_PMCOLOR_BYTE_ORDER(B, G, R, A)
464     return media::GpuVideoAcceleratorFactories::OutputFormat::BGRA;
465 #elif SK_PMCOLOR_BYTE_ORDER(R, G, B, A)
466     return media::GpuVideoAcceleratorFactories::OutputFormat::RGBA;
467 #endif
468   }
469 
470   if (capabilities.image_ycbcr_420v &&
471       !capabilities.image_ycbcr_420v_disabled_for_video_frames) {
472     return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB;
473   }
474   if (capabilities.texture_rg)
475     return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB;
476   return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
477 }
478 
479 gpu::SharedImageInterface*
SharedImageInterface()480 GpuVideoAcceleratorFactoriesImpl::SharedImageInterface() {
481   return CheckContextLost() ? nullptr
482                             : context_provider_->SharedImageInterface();
483 }
484 
485 gpu::GpuMemoryBufferManager*
GpuMemoryBufferManager()486 GpuVideoAcceleratorFactoriesImpl::GpuMemoryBufferManager() {
487   return gpu_memory_buffer_manager_;
488 }
489 
490 base::UnsafeSharedMemoryRegion
CreateSharedMemoryRegion(size_t size)491 GpuVideoAcceleratorFactoriesImpl::CreateSharedMemoryRegion(size_t size) {
492   // If necessary, this call will make a synchronous request to a privileged
493   // process to create the shared region.
494   return base::UnsafeSharedMemoryRegion::Create(size);
495 }
496 
497 scoped_refptr<base::SequencedTaskRunner>
GetTaskRunner()498 GpuVideoAcceleratorFactoriesImpl::GetTaskRunner() {
499   return task_runner_;
500 }
501 
502 base::Optional<media::VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles()503 GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles() {
504   base::AutoLock lock(supported_profiles_lock_);
505   return supported_vea_profiles_;
506 }
507 
508 viz::RasterContextProvider*
GetMediaContextProvider()509 GpuVideoAcceleratorFactoriesImpl::GetMediaContextProvider() {
510   return CheckContextLost() ? nullptr : context_provider_.get();
511 }
512 
SetRenderingColorSpace(const gfx::ColorSpace & color_space)513 void GpuVideoAcceleratorFactoriesImpl::SetRenderingColorSpace(
514     const gfx::ColorSpace& color_space) {
515   rendering_color_space_ = color_space;
516 }
517 
CheckContextProviderLostOnMainThread()518 bool GpuVideoAcceleratorFactoriesImpl::CheckContextProviderLostOnMainThread() {
519   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
520   return context_provider_lost_;
521 }
522 
OnContextLost()523 void GpuVideoAcceleratorFactoriesImpl::OnContextLost() {
524   DCHECK(task_runner_->RunsTasksInCurrentSequence());
525   TRACE_EVENT0("media", "GpuVideoAcceleratorFactoriesImpl::OnContextLost");
526 
527   // Don't delete the |context_provider_| here, we could be in the middle of
528   // it notifying about the loss, and we'd be destroying it while it's on
529   // the stack.
530   context_provider_lost_on_media_thread_ = true;
531   // Inform the main thread of the loss as well, so that this class can be
532   // replaced.
533   main_thread_task_runner_->PostTask(
534       FROM_HERE,
535       base::BindOnce(
536           &GpuVideoAcceleratorFactoriesImpl::SetContextProviderLostOnMainThread,
537           base::Unretained(this)));
538 }
539 
SetContextProviderLostOnMainThread()540 void GpuVideoAcceleratorFactoriesImpl::SetContextProviderLostOnMainThread() {
541   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
542   context_provider_lost_ = true;
543 }
544 
545 }  // namespace content
546