Upload upstream chromium 85.0.4183.84
[platform/framework/web/chromium-efl.git] / media / filters / decrypting_video_decoder.cc
1 // Copyright (c) 2012 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/filters/decrypting_video_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/bind_to_current_loop.h"
15 #include "media/base/cdm_context.h"
16 #include "media/base/decoder_buffer.h"
17 #include "media/base/media_log.h"
18 #include "media/base/video_frame.h"
19
20 namespace media {
21
22 const char DecryptingVideoDecoder::kDecoderName[] = "DecryptingVideoDecoder";
23
24 DecryptingVideoDecoder::DecryptingVideoDecoder(
25     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
26     MediaLog* media_log)
27     : task_runner_(task_runner), media_log_(media_log) {}
28
29 std::string DecryptingVideoDecoder::GetDisplayName() const {
30   return kDecoderName;
31 }
32
33 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config,
34                                         bool /* low_delay */,
35                                         CdmContext* cdm_context,
36                                         InitCB init_cb,
37                                         const OutputCB& output_cb,
38                                         const WaitingCB& waiting_cb) {
39   DVLOG(2) << __func__ << ": " << config.AsHumanReadableString();
40
41   DCHECK(task_runner_->BelongsToCurrentThread());
42   DCHECK(state_ == kUninitialized || state_ == kIdle ||
43          state_ == kDecodeFinished)
44       << state_;
45   DCHECK(!decode_cb_);
46   DCHECK(!reset_cb_);
47   DCHECK(config.IsValidConfig());
48
49   init_cb_ = BindToCurrentLoop(std::move(init_cb));
50   if (!cdm_context) {
51     // Once we have a CDM context, one should always be present.
52     DCHECK(!support_clear_content_);
53     std::move(init_cb_).Run(StatusCode::kDecoderMissingCdmForEncryptedContent);
54     return;
55   }
56
57   if (!config.is_encrypted() && !support_clear_content_) {
58     std::move(init_cb_).Run(StatusCode::kClearContentUnsupported);
59     return;
60   }
61
62   // Once initialized with encryption support, the value is sticky, so we'll use
63   // the decryptor for clear content as well.
64   support_clear_content_ = true;
65
66   output_cb_ = BindToCurrentLoop(output_cb);
67   weak_this_ = weak_factory_.GetWeakPtr();
68   config_ = config;
69
70   DCHECK(waiting_cb);
71   waiting_cb_ = waiting_cb;
72
73   if (state_ == kUninitialized) {
74     if (!cdm_context->GetDecryptor()) {
75       DVLOG(1) << __func__ << ": no decryptor";
76       std::move(init_cb_).Run(StatusCode::kDecoderFailedInitialization);
77       return;
78     }
79
80     decryptor_ = cdm_context->GetDecryptor();
81   } else {
82     // Reinitialization (i.e. upon a config change). The new config can be
83     // encrypted or clear.
84     decryptor_->DeinitializeDecoder(Decryptor::kVideo);
85   }
86
87   state_ = kPendingDecoderInit;
88   decryptor_->InitializeVideoDecoder(
89       config_, BindToCurrentLoop(base::BindOnce(
90                    &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
91 }
92
93 void DecryptingVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
94                                     DecodeCB decode_cb) {
95   DVLOG(3) << "Decode()";
96   DCHECK(task_runner_->BelongsToCurrentThread());
97   DCHECK(state_ == kIdle || state_ == kDecodeFinished || state_ == kError)
98       << state_;
99   DCHECK(decode_cb);
100   CHECK(!decode_cb_) << "Overlapping decodes are not supported.";
101
102   decode_cb_ = BindToCurrentLoop(std::move(decode_cb));
103
104   if (state_ == kError) {
105     std::move(decode_cb_).Run(DecodeStatus::DECODE_ERROR);
106     return;
107   }
108
109   // Return empty frames if decoding has finished.
110   if (state_ == kDecodeFinished) {
111     std::move(decode_cb_).Run(DecodeStatus::OK);
112     return;
113   }
114
115   pending_buffer_to_decode_ = std::move(buffer);
116   state_ = kPendingDecode;
117   DecodePendingBuffer();
118 }
119
120 void DecryptingVideoDecoder::Reset(base::OnceClosure closure) {
121   DVLOG(2) << "Reset() - state: " << state_;
122   DCHECK(task_runner_->BelongsToCurrentThread());
123   DCHECK(state_ == kIdle || state_ == kPendingDecode ||
124          state_ == kWaitingForKey || state_ == kDecodeFinished ||
125          state_ == kError)
126       << state_;
127   DCHECK(!init_cb_);  // No Reset() during pending initialization.
128   DCHECK(!reset_cb_);
129
130   reset_cb_ = BindToCurrentLoop(std::move(closure));
131
132   decryptor_->ResetDecoder(Decryptor::kVideo);
133
134   // Reset() cannot complete if the decode callback is still pending.
135   // Defer the resetting process in this case. The |reset_cb_| will be fired
136   // after the decode callback is fired - see DecryptAndDecodeBuffer() and
137   // DeliverFrame().
138   if (state_ == kPendingDecode) {
139     DCHECK(decode_cb_);
140     return;
141   }
142
143   if (state_ == kWaitingForKey) {
144     CompleteWaitingForDecryptionKey();
145     DCHECK(decode_cb_);
146     pending_buffer_to_decode_.reset();
147     std::move(decode_cb_).Run(DecodeStatus::ABORTED);
148   }
149
150   DCHECK(!decode_cb_);
151   DoReset();
152 }
153
154 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
155   DCHECK(task_runner_->BelongsToCurrentThread());
156
157   if (state_ == kUninitialized)
158     return;
159
160   if (state_ == kWaitingForKey)
161     CompleteWaitingForDecryptionKey();
162   if (state_ == kPendingDecode)
163     CompletePendingDecode(Decryptor::kError);
164
165   if (decryptor_) {
166     decryptor_->DeinitializeDecoder(Decryptor::kVideo);
167     decryptor_ = nullptr;
168   }
169   pending_buffer_to_decode_.reset();
170   if (init_cb_)
171     std::move(init_cb_).Run(StatusCode::kDecoderInitializeNeverCompleted);
172   if (decode_cb_)
173     std::move(decode_cb_).Run(DecodeStatus::ABORTED);
174   if (reset_cb_)
175     std::move(reset_cb_).Run();
176 }
177
178 void DecryptingVideoDecoder::FinishInitialization(bool success) {
179   DVLOG(2) << "FinishInitialization()";
180   DCHECK(task_runner_->BelongsToCurrentThread());
181   DCHECK_EQ(state_, kPendingDecoderInit) << state_;
182   DCHECK(init_cb_);
183   DCHECK(!reset_cb_);   // No Reset() before initialization finished.
184   DCHECK(!decode_cb_);  // No Decode() before initialization finished.
185
186   if (!success) {
187     DVLOG(1) << __func__ << ": failed to init video decoder on decryptor";
188     std::move(init_cb_).Run(StatusCode::kDecoderInitializeNeverCompleted);
189     decryptor_ = nullptr;
190     state_ = kError;
191     return;
192   }
193
194   decryptor_->RegisterNewKeyCB(
195       Decryptor::kVideo, BindToCurrentLoop(base::BindRepeating(
196                              &DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
197
198   // Success!
199   state_ = kIdle;
200   std::move(init_cb_).Run(OkStatus());
201 }
202
203 void DecryptingVideoDecoder::DecodePendingBuffer() {
204   DCHECK(task_runner_->BelongsToCurrentThread());
205   DCHECK_EQ(state_, kPendingDecode) << state_;
206
207   // Note: Traces require a unique ID per decode, if we ever support multiple
208   // in flight decodes, the trace begin+end macros need the same unique id.
209   DCHECK_EQ(GetMaxDecodeRequests(), 1);
210   TRACE_EVENT_ASYNC_BEGIN1(
211       "media", "DecryptingVideoDecoder::DecodePendingBuffer", this,
212       "timestamp_us",
213       pending_buffer_to_decode_->end_of_stream()
214           ? 0
215           : pending_buffer_to_decode_->timestamp().InMicroseconds());
216
217   decryptor_->DecryptAndDecodeVideo(
218       pending_buffer_to_decode_,
219       BindToCurrentLoop(base::BindRepeating(
220           &DecryptingVideoDecoder::DeliverFrame, weak_this_)));
221 }
222
223 void DecryptingVideoDecoder::DeliverFrame(Decryptor::Status status,
224                                           scoped_refptr<VideoFrame> frame) {
225   DVLOG(3) << "DeliverFrame() - status: " << status;
226   DCHECK(task_runner_->BelongsToCurrentThread());
227   DCHECK_EQ(state_, kPendingDecode) << state_;
228   DCHECK(decode_cb_);
229   DCHECK(pending_buffer_to_decode_.get());
230   CompletePendingDecode(status);
231
232   bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
233   key_added_while_decode_pending_ = false;
234
235   scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
236       std::move(pending_buffer_to_decode_);
237
238   if (reset_cb_) {
239     std::move(decode_cb_).Run(DecodeStatus::ABORTED);
240     DoReset();
241     return;
242   }
243
244   DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != nullptr);
245
246   if (status == Decryptor::kError) {
247     DVLOG(2) << "DeliverFrame() - kError";
248     MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": decode error";
249     state_ = kError;
250     std::move(decode_cb_).Run(DecodeStatus::DECODE_ERROR);
251     return;
252   }
253
254   if (status == Decryptor::kNoKey) {
255     std::string key_id =
256         scoped_pending_buffer_to_decode->decrypt_config()->key_id();
257     std::string log_message =
258         "no key for key ID " + base::HexEncode(key_id.data(), key_id.size()) +
259         "; will resume decoding after new usable key is available";
260     DVLOG(1) << __func__ << ": " << log_message;
261     MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": " << log_message;
262
263     // Set |pending_buffer_to_decode_| back as we need to try decoding the
264     // pending buffer again when new key is added to the decryptor.
265     pending_buffer_to_decode_ = std::move(scoped_pending_buffer_to_decode);
266
267     if (need_to_try_again_if_nokey_is_returned) {
268       // The |state_| is still kPendingDecode.
269       MEDIA_LOG(INFO, media_log_)
270           << GetDisplayName() << ": key was added, resuming decode";
271       DecodePendingBuffer();
272       return;
273     }
274
275     TRACE_EVENT_ASYNC_BEGIN0(
276         "media", "DecryptingVideoDecoder::WaitingForDecryptionKey", this);
277     state_ = kWaitingForKey;
278     waiting_cb_.Run(WaitingReason::kNoDecryptionKey);
279     return;
280   }
281
282   if (status == Decryptor::kNeedMoreData) {
283     DVLOG(2) << "DeliverFrame() - kNeedMoreData";
284     state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
285                                                               : kIdle;
286     std::move(decode_cb_).Run(DecodeStatus::OK);
287     return;
288   }
289
290   DCHECK_EQ(status, Decryptor::kSuccess);
291   CHECK(frame);
292
293   // Frame returned with kSuccess should not be an end-of-stream frame.
294   DCHECK(!frame->metadata()->end_of_stream);
295
296   // If color space is not set, use the color space in the |config_|.
297   if (!frame->ColorSpace().IsValid()) {
298     DVLOG(3) << "Setting color space using information in the config.";
299     if (config_.color_space_info().IsSpecified())
300       frame->set_color_space(config_.color_space_info().ToGfxColorSpace());
301   }
302
303   output_cb_.Run(std::move(frame));
304
305   if (scoped_pending_buffer_to_decode->end_of_stream()) {
306     // Set |pending_buffer_to_decode_| back as we need to keep flushing the
307     // decryptor.
308     pending_buffer_to_decode_ = std::move(scoped_pending_buffer_to_decode);
309     DecodePendingBuffer();
310     return;
311   }
312
313   state_ = kIdle;
314   std::move(decode_cb_).Run(DecodeStatus::OK);
315 }
316
317 void DecryptingVideoDecoder::OnKeyAdded() {
318   DVLOG(2) << "OnKeyAdded()";
319   DCHECK(task_runner_->BelongsToCurrentThread());
320
321   if (state_ == kPendingDecode) {
322     key_added_while_decode_pending_ = true;
323     return;
324   }
325
326   if (state_ == kWaitingForKey) {
327     CompleteWaitingForDecryptionKey();
328     MEDIA_LOG(INFO, media_log_)
329         << GetDisplayName() << ": key added, resuming decode";
330     state_ = kPendingDecode;
331     DecodePendingBuffer();
332   }
333 }
334
335 void DecryptingVideoDecoder::DoReset() {
336   DCHECK(!init_cb_);
337   DCHECK(!decode_cb_);
338   state_ = kIdle;
339   std::move(reset_cb_).Run();
340 }
341
342 void DecryptingVideoDecoder::CompletePendingDecode(Decryptor::Status status) {
343   DCHECK_EQ(state_, kPendingDecode);
344   TRACE_EVENT_ASYNC_END1("media", "DecryptingVideoDecoder::DecodePendingBuffer",
345                          this, "status", Decryptor::GetStatusName(status));
346 }
347
348 void DecryptingVideoDecoder::CompleteWaitingForDecryptionKey() {
349   DCHECK_EQ(state_, kWaitingForKey);
350   TRACE_EVENT_ASYNC_END0(
351       "media", "DecryptingVideoDecoder::WaitingForDecryptionKey", this);
352 }
353
354 }  // namespace media