InputImeEventRouter::RegisterImeExtension should register extensions
[chromium-blink-merge.git] / media / filters / decrypting_video_decoder.cc
blob421ec07fa89f8cc1e7ed7bba552ce4fa8d2368e8
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/debug/trace_event.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "media/base/bind_to_current_loop.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/decryptor.h"
16 #include "media/base/pipeline.h"
17 #include "media/base/video_decoder_config.h"
18 #include "media/base/video_frame.h"
20 namespace media {
22 DecryptingVideoDecoder::DecryptingVideoDecoder(
23 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
24 const SetDecryptorReadyCB& set_decryptor_ready_cb)
25 : task_runner_(task_runner),
26 state_(kUninitialized),
27 set_decryptor_ready_cb_(set_decryptor_ready_cb),
28 decryptor_(NULL),
29 key_added_while_decode_pending_(false),
30 trace_id_(0),
31 weak_factory_(this) {}
33 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config,
34 bool /* low_delay */,
35 const PipelineStatusCB& status_cb,
36 const OutputCB& output_cb) {
37 DVLOG(2) << "Initialize()";
38 DCHECK(task_runner_->BelongsToCurrentThread());
39 DCHECK(state_ == kUninitialized ||
40 state_ == kIdle ||
41 state_ == kDecodeFinished) << state_;
42 DCHECK(decode_cb_.is_null());
43 DCHECK(reset_cb_.is_null());
44 DCHECK(config.IsValidConfig());
45 DCHECK(config.is_encrypted());
47 init_cb_ = BindToCurrentLoop(status_cb);
48 output_cb_ = BindToCurrentLoop(output_cb);
49 weak_this_ = weak_factory_.GetWeakPtr();
50 config_ = config;
52 if (state_ == kUninitialized) {
53 state_ = kDecryptorRequested;
54 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind(
55 &DecryptingVideoDecoder::SetDecryptor, weak_this_)));
56 return;
59 // Reinitialization.
60 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
61 state_ = kPendingDecoderInit;
62 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind(
63 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
66 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
67 const DecodeCB& decode_cb) {
68 DVLOG(3) << "Decode()";
69 DCHECK(task_runner_->BelongsToCurrentThread());
70 DCHECK(state_ == kIdle ||
71 state_ == kDecodeFinished ||
72 state_ == kError) << state_;
73 DCHECK(!decode_cb.is_null());
74 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
76 decode_cb_ = BindToCurrentLoop(decode_cb);
78 if (state_ == kError) {
79 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
80 return;
83 // Return empty frames if decoding has finished.
84 if (state_ == kDecodeFinished) {
85 base::ResetAndReturn(&decode_cb_).Run(kOk);
86 return;
89 pending_buffer_to_decode_ = buffer;
90 state_ = kPendingDecode;
91 DecodePendingBuffer();
94 void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
95 DVLOG(2) << "Reset() - state: " << state_;
96 DCHECK(task_runner_->BelongsToCurrentThread());
97 DCHECK(state_ == kIdle ||
98 state_ == kPendingDecode ||
99 state_ == kWaitingForKey ||
100 state_ == kDecodeFinished ||
101 state_ == kError) << state_;
102 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
103 DCHECK(reset_cb_.is_null());
105 reset_cb_ = BindToCurrentLoop(closure);
107 decryptor_->ResetDecoder(Decryptor::kVideo);
109 // Reset() cannot complete if the decode callback is still pending.
110 // Defer the resetting process in this case. The |reset_cb_| will be fired
111 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
112 // DeliverFrame().
113 if (state_ == kPendingDecode) {
114 DCHECK(!decode_cb_.is_null());
115 return;
118 if (state_ == kWaitingForKey) {
119 DCHECK(!decode_cb_.is_null());
120 pending_buffer_to_decode_ = NULL;
121 base::ResetAndReturn(&decode_cb_).Run(kAborted);
124 DCHECK(decode_cb_.is_null());
125 DoReset();
128 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
129 DCHECK(task_runner_->BelongsToCurrentThread());
131 if (state_ == kUninitialized)
132 return;
134 if (decryptor_) {
135 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
136 decryptor_ = NULL;
138 if (!set_decryptor_ready_cb_.is_null())
139 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
140 pending_buffer_to_decode_ = NULL;
141 if (!init_cb_.is_null())
142 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
143 if (!decode_cb_.is_null())
144 base::ResetAndReturn(&decode_cb_).Run(kAborted);
145 if (!reset_cb_.is_null())
146 base::ResetAndReturn(&reset_cb_).Run();
149 void DecryptingVideoDecoder::SetDecryptor(
150 Decryptor* decryptor,
151 const DecryptorAttachedCB& decryptor_attached_cb) {
152 DVLOG(2) << "SetDecryptor()";
153 DCHECK(task_runner_->BelongsToCurrentThread());
154 DCHECK_EQ(state_, kDecryptorRequested) << state_;
155 DCHECK(!init_cb_.is_null());
156 DCHECK(!set_decryptor_ready_cb_.is_null());
157 set_decryptor_ready_cb_.Reset();
159 if (!decryptor) {
160 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
161 state_ = kError;
162 decryptor_attached_cb.Run(false);
163 return;
166 decryptor_ = decryptor;
168 state_ = kPendingDecoderInit;
169 decryptor_->InitializeVideoDecoder(
170 config_,
171 BindToCurrentLoop(base::Bind(
172 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
173 decryptor_attached_cb.Run(true);
176 void DecryptingVideoDecoder::FinishInitialization(bool success) {
177 DVLOG(2) << "FinishInitialization()";
178 DCHECK(task_runner_->BelongsToCurrentThread());
179 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
180 DCHECK(!init_cb_.is_null());
181 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
182 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
184 if (!success) {
185 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
186 decryptor_ = NULL;
187 state_ = kError;
188 return;
191 decryptor_->RegisterNewKeyCB(
192 Decryptor::kVideo,
193 BindToCurrentLoop(
194 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
196 // Success!
197 state_ = kIdle;
198 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
202 void DecryptingVideoDecoder::DecodePendingBuffer() {
203 DCHECK(task_runner_->BelongsToCurrentThread());
204 DCHECK_EQ(state_, kPendingDecode) << state_;
205 TRACE_EVENT_ASYNC_BEGIN0(
206 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_);
208 int buffer_size = 0;
209 if (!pending_buffer_to_decode_->end_of_stream()) {
210 buffer_size = pending_buffer_to_decode_->data_size();
213 decryptor_->DecryptAndDecodeVideo(
214 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind(
215 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size)));
218 void DecryptingVideoDecoder::DeliverFrame(
219 int buffer_size,
220 Decryptor::Status status,
221 const scoped_refptr<VideoFrame>& frame) {
222 DVLOG(3) << "DeliverFrame() - status: " << status;
223 DCHECK(task_runner_->BelongsToCurrentThread());
224 DCHECK_EQ(state_, kPendingDecode) << state_;
225 DCHECK(!decode_cb_.is_null());
226 DCHECK(pending_buffer_to_decode_.get());
228 TRACE_EVENT_ASYNC_END2(
229 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_,
230 "buffer_size", buffer_size, "status", status);
232 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
233 key_added_while_decode_pending_ = false;
235 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
236 pending_buffer_to_decode_;
237 pending_buffer_to_decode_ = NULL;
239 if (!reset_cb_.is_null()) {
240 base::ResetAndReturn(&decode_cb_).Run(kAborted);
241 DoReset();
242 return;
245 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL);
247 if (status == Decryptor::kError) {
248 DVLOG(2) << "DeliverFrame() - kError";
249 state_ = kError;
250 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
251 return;
254 if (status == Decryptor::kNoKey) {
255 DVLOG(2) << "DeliverFrame() - kNoKey";
256 // Set |pending_buffer_to_decode_| back as we need to try decoding the
257 // pending buffer again when new key is added to the decryptor.
258 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
260 if (need_to_try_again_if_nokey_is_returned) {
261 // The |state_| is still kPendingDecode.
262 DecodePendingBuffer();
263 return;
266 state_ = kWaitingForKey;
267 return;
270 if (status == Decryptor::kNeedMoreData) {
271 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
272 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
273 : kIdle;
274 base::ResetAndReturn(&decode_cb_).Run(kOk);
275 return;
278 DCHECK_EQ(status, Decryptor::kSuccess);
279 // No frame returned with kSuccess should be end-of-stream frame.
280 DCHECK(!frame->end_of_stream());
281 output_cb_.Run(frame);
283 if (scoped_pending_buffer_to_decode->end_of_stream()) {
284 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
285 // decryptor.
286 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
287 DecodePendingBuffer();
288 return;
291 state_ = kIdle;
292 base::ResetAndReturn(&decode_cb_).Run(kOk);
295 void DecryptingVideoDecoder::OnKeyAdded() {
296 DVLOG(2) << "OnKeyAdded()";
297 DCHECK(task_runner_->BelongsToCurrentThread());
299 if (state_ == kPendingDecode) {
300 key_added_while_decode_pending_ = true;
301 return;
304 if (state_ == kWaitingForKey) {
305 state_ = kPendingDecode;
306 DecodePendingBuffer();
310 void DecryptingVideoDecoder::DoReset() {
311 DCHECK(init_cb_.is_null());
312 DCHECK(decode_cb_.is_null());
313 state_ = kIdle;
314 base::ResetAndReturn(&reset_cb_).Run();
317 } // namespace media