MediaLog: Log selected audio/video decoder name.
[chromium-blink-merge.git] / media / filters / decrypting_video_decoder.cc
blob4a14bad5dcd31c8bf061897be6c1a4c570e6eed3
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 std::string DecryptingVideoDecoder::GetDisplayName() const {
34 return "DecryptingVideoDecoder";
37 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config,
38 bool /* low_delay */,
39 const PipelineStatusCB& status_cb,
40 const OutputCB& output_cb) {
41 DVLOG(2) << "Initialize()";
42 DCHECK(task_runner_->BelongsToCurrentThread());
43 DCHECK(state_ == kUninitialized ||
44 state_ == kIdle ||
45 state_ == kDecodeFinished) << state_;
46 DCHECK(decode_cb_.is_null());
47 DCHECK(reset_cb_.is_null());
48 DCHECK(config.IsValidConfig());
49 DCHECK(config.is_encrypted());
51 init_cb_ = BindToCurrentLoop(status_cb);
52 output_cb_ = BindToCurrentLoop(output_cb);
53 weak_this_ = weak_factory_.GetWeakPtr();
54 config_ = config;
56 if (state_ == kUninitialized) {
57 state_ = kDecryptorRequested;
58 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind(
59 &DecryptingVideoDecoder::SetDecryptor, weak_this_)));
60 return;
63 // Reinitialization.
64 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
65 state_ = kPendingDecoderInit;
66 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind(
67 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
70 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
71 const DecodeCB& decode_cb) {
72 DVLOG(3) << "Decode()";
73 DCHECK(task_runner_->BelongsToCurrentThread());
74 DCHECK(state_ == kIdle ||
75 state_ == kDecodeFinished ||
76 state_ == kError) << state_;
77 DCHECK(!decode_cb.is_null());
78 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
80 decode_cb_ = BindToCurrentLoop(decode_cb);
82 if (state_ == kError) {
83 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
84 return;
87 // Return empty frames if decoding has finished.
88 if (state_ == kDecodeFinished) {
89 base::ResetAndReturn(&decode_cb_).Run(kOk);
90 return;
93 pending_buffer_to_decode_ = buffer;
94 state_ = kPendingDecode;
95 DecodePendingBuffer();
98 void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
99 DVLOG(2) << "Reset() - state: " << state_;
100 DCHECK(task_runner_->BelongsToCurrentThread());
101 DCHECK(state_ == kIdle ||
102 state_ == kPendingDecode ||
103 state_ == kWaitingForKey ||
104 state_ == kDecodeFinished ||
105 state_ == kError) << state_;
106 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
107 DCHECK(reset_cb_.is_null());
109 reset_cb_ = BindToCurrentLoop(closure);
111 decryptor_->ResetDecoder(Decryptor::kVideo);
113 // Reset() cannot complete if the decode callback is still pending.
114 // Defer the resetting process in this case. The |reset_cb_| will be fired
115 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
116 // DeliverFrame().
117 if (state_ == kPendingDecode) {
118 DCHECK(!decode_cb_.is_null());
119 return;
122 if (state_ == kWaitingForKey) {
123 DCHECK(!decode_cb_.is_null());
124 pending_buffer_to_decode_ = NULL;
125 base::ResetAndReturn(&decode_cb_).Run(kAborted);
128 DCHECK(decode_cb_.is_null());
129 DoReset();
132 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
133 DCHECK(task_runner_->BelongsToCurrentThread());
135 if (state_ == kUninitialized)
136 return;
138 if (decryptor_) {
139 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
140 decryptor_ = NULL;
142 if (!set_decryptor_ready_cb_.is_null())
143 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
144 pending_buffer_to_decode_ = NULL;
145 if (!init_cb_.is_null())
146 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
147 if (!decode_cb_.is_null())
148 base::ResetAndReturn(&decode_cb_).Run(kAborted);
149 if (!reset_cb_.is_null())
150 base::ResetAndReturn(&reset_cb_).Run();
153 void DecryptingVideoDecoder::SetDecryptor(
154 Decryptor* decryptor,
155 const DecryptorAttachedCB& decryptor_attached_cb) {
156 DVLOG(2) << "SetDecryptor()";
157 DCHECK(task_runner_->BelongsToCurrentThread());
158 DCHECK_EQ(state_, kDecryptorRequested) << state_;
159 DCHECK(!init_cb_.is_null());
160 DCHECK(!set_decryptor_ready_cb_.is_null());
161 set_decryptor_ready_cb_.Reset();
163 if (!decryptor) {
164 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
165 state_ = kError;
166 decryptor_attached_cb.Run(false);
167 return;
170 decryptor_ = decryptor;
172 state_ = kPendingDecoderInit;
173 decryptor_->InitializeVideoDecoder(
174 config_,
175 BindToCurrentLoop(base::Bind(
176 &DecryptingVideoDecoder::FinishInitialization, weak_this_)));
177 decryptor_attached_cb.Run(true);
180 void DecryptingVideoDecoder::FinishInitialization(bool success) {
181 DVLOG(2) << "FinishInitialization()";
182 DCHECK(task_runner_->BelongsToCurrentThread());
183 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
184 DCHECK(!init_cb_.is_null());
185 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
186 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
188 if (!success) {
189 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
190 decryptor_ = NULL;
191 state_ = kError;
192 return;
195 decryptor_->RegisterNewKeyCB(
196 Decryptor::kVideo,
197 BindToCurrentLoop(
198 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
200 // Success!
201 state_ = kIdle;
202 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
206 void DecryptingVideoDecoder::DecodePendingBuffer() {
207 DCHECK(task_runner_->BelongsToCurrentThread());
208 DCHECK_EQ(state_, kPendingDecode) << state_;
209 TRACE_EVENT_ASYNC_BEGIN0(
210 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_);
212 int buffer_size = 0;
213 if (!pending_buffer_to_decode_->end_of_stream()) {
214 buffer_size = pending_buffer_to_decode_->data_size();
217 decryptor_->DecryptAndDecodeVideo(
218 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind(
219 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size)));
222 void DecryptingVideoDecoder::DeliverFrame(
223 int buffer_size,
224 Decryptor::Status status,
225 const scoped_refptr<VideoFrame>& frame) {
226 DVLOG(3) << "DeliverFrame() - status: " << status;
227 DCHECK(task_runner_->BelongsToCurrentThread());
228 DCHECK_EQ(state_, kPendingDecode) << state_;
229 DCHECK(!decode_cb_.is_null());
230 DCHECK(pending_buffer_to_decode_.get());
232 TRACE_EVENT_ASYNC_END2(
233 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_,
234 "buffer_size", buffer_size, "status", status);
236 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
237 key_added_while_decode_pending_ = false;
239 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
240 pending_buffer_to_decode_;
241 pending_buffer_to_decode_ = NULL;
243 if (!reset_cb_.is_null()) {
244 base::ResetAndReturn(&decode_cb_).Run(kAborted);
245 DoReset();
246 return;
249 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL);
251 if (status == Decryptor::kError) {
252 DVLOG(2) << "DeliverFrame() - kError";
253 state_ = kError;
254 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
255 return;
258 if (status == Decryptor::kNoKey) {
259 DVLOG(2) << "DeliverFrame() - kNoKey";
260 // Set |pending_buffer_to_decode_| back as we need to try decoding the
261 // pending buffer again when new key is added to the decryptor.
262 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
264 if (need_to_try_again_if_nokey_is_returned) {
265 // The |state_| is still kPendingDecode.
266 DecodePendingBuffer();
267 return;
270 state_ = kWaitingForKey;
271 return;
274 if (status == Decryptor::kNeedMoreData) {
275 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
276 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
277 : kIdle;
278 base::ResetAndReturn(&decode_cb_).Run(kOk);
279 return;
282 DCHECK_EQ(status, Decryptor::kSuccess);
283 // No frame returned with kSuccess should be end-of-stream frame.
284 DCHECK(!frame->end_of_stream());
285 output_cb_.Run(frame);
287 if (scoped_pending_buffer_to_decode->end_of_stream()) {
288 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
289 // decryptor.
290 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
291 DecodePendingBuffer();
292 return;
295 state_ = kIdle;
296 base::ResetAndReturn(&decode_cb_).Run(kOk);
299 void DecryptingVideoDecoder::OnKeyAdded() {
300 DVLOG(2) << "OnKeyAdded()";
301 DCHECK(task_runner_->BelongsToCurrentThread());
303 if (state_ == kPendingDecode) {
304 key_added_while_decode_pending_ = true;
305 return;
308 if (state_ == kWaitingForKey) {
309 state_ = kPendingDecode;
310 DecodePendingBuffer();
314 void DecryptingVideoDecoder::DoReset() {
315 DCHECK(init_cb_.is_null());
316 DCHECK(decode_cb_.is_null());
317 state_ = kIdle;
318 base::ResetAndReturn(&reset_cb_).Run();
321 } // namespace media