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"
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"
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
),
31 key_added_while_decode_pending_(false),
36 std::string
DecryptingVideoDecoder::GetDisplayName() const {
40 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
42 const InitCB
& init_cb
,
43 const OutputCB
& output_cb
) {
44 DVLOG(2) << "Initialize()";
45 DCHECK(task_runner_
->BelongsToCurrentThread());
46 DCHECK(state_
== kUninitialized
||
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();
59 if (state_
== kUninitialized
) {
60 state_
= kDecryptorRequested
;
61 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(base::Bind(
62 &DecryptingVideoDecoder::SetDecryptor
, weak_this_
)));
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
);
90 // Return empty frames if decoding has finished.
91 if (state_
== kDecodeFinished
) {
92 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
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
120 if (state_
== kPendingDecode
) {
121 DCHECK(!decode_cb_
.is_null());
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());
135 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
136 DCHECK(task_runner_
->BelongsToCurrentThread());
138 if (state_
== kUninitialized
)
142 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
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();
167 base::ResetAndReturn(&init_cb_
).Run(false);
169 decryptor_attached_cb
.Run(false);
173 decryptor_
= decryptor
;
175 state_
= kPendingDecoderInit
;
176 decryptor_
->InitializeVideoDecoder(
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.
192 base::ResetAndReturn(&init_cb_
).Run(false);
198 decryptor_
->RegisterNewKeyCB(
201 base::Bind(&DecryptingVideoDecoder::OnKeyAdded
, weak_this_
)));
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_
);
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(
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
);
252 DCHECK_EQ(status
== Decryptor::kSuccess
, frame
.get() != NULL
);
254 if (status
== Decryptor::kError
) {
255 DVLOG(2) << "DeliverFrame() - kError";
257 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
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();
273 state_
= kWaitingForKey
;
274 waiting_for_decryption_key_cb_
.Run();
278 if (status
== Decryptor::kNeedMoreData
) {
279 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
280 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
282 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
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
294 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
295 DecodePendingBuffer();
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;
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());
322 base::ResetAndReturn(&reset_cb_
).Run();