Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / filters / decrypting_video_decoder.cc
blob19e62b3ab30b05be08851852f85737471ef6d31a
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.
5 #include "media/filters/decrypting_video_decoder.h"
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/trace_event/trace_event.h"
13 #include "media/base/bind_to_current_loop.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/media_log.h"
16 #include "media/base/pipeline.h"
17 #include "media/base/video_frame.h"
19 namespace media {
21 const char DecryptingVideoDecoder::kDecoderName[] = "DecryptingVideoDecoder";
23 DecryptingVideoDecoder::DecryptingVideoDecoder(
24 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
25 const scoped_refptr<MediaLog>& media_log,
26 const SetDecryptorReadyCB& set_decryptor_ready_cb,
27 const base::Closure& waiting_for_decryption_key_cb)
28 : task_runner_(task_runner),
29 media_log_(media_log),
30 state_(kUninitialized),
31 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb),
32 set_decryptor_ready_cb_(set_decryptor_ready_cb),
33 decryptor_(NULL),
34 key_added_while_decode_pending_(false),
35 trace_id_(0),
36 weak_factory_(this) {
39 std::string DecryptingVideoDecoder::GetDisplayName() const {
40 return kDecoderName;
43 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config,
44 bool /* low_delay */,
45 const InitCB& init_cb,
46 const OutputCB& output_cb) {
47 DVLOG(2) << "Initialize()";
48 DCHECK(task_runner_->BelongsToCurrentThread());
49 DCHECK(state_ == kUninitialized ||
50 state_ == kIdle ||
51 state_ == kDecodeFinished) << state_;
52 DCHECK(decode_cb_.is_null());
53 DCHECK(reset_cb_.is_null());
54 DCHECK(config.IsValidConfig());
55 DCHECK(config.is_encrypted());
57 init_cb_ = BindToCurrentLoop(init_cb);
58 output_cb_ = BindToCurrentLoop(output_cb);
59 weak_this_ = weak_factory_.GetWeakPtr();
60 config_ = config;
62 if (state_ == kUninitialized) {
63 state_ = kDecryptorRequested;
64 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind(
65 &DecryptingVideoDecoder::SetDecryptor, weak_this_)));
66 return;
69 // Reinitialization.
70 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
71 state_ = kPendingDecoderInit;
72 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind(
73 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
76 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
77 const DecodeCB& decode_cb) {
78 DVLOG(3) << "Decode()";
79 DCHECK(task_runner_->BelongsToCurrentThread());
80 DCHECK(state_ == kIdle ||
81 state_ == kDecodeFinished ||
82 state_ == kError) << state_;
83 DCHECK(!decode_cb.is_null());
84 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
86 decode_cb_ = BindToCurrentLoop(decode_cb);
88 if (state_ == kError) {
89 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
90 return;
93 // Return empty frames if decoding has finished.
94 if (state_ == kDecodeFinished) {
95 base::ResetAndReturn(&decode_cb_).Run(kOk);
96 return;
99 pending_buffer_to_decode_ = buffer;
100 state_ = kPendingDecode;
101 DecodePendingBuffer();
104 void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
105 DVLOG(2) << "Reset() - state: " << state_;
106 DCHECK(task_runner_->BelongsToCurrentThread());
107 DCHECK(state_ == kIdle ||
108 state_ == kPendingDecode ||
109 state_ == kWaitingForKey ||
110 state_ == kDecodeFinished ||
111 state_ == kError) << state_;
112 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
113 DCHECK(reset_cb_.is_null());
115 reset_cb_ = BindToCurrentLoop(closure);
117 decryptor_->ResetDecoder(Decryptor::kVideo);
119 // Reset() cannot complete if the decode callback is still pending.
120 // Defer the resetting process in this case. The |reset_cb_| will be fired
121 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
122 // DeliverFrame().
123 if (state_ == kPendingDecode) {
124 DCHECK(!decode_cb_.is_null());
125 return;
128 if (state_ == kWaitingForKey) {
129 DCHECK(!decode_cb_.is_null());
130 pending_buffer_to_decode_ = NULL;
131 base::ResetAndReturn(&decode_cb_).Run(kAborted);
134 DCHECK(decode_cb_.is_null());
135 DoReset();
138 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
139 DCHECK(task_runner_->BelongsToCurrentThread());
141 if (state_ == kUninitialized)
142 return;
144 if (decryptor_) {
145 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
146 decryptor_ = NULL;
148 if (!set_decryptor_ready_cb_.is_null())
149 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
150 pending_buffer_to_decode_ = NULL;
151 if (!init_cb_.is_null())
152 base::ResetAndReturn(&init_cb_).Run(false);
153 if (!decode_cb_.is_null())
154 base::ResetAndReturn(&decode_cb_).Run(kAborted);
155 if (!reset_cb_.is_null())
156 base::ResetAndReturn(&reset_cb_).Run();
159 void DecryptingVideoDecoder::SetDecryptor(
160 Decryptor* decryptor,
161 const DecryptorAttachedCB& decryptor_attached_cb) {
162 DVLOG(2) << "SetDecryptor()";
163 DCHECK(task_runner_->BelongsToCurrentThread());
164 DCHECK_EQ(state_, kDecryptorRequested) << state_;
165 DCHECK(!init_cb_.is_null());
166 DCHECK(!set_decryptor_ready_cb_.is_null());
167 set_decryptor_ready_cb_.Reset();
169 if (!decryptor) {
170 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor set";
171 base::ResetAndReturn(&init_cb_).Run(false);
172 state_ = kError;
173 decryptor_attached_cb.Run(false);
174 return;
177 decryptor_ = decryptor;
179 state_ = kPendingDecoderInit;
180 decryptor_->InitializeVideoDecoder(
181 config_,
182 BindToCurrentLoop(base::Bind(
183 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
184 decryptor_attached_cb.Run(true);
187 void DecryptingVideoDecoder::FinishInitialization(bool success) {
188 DVLOG(2) << "FinishInitialization()";
189 DCHECK(task_runner_->BelongsToCurrentThread());
190 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
191 DCHECK(!init_cb_.is_null());
192 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
193 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
195 if (!success) {
196 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName()
197 << ": failed to init decoder on decryptor";
198 base::ResetAndReturn(&init_cb_).Run(false);
199 decryptor_ = NULL;
200 state_ = kError;
201 return;
204 decryptor_->RegisterNewKeyCB(
205 Decryptor::kVideo,
206 BindToCurrentLoop(
207 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
209 // Success!
210 state_ = kIdle;
211 base::ResetAndReturn(&init_cb_).Run(true);
215 void DecryptingVideoDecoder::DecodePendingBuffer() {
216 DCHECK(task_runner_->BelongsToCurrentThread());
217 DCHECK_EQ(state_, kPendingDecode) << state_;
218 TRACE_EVENT_ASYNC_BEGIN0(
219 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_);
221 int buffer_size = 0;
222 if (!pending_buffer_to_decode_->end_of_stream()) {
223 buffer_size = pending_buffer_to_decode_->data_size();
226 decryptor_->DecryptAndDecodeVideo(
227 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind(
228 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size)));
231 void DecryptingVideoDecoder::DeliverFrame(
232 int buffer_size,
233 Decryptor::Status status,
234 const scoped_refptr<VideoFrame>& frame) {
235 DVLOG(3) << "DeliverFrame() - status: " << status;
236 DCHECK(task_runner_->BelongsToCurrentThread());
237 DCHECK_EQ(state_, kPendingDecode) << state_;
238 DCHECK(!decode_cb_.is_null());
239 DCHECK(pending_buffer_to_decode_.get());
241 TRACE_EVENT_ASYNC_END2(
242 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_,
243 "buffer_size", buffer_size, "status", status);
245 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
246 key_added_while_decode_pending_ = false;
248 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
249 pending_buffer_to_decode_;
250 pending_buffer_to_decode_ = NULL;
252 if (!reset_cb_.is_null()) {
253 base::ResetAndReturn(&decode_cb_).Run(kAborted);
254 DoReset();
255 return;
258 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL);
260 if (status == Decryptor::kError) {
261 DVLOG(2) << "DeliverFrame() - kError";
262 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": decode error";
263 state_ = kError;
264 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
265 return;
268 if (status == Decryptor::kNoKey) {
269 DVLOG(2) << "DeliverFrame() - kNoKey";
270 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no key";
272 // Set |pending_buffer_to_decode_| back as we need to try decoding the
273 // pending buffer again when new key is added to the decryptor.
274 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
276 if (need_to_try_again_if_nokey_is_returned) {
277 // The |state_| is still kPendingDecode.
278 DecodePendingBuffer();
279 return;
282 state_ = kWaitingForKey;
283 waiting_for_decryption_key_cb_.Run();
284 return;
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(kOk);
292 return;
295 DCHECK_EQ(status, Decryptor::kSuccess);
296 // No frame returned with kSuccess should be end-of-stream frame.
297 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM));
298 output_cb_.Run(frame);
300 if (scoped_pending_buffer_to_decode->end_of_stream()) {
301 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
302 // decryptor.
303 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
304 DecodePendingBuffer();
305 return;
308 state_ = kIdle;
309 base::ResetAndReturn(&decode_cb_).Run(kOk);
312 void DecryptingVideoDecoder::OnKeyAdded() {
313 DVLOG(2) << "OnKeyAdded()";
314 DCHECK(task_runner_->BelongsToCurrentThread());
316 if (state_ == kPendingDecode) {
317 key_added_while_decode_pending_ = true;
318 return;
321 if (state_ == kWaitingForKey) {
322 state_ = kPendingDecode;
323 DecodePendingBuffer();
327 void DecryptingVideoDecoder::DoReset() {
328 DCHECK(init_cb_.is_null());
329 DCHECK(decode_cb_.is_null());
330 state_ = kIdle;
331 base::ResetAndReturn(&reset_cb_).Run();
334 } // namespace media