media: Reland "Simplify {Audio|Video}Decoder initialization callback."
[chromium-blink-merge.git] / media / filters / decrypting_video_decoder.cc
blob3627080a8653f9ae9d85c04b5f6f75f893886c9e
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/pipeline.h"
16 #include "media/base/video_frame.h"
18 namespace media {
20 const char DecryptingVideoDecoder::kDecoderName[] = "DecryptingVideoDecoder";
22 DecryptingVideoDecoder::DecryptingVideoDecoder(
23 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
24 const SetDecryptorReadyCB& set_decryptor_ready_cb,
25 const base::Closure& waiting_for_decryption_key_cb)
26 : task_runner_(task_runner),
27 state_(kUninitialized),
28 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb),
29 set_decryptor_ready_cb_(set_decryptor_ready_cb),
30 decryptor_(NULL),
31 key_added_while_decode_pending_(false),
32 trace_id_(0),
33 weak_factory_(this) {
36 std::string DecryptingVideoDecoder::GetDisplayName() const {
37 return kDecoderName;
40 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config,
41 bool /* low_delay */,
42 const InitCB& init_cb,
43 const OutputCB& output_cb) {
44 DVLOG(2) << "Initialize()";
45 DCHECK(task_runner_->BelongsToCurrentThread());
46 DCHECK(state_ == kUninitialized ||
47 state_ == kIdle ||
48 state_ == kDecodeFinished) << state_;
49 DCHECK(decode_cb_.is_null());
50 DCHECK(reset_cb_.is_null());
51 DCHECK(config.IsValidConfig());
52 DCHECK(config.is_encrypted());
54 init_cb_ = BindToCurrentLoop(init_cb);
55 output_cb_ = BindToCurrentLoop(output_cb);
56 weak_this_ = weak_factory_.GetWeakPtr();
57 config_ = config;
59 if (state_ == kUninitialized) {
60 state_ = kDecryptorRequested;
61 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind(
62 &DecryptingVideoDecoder::SetDecryptor, weak_this_)));
63 return;
66 // Reinitialization.
67 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
68 state_ = kPendingDecoderInit;
69 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind(
70 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
73 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
74 const DecodeCB& decode_cb) {
75 DVLOG(3) << "Decode()";
76 DCHECK(task_runner_->BelongsToCurrentThread());
77 DCHECK(state_ == kIdle ||
78 state_ == kDecodeFinished ||
79 state_ == kError) << state_;
80 DCHECK(!decode_cb.is_null());
81 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
83 decode_cb_ = BindToCurrentLoop(decode_cb);
85 if (state_ == kError) {
86 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
87 return;
90 // Return empty frames if decoding has finished.
91 if (state_ == kDecodeFinished) {
92 base::ResetAndReturn(&decode_cb_).Run(kOk);
93 return;
96 pending_buffer_to_decode_ = buffer;
97 state_ = kPendingDecode;
98 DecodePendingBuffer();
101 void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
102 DVLOG(2) << "Reset() - state: " << state_;
103 DCHECK(task_runner_->BelongsToCurrentThread());
104 DCHECK(state_ == kIdle ||
105 state_ == kPendingDecode ||
106 state_ == kWaitingForKey ||
107 state_ == kDecodeFinished ||
108 state_ == kError) << state_;
109 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
110 DCHECK(reset_cb_.is_null());
112 reset_cb_ = BindToCurrentLoop(closure);
114 decryptor_->ResetDecoder(Decryptor::kVideo);
116 // Reset() cannot complete if the decode callback is still pending.
117 // Defer the resetting process in this case. The |reset_cb_| will be fired
118 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
119 // DeliverFrame().
120 if (state_ == kPendingDecode) {
121 DCHECK(!decode_cb_.is_null());
122 return;
125 if (state_ == kWaitingForKey) {
126 DCHECK(!decode_cb_.is_null());
127 pending_buffer_to_decode_ = NULL;
128 base::ResetAndReturn(&decode_cb_).Run(kAborted);
131 DCHECK(decode_cb_.is_null());
132 DoReset();
135 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
136 DCHECK(task_runner_->BelongsToCurrentThread());
138 if (state_ == kUninitialized)
139 return;
141 if (decryptor_) {
142 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
143 decryptor_ = NULL;
145 if (!set_decryptor_ready_cb_.is_null())
146 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
147 pending_buffer_to_decode_ = NULL;
148 if (!init_cb_.is_null())
149 base::ResetAndReturn(&init_cb_).Run(false);
150 if (!decode_cb_.is_null())
151 base::ResetAndReturn(&decode_cb_).Run(kAborted);
152 if (!reset_cb_.is_null())
153 base::ResetAndReturn(&reset_cb_).Run();
156 void DecryptingVideoDecoder::SetDecryptor(
157 Decryptor* decryptor,
158 const DecryptorAttachedCB& decryptor_attached_cb) {
159 DVLOG(2) << "SetDecryptor()";
160 DCHECK(task_runner_->BelongsToCurrentThread());
161 DCHECK_EQ(state_, kDecryptorRequested) << state_;
162 DCHECK(!init_cb_.is_null());
163 DCHECK(!set_decryptor_ready_cb_.is_null());
164 set_decryptor_ready_cb_.Reset();
166 if (!decryptor) {
167 base::ResetAndReturn(&init_cb_).Run(false);
168 state_ = kError;
169 decryptor_attached_cb.Run(false);
170 return;
173 decryptor_ = decryptor;
175 state_ = kPendingDecoderInit;
176 decryptor_->InitializeVideoDecoder(
177 config_,
178 BindToCurrentLoop(base::Bind(
179 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
180 decryptor_attached_cb.Run(true);
183 void DecryptingVideoDecoder::FinishInitialization(bool success) {
184 DVLOG(2) << "FinishInitialization()";
185 DCHECK(task_runner_->BelongsToCurrentThread());
186 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
187 DCHECK(!init_cb_.is_null());
188 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
189 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
191 if (!success) {
192 base::ResetAndReturn(&init_cb_).Run(false);
193 decryptor_ = NULL;
194 state_ = kError;
195 return;
198 decryptor_->RegisterNewKeyCB(
199 Decryptor::kVideo,
200 BindToCurrentLoop(
201 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
203 // Success!
204 state_ = kIdle;
205 base::ResetAndReturn(&init_cb_).Run(true);
209 void DecryptingVideoDecoder::DecodePendingBuffer() {
210 DCHECK(task_runner_->BelongsToCurrentThread());
211 DCHECK_EQ(state_, kPendingDecode) << state_;
212 TRACE_EVENT_ASYNC_BEGIN0(
213 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_);
215 int buffer_size = 0;
216 if (!pending_buffer_to_decode_->end_of_stream()) {
217 buffer_size = pending_buffer_to_decode_->data_size();
220 decryptor_->DecryptAndDecodeVideo(
221 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind(
222 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size)));
225 void DecryptingVideoDecoder::DeliverFrame(
226 int buffer_size,
227 Decryptor::Status status,
228 const scoped_refptr<VideoFrame>& frame) {
229 DVLOG(3) << "DeliverFrame() - status: " << status;
230 DCHECK(task_runner_->BelongsToCurrentThread());
231 DCHECK_EQ(state_, kPendingDecode) << state_;
232 DCHECK(!decode_cb_.is_null());
233 DCHECK(pending_buffer_to_decode_.get());
235 TRACE_EVENT_ASYNC_END2(
236 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_,
237 "buffer_size", buffer_size, "status", status);
239 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
240 key_added_while_decode_pending_ = false;
242 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
243 pending_buffer_to_decode_;
244 pending_buffer_to_decode_ = NULL;
246 if (!reset_cb_.is_null()) {
247 base::ResetAndReturn(&decode_cb_).Run(kAborted);
248 DoReset();
249 return;
252 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL);
254 if (status == Decryptor::kError) {
255 DVLOG(2) << "DeliverFrame() - kError";
256 state_ = kError;
257 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
258 return;
261 if (status == Decryptor::kNoKey) {
262 DVLOG(2) << "DeliverFrame() - kNoKey";
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_ = scoped_pending_buffer_to_decode;
267 if (need_to_try_again_if_nokey_is_returned) {
268 // The |state_| is still kPendingDecode.
269 DecodePendingBuffer();
270 return;
273 state_ = kWaitingForKey;
274 waiting_for_decryption_key_cb_.Run();
275 return;
278 if (status == Decryptor::kNeedMoreData) {
279 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
280 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
281 : kIdle;
282 base::ResetAndReturn(&decode_cb_).Run(kOk);
283 return;
286 DCHECK_EQ(status, Decryptor::kSuccess);
287 // No frame returned with kSuccess should be end-of-stream frame.
288 DCHECK(!frame->IsEndOfStream());
289 output_cb_.Run(frame);
291 if (scoped_pending_buffer_to_decode->end_of_stream()) {
292 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
293 // decryptor.
294 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
295 DecodePendingBuffer();
296 return;
299 state_ = kIdle;
300 base::ResetAndReturn(&decode_cb_).Run(kOk);
303 void DecryptingVideoDecoder::OnKeyAdded() {
304 DVLOG(2) << "OnKeyAdded()";
305 DCHECK(task_runner_->BelongsToCurrentThread());
307 if (state_ == kPendingDecode) {
308 key_added_while_decode_pending_ = true;
309 return;
312 if (state_ == kWaitingForKey) {
313 state_ = kPendingDecode;
314 DecodePendingBuffer();
318 void DecryptingVideoDecoder::DoReset() {
319 DCHECK(init_cb_.is_null());
320 DCHECK(decode_cb_.is_null());
321 state_ = kIdle;
322 base::ResetAndReturn(&reset_cb_).Run();
325 } // namespace media