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