[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / stable_video_decoder_factory_service.cc
1 // Copyright 2021 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.
4
5 #include "media/mojo/services/stable_video_decoder_factory_service.h"
6
7 #include "base/task/single_thread_task_runner.h"
8 #include "base/task/thread_pool.h"
9 #include "components/viz/common/switches.h"
10 #include "gpu/config/gpu_driver_bug_workarounds.h"
11 #include "gpu/config/gpu_preferences.h"
12 #include "media/base/media_log.h"
13 #include "media/base/media_util.h"
14 #include "media/gpu/buildflags.h"
15 #include "media/gpu/chromeos/platform_video_frame_pool.h"
16 #include "media/gpu/chromeos/video_decoder_pipeline.h"
17 #include "media/gpu/gpu_video_accelerator_util.h"
18 #include "media/gpu/gpu_video_decode_accelerator_factory.h"
19 #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
20 #include "media/gpu/ipc/service/vda_video_decoder.h"
21 #include "media/mojo/services/mojo_media_client.h"
22 #include "media/mojo/services/mojo_video_decoder_service.h"
23 #include "media/mojo/services/stable_video_decoder_service.h"
24 #include "media/video/video_decode_accelerator.h"
25 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
26
27 namespace media {
28
29 namespace {
30
31 // This is a lighter alternative to using a GpuMojoMediaClient. While we could
32 // use a GpuMojoMediaClient, that would be abusing the abstraction a bit since
33 // that class is too semantically coupled with the GPU process through things
34 // like its |gpu_task_runner_| and |media_gpu_channel_manager_| members.
35 class MojoMediaClientImpl : public MojoMediaClient {
36  public:
37   MojoMediaClientImpl(const gpu::GpuFeatureInfo& gpu_feature_info,
38                       bool enable_direct_video_decoder)
39       : gpu_driver_bug_workarounds_(
40             gpu_feature_info.enabled_gpu_driver_bug_workarounds),
41         enable_direct_video_decoder_(enable_direct_video_decoder) {}
42   MojoMediaClientImpl(const MojoMediaClientImpl&) = delete;
43   MojoMediaClientImpl& operator=(const MojoMediaClientImpl&) = delete;
44   ~MojoMediaClientImpl() override = default;
45
46   // MojoMediaClient implementation.
47   std::vector<SupportedVideoDecoderConfig> GetSupportedVideoDecoderConfigs()
48       final {
49     absl::optional<std::vector<SupportedVideoDecoderConfig>> configs;
50     switch (GetDecoderImplementationType()) {
51       case VideoDecoderType::kVaapi:
52       case VideoDecoderType::kV4L2:
53         configs = VideoDecoderPipeline::GetSupportedConfigs(
54             GetDecoderImplementationType(), gpu_driver_bug_workarounds_);
55         break;
56       case VideoDecoderType::kVda: {
57         // Note that we pass a default-constructed gpu::GpuPreferences.
58         // GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities() uses the
59         // preferences only to check if accelerated video decoding is disabled.
60         // However, if we're here, we know that accelerated video decoding is
61         // enabled since the browser process checks for this.
62         VideoDecodeAccelerator::Capabilities capabilities =
63             GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
64                 GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
65                     gpu::GpuPreferences(), gpu_driver_bug_workarounds_));
66         configs = ConvertFromSupportedProfiles(
67             capabilities.supported_profiles,
68             capabilities.flags & VideoDecodeAccelerator::Capabilities::
69                                      SUPPORTS_ENCRYPTED_STREAMS);
70         break;
71       }
72       default:
73         NOTREACHED();
74     }
75     return configs.value_or(std::vector<SupportedVideoDecoderConfig>{});
76   }
77   VideoDecoderType GetDecoderImplementationType() final {
78     if (!enable_direct_video_decoder_) {
79       return VideoDecoderType::kVda;
80     }
81
82     // TODO(b/195769334): how can we keep this in sync with
83     // VideoDecoderPipeline::GetDecoderType()?
84 #if BUILDFLAG(USE_VAAPI)
85     return VideoDecoderType::kVaapi;
86 #elif BUILDFLAG(USE_V4L2_CODEC)
87     return VideoDecoderType::kV4L2;
88 #else
89 #error StableVideoDecoderFactoryService should only be built on platforms that
90 #error support video decode acceleration through either VA-API or V4L2.
91 #endif
92   }
93   std::unique_ptr<VideoDecoder> CreateVideoDecoder(
94       scoped_refptr<base::SequencedTaskRunner> task_runner,
95       MediaLog* media_log,
96       mojom::CommandBufferIdPtr command_buffer_id,
97       RequestOverlayInfoCB request_overlay_info_cb,
98       const gfx::ColorSpace& target_color_space,
99       mojo::PendingRemote<stable::mojom::StableVideoDecoder> oop_video_decoder)
100       final {
101     // For out-of-process video decoding, |command_buffer_id| is not used and
102     // should not be supplied.
103     DCHECK(!command_buffer_id);
104
105     DCHECK(!oop_video_decoder);
106
107     std::unique_ptr<MediaLog> log =
108         media_log ? media_log->Clone()
109                   : std::make_unique<media::NullMediaLog>();
110
111     if (GetDecoderImplementationType() == VideoDecoderType::kVda) {
112       if (!gpu_task_runner_) {
113         gpu_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
114             {base::WithBaseSyncPrimitives(), base::MayBlock()},
115             base::SingleThreadTaskRunnerThreadMode::DEDICATED);
116       }
117       // Note that we pass a default-constructed gpu::GpuPreferences.
118       // VdaVideoDecoder::Create() uses the preferences only to check if
119       // accelerated video decoding is disabled. However, if we're here, we know
120       // that accelerated video decoding is enabled since the browser process
121       // checks for this.
122       return VdaVideoDecoder::Create(
123           /*parent_task_runner=*/std::move(task_runner), gpu_task_runner_,
124           std::move(log), target_color_space, gpu::GpuPreferences(),
125           gpu_driver_bug_workarounds_,
126           /*get_stub_cb=*/base::NullCallback(),
127           VideoDecodeAccelerator::Config::OutputMode::kImport);
128     } else {
129       return VideoDecoderPipeline::Create(
130           gpu_driver_bug_workarounds_,
131           /*client_task_runner=*/std::move(task_runner),
132           std::make_unique<PlatformVideoFramePool>(),
133           /*frame_converter=*/nullptr,
134           VideoDecoderPipeline::DefaultPreferredRenderableFourccs(),
135           std::move(log),
136           /*oop_video_decoder=*/{});
137     }
138   }
139
140  private:
141   // A "GPU" thread. With traditional hardware video decoding that runs in the
142   // GPU process, this would be the thread needed to access specific GPU
143   // functionality. For out-of-process video decoding, this isn't really the
144   // "GPU" thread, but we use the terminology of the VdaVideoDecoder::Create()
145   // (as such this member is only used when using the VdaVideoDecoder).
146   //
147   // TODO(b/195769334): could we get rid of this and just use the same task
148   // runner for the |parent_task_runner| and |gpu_task_runner| parameters of
149   // VdaVideoDecoder::Create(). For now, we've made it a dedicated thread in
150   // case the VdaVideoDecoder or any of the underlying components rely on a
151   // separate GPU thread.
152   scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
153   const gpu::GpuDriverBugWorkarounds gpu_driver_bug_workarounds_;
154   const bool enable_direct_video_decoder_;
155 };
156
157 }  // namespace
158
159 StableVideoDecoderFactoryService::StableVideoDecoderFactoryService(
160     const gpu::GpuFeatureInfo& gpu_feature_info,
161     bool enable_direct_video_decoder)
162     : receiver_(this),
163       mojo_media_client_(
164           std::make_unique<MojoMediaClientImpl>(gpu_feature_info,
165                                                 enable_direct_video_decoder)) {
166   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
167   mojo_media_client_->Initialize();
168 }
169
170 StableVideoDecoderFactoryService::~StableVideoDecoderFactoryService() {
171   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
172 }
173
174 void StableVideoDecoderFactoryService::BindReceiver(
175     mojo::PendingReceiver<stable::mojom::StableVideoDecoderFactory> receiver,
176     base::OnceClosure disconnect_cb) {
177   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
178   // The browser process should guarantee that BindReceiver() is only called
179   // once.
180   DCHECK(!receiver_.is_bound());
181   receiver_.Bind(std::move(receiver));
182   receiver_.set_disconnect_handler(std::move(disconnect_cb));
183 }
184
185 void StableVideoDecoderFactoryService::CreateStableVideoDecoder(
186     mojo::PendingReceiver<stable::mojom::StableVideoDecoder> receiver,
187     mojo::PendingRemote<stable::mojom::StableVideoDecoderTracker> tracker) {
188   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
189
190   std::unique_ptr<mojom::VideoDecoder> dst_video_decoder;
191   if (video_decoder_creation_cb_for_testing_) {
192     dst_video_decoder = video_decoder_creation_cb_for_testing_.Run(
193         mojo_media_client_.get(), &cdm_service_context_);
194   } else {
195     dst_video_decoder = std::make_unique<MojoVideoDecoderService>(
196         mojo_media_client_.get(), &cdm_service_context_,
197         mojo::PendingRemote<stable::mojom::StableVideoDecoder>());
198   }
199   video_decoders_.Add(std::make_unique<StableVideoDecoderService>(
200                           std::move(tracker), std::move(dst_video_decoder),
201                           &cdm_service_context_),
202                       std::move(receiver));
203 }
204
205 }  // namespace media