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