Upload upstream chromium 120.0.6099.5
[platform/framework/web/chromium-efl.git] / media / renderers / decrypting_renderer.cc
1 // Copyright 2018 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/renderers/decrypting_renderer.h"
6
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/task/sequenced_task_runner.h"
10 #include "media/base/cdm_context.h"
11 #include "media/base/demuxer_stream.h"
12 #include "media/base/media_log.h"
13 #include "media/base/media_resource.h"
14 #include "media/base/renderer_client.h"
15 #include "media/filters/decrypting_demuxer_stream.h"
16 #include "media/filters/decrypting_media_resource.h"
17
18 namespace media {
19
20 DecryptingRenderer::DecryptingRenderer(
21     std::unique_ptr<Renderer> renderer,
22     MediaLog* media_log,
23     const scoped_refptr<base::SequencedTaskRunner> media_task_runner)
24     : renderer_(std::move(renderer)),
25       media_log_(media_log),
26       media_task_runner_(media_task_runner),
27       client_(nullptr),
28       media_resource_(nullptr),
29       decrypting_media_resource_(nullptr) {
30   DCHECK(renderer_);
31 }
32
33 DecryptingRenderer::~DecryptingRenderer() {}
34
35 // The behavior of Initialize():
36 //
37 // Streams    CdmContext    Action
38 // ---------------------------------------------------------------------
39 // Clear      nullptr       InitializeRenderer()
40 // Clear      AesDecryptor  CreateAndInitializeDecryptingMediaResource()
41 // Clear      Other         InitializeRenderer()
42 // Encrypted  nullptr       Wait
43 // Encrypted  AesDecryptor  CreateAndInitializeDecryptingMediaResource()
44 // Encrypted  Other         InitializeRenderer()
45 void DecryptingRenderer::Initialize(MediaResource* media_resource,
46                                     RendererClient* client,
47                                     PipelineStatusCallback init_cb) {
48   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
49   DCHECK(media_resource);
50   DCHECK(client);
51
52   // Using |this| with a MediaResource::Type::URL will result in a crash.
53   DCHECK_EQ(media_resource->GetType(), MediaResource::Type::kStream);
54
55   media_resource_ = media_resource;
56   client_ = client;
57   init_cb_ = std::move(init_cb);
58
59   bool has_encrypted_stream = HasEncryptedStream();
60
61   // If we do not have a valid |cdm_context_| and there are encrypted streams we
62   // need to wait.
63   if (!cdm_context_ && has_encrypted_stream) {
64     waiting_for_cdm_ = true;
65     return;
66   }
67
68   if (cdm_context_ && cdm_context_->GetDecryptor() &&
69       cdm_context_->GetDecryptor()->CanAlwaysDecrypt()) {
70     CreateAndInitializeDecryptingMediaResource();
71     return;
72   }
73
74   InitializeRenderer(true);
75 }
76
77 void DecryptingRenderer::SetCdm(CdmContext* cdm_context,
78                                 CdmAttachedCB cdm_attached_cb) {
79   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
80
81   if (cdm_context_) {
82     DVLOG(1) << "Switching CDM not supported.";
83     std::move(cdm_attached_cb).Run(false);
84     return;
85   }
86
87   cdm_context_ = cdm_context;
88
89   // If we are using an AesDecryptor all decryption will be handled by the
90   // DecryptingMediaResource instead of the renderer implementation.
91   if (cdm_context_->GetDecryptor() &&
92       cdm_context_->GetDecryptor()->CanAlwaysDecrypt()) {
93     // If Initialize() was invoked prior to this function then
94     // |waiting_for_cdm_| will be true (if we reached this branch). In this
95     // scenario we want to initialize the DecryptingMediaResource here.
96     if (waiting_for_cdm_)
97       CreateAndInitializeDecryptingMediaResource();
98     std::move(cdm_attached_cb).Run(true);
99     return;
100   }
101
102   renderer_->SetCdm(cdm_context_, std::move(cdm_attached_cb));
103
104   // We only want to initialize the renderer if we were waiting for the
105   // CdmContext, otherwise it will already have been initialized.
106   if (waiting_for_cdm_)
107     InitializeRenderer(true);
108 }
109
110 void DecryptingRenderer::SetLatencyHint(
111     absl::optional<base::TimeDelta> latency_hint) {
112   renderer_->SetLatencyHint(latency_hint);
113 }
114
115 void DecryptingRenderer::SetPreservesPitch(bool preserves_pitch) {
116   renderer_->SetPreservesPitch(preserves_pitch);
117 }
118
119 void DecryptingRenderer::SetWasPlayedWithUserActivation(
120     bool was_played_with_user_activation) {
121   renderer_->SetWasPlayedWithUserActivation(was_played_with_user_activation);
122 }
123
124 void DecryptingRenderer::Flush(base::OnceClosure flush_cb) {
125   renderer_->Flush(std::move(flush_cb));
126 }
127
128 void DecryptingRenderer::StartPlayingFrom(base::TimeDelta time) {
129   renderer_->StartPlayingFrom(time);
130 }
131
132 void DecryptingRenderer::SetPlaybackRate(double playback_rate) {
133   renderer_->SetPlaybackRate(playback_rate);
134 }
135
136 void DecryptingRenderer::SetVolume(float volume) {
137   renderer_->SetVolume(volume);
138 }
139
140 base::TimeDelta DecryptingRenderer::GetMediaTime() {
141   return renderer_->GetMediaTime();
142 }
143
144 void DecryptingRenderer::OnSelectedVideoTracksChanged(
145     const std::vector<DemuxerStream*>& enabled_tracks,
146     base::OnceClosure change_completed_cb) {
147   renderer_->OnSelectedVideoTracksChanged(enabled_tracks,
148                                           std::move(change_completed_cb));
149 }
150
151 void DecryptingRenderer::OnEnabledAudioTracksChanged(
152     const std::vector<DemuxerStream*>& enabled_tracks,
153     base::OnceClosure change_completed_cb) {
154   renderer_->OnEnabledAudioTracksChanged(enabled_tracks,
155                                          std::move(change_completed_cb));
156 }
157
158 RendererType DecryptingRenderer::GetRendererType() {
159   // DecryptingRenderer is a thin wrapping layer; return the underlying type.
160   return renderer_->GetRendererType();
161 }
162
163 void DecryptingRenderer::CreateAndInitializeDecryptingMediaResource() {
164   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
165   DCHECK(init_cb_);
166
167   decrypting_media_resource_ = std::make_unique<DecryptingMediaResource>(
168       media_resource_, cdm_context_, media_log_, media_task_runner_);
169   decrypting_media_resource_->Initialize(
170       base::BindOnce(&DecryptingRenderer::InitializeRenderer,
171                      weak_factory_.GetWeakPtr()),
172       base::BindRepeating(&DecryptingRenderer::OnWaiting,
173                           weak_factory_.GetWeakPtr()));
174 }
175
176 void DecryptingRenderer::InitializeRenderer(bool success) {
177   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
178
179   if (!success) {
180     std::move(init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
181     return;
182   }
183
184   // |decrypting_media_resource_| when |cdm_context_| is null and there are no
185   // encrypted streams.
186   MediaResource* const maybe_decrypting_media_resource =
187       decrypting_media_resource_ ? decrypting_media_resource_.get()
188                                  : media_resource_.get();
189   renderer_->Initialize(maybe_decrypting_media_resource, client_,
190                         std::move(init_cb_));
191 }
192
193 bool DecryptingRenderer::HasEncryptedStream() {
194   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
195
196   for (auto* stream : media_resource_->GetAllStreams()) {
197     if ((stream->type() == DemuxerStream::AUDIO &&
198          stream->audio_decoder_config().is_encrypted()) ||
199         (stream->type() == DemuxerStream::VIDEO &&
200          stream->video_decoder_config().is_encrypted())) {
201       return true;
202     }
203   }
204
205   return false;
206 }
207
208 bool DecryptingRenderer::HasDecryptingMediaResourceForTesting() const {
209   return decrypting_media_resource_ != nullptr;
210 }
211
212 void DecryptingRenderer::OnWaiting(WaitingReason reason) {
213   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
214   client_->OnWaiting(reason);
215 }
216
217 }  // namespace media