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/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"
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
),
29 key_added_while_decode_pending_(false),
31 weak_factory_(this) {}
33 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
35 const PipelineStatusCB
& status_cb
,
36 const OutputCB
& output_cb
) {
37 DVLOG(2) << "Initialize()";
38 DCHECK(task_runner_
->BelongsToCurrentThread());
39 DCHECK(state_
== kUninitialized
||
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();
52 if (state_
== kUninitialized
) {
53 state_
= kDecryptorRequested
;
54 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(base::Bind(
55 &DecryptingVideoDecoder::SetDecryptor
, weak_this_
)));
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
);
83 // Return empty frames if decoding has finished.
84 if (state_
== kDecodeFinished
) {
85 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
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
113 if (state_
== kPendingDecode
) {
114 DCHECK(!decode_cb_
.is_null());
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());
128 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
129 DCHECK(task_runner_
->BelongsToCurrentThread());
131 if (state_
== kUninitialized
)
135 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
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();
160 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
162 decryptor_attached_cb
.Run(false);
166 decryptor_
= decryptor
;
168 state_
= kPendingDecoderInit
;
169 decryptor_
->InitializeVideoDecoder(
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.
185 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
191 decryptor_
->RegisterNewKeyCB(
194 base::Bind(&DecryptingVideoDecoder::OnKeyAdded
, weak_this_
)));
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_
);
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(
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
);
245 DCHECK_EQ(status
== Decryptor::kSuccess
, frame
.get() != NULL
);
247 if (status
== Decryptor::kError
) {
248 DVLOG(2) << "DeliverFrame() - kError";
250 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
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();
266 state_
= kWaitingForKey
;
270 if (status
== Decryptor::kNeedMoreData
) {
271 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
272 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
274 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
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
286 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
287 DecodePendingBuffer();
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;
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());
314 base::ResetAndReturn(&reset_cb_
).Run();