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/media_log.h"
16 #include "media/base/pipeline.h"
17 #include "media/base/video_frame.h"
21 const char DecryptingVideoDecoder::kDecoderName
[] = "DecryptingVideoDecoder";
23 DecryptingVideoDecoder::DecryptingVideoDecoder(
24 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
25 const scoped_refptr
<MediaLog
>& media_log
,
26 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
27 const base::Closure
& waiting_for_decryption_key_cb
)
28 : task_runner_(task_runner
),
29 media_log_(media_log
),
30 state_(kUninitialized
),
31 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb
),
32 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
34 key_added_while_decode_pending_(false),
39 std::string
DecryptingVideoDecoder::GetDisplayName() const {
43 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
45 const InitCB
& init_cb
,
46 const OutputCB
& output_cb
) {
47 DVLOG(2) << "Initialize()";
48 DCHECK(task_runner_
->BelongsToCurrentThread());
49 DCHECK(state_
== kUninitialized
||
51 state_
== kDecodeFinished
) << state_
;
52 DCHECK(decode_cb_
.is_null());
53 DCHECK(reset_cb_
.is_null());
54 DCHECK(config
.IsValidConfig());
55 DCHECK(config
.is_encrypted());
57 init_cb_
= BindToCurrentLoop(init_cb
);
58 output_cb_
= BindToCurrentLoop(output_cb
);
59 weak_this_
= weak_factory_
.GetWeakPtr();
62 if (state_
== kUninitialized
) {
63 state_
= kDecryptorRequested
;
64 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(base::Bind(
65 &DecryptingVideoDecoder::SetDecryptor
, weak_this_
)));
70 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
71 state_
= kPendingDecoderInit
;
72 decryptor_
->InitializeVideoDecoder(config
, BindToCurrentLoop(base::Bind(
73 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
76 void DecryptingVideoDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
77 const DecodeCB
& decode_cb
) {
78 DVLOG(3) << "Decode()";
79 DCHECK(task_runner_
->BelongsToCurrentThread());
80 DCHECK(state_
== kIdle
||
81 state_
== kDecodeFinished
||
82 state_
== kError
) << state_
;
83 DCHECK(!decode_cb
.is_null());
84 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
86 decode_cb_
= BindToCurrentLoop(decode_cb
);
88 if (state_
== kError
) {
89 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
93 // Return empty frames if decoding has finished.
94 if (state_
== kDecodeFinished
) {
95 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
99 pending_buffer_to_decode_
= buffer
;
100 state_
= kPendingDecode
;
101 DecodePendingBuffer();
104 void DecryptingVideoDecoder::Reset(const base::Closure
& closure
) {
105 DVLOG(2) << "Reset() - state: " << state_
;
106 DCHECK(task_runner_
->BelongsToCurrentThread());
107 DCHECK(state_
== kIdle
||
108 state_
== kPendingDecode
||
109 state_
== kWaitingForKey
||
110 state_
== kDecodeFinished
||
111 state_
== kError
) << state_
;
112 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
113 DCHECK(reset_cb_
.is_null());
115 reset_cb_
= BindToCurrentLoop(closure
);
117 decryptor_
->ResetDecoder(Decryptor::kVideo
);
119 // Reset() cannot complete if the decode callback is still pending.
120 // Defer the resetting process in this case. The |reset_cb_| will be fired
121 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
123 if (state_
== kPendingDecode
) {
124 DCHECK(!decode_cb_
.is_null());
128 if (state_
== kWaitingForKey
) {
129 DCHECK(!decode_cb_
.is_null());
130 pending_buffer_to_decode_
= NULL
;
131 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
134 DCHECK(decode_cb_
.is_null());
138 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
139 DCHECK(task_runner_
->BelongsToCurrentThread());
141 if (state_
== kUninitialized
)
145 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
148 if (!set_decryptor_ready_cb_
.is_null())
149 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
150 pending_buffer_to_decode_
= NULL
;
151 if (!init_cb_
.is_null())
152 base::ResetAndReturn(&init_cb_
).Run(false);
153 if (!decode_cb_
.is_null())
154 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
155 if (!reset_cb_
.is_null())
156 base::ResetAndReturn(&reset_cb_
).Run();
159 void DecryptingVideoDecoder::SetDecryptor(
160 Decryptor
* decryptor
,
161 const DecryptorAttachedCB
& decryptor_attached_cb
) {
162 DVLOG(2) << "SetDecryptor()";
163 DCHECK(task_runner_
->BelongsToCurrentThread());
164 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
165 DCHECK(!init_cb_
.is_null());
166 DCHECK(!set_decryptor_ready_cb_
.is_null());
167 set_decryptor_ready_cb_
.Reset();
170 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName() << ": no decryptor set";
171 base::ResetAndReturn(&init_cb_
).Run(false);
173 decryptor_attached_cb
.Run(false);
177 decryptor_
= decryptor
;
179 state_
= kPendingDecoderInit
;
180 decryptor_
->InitializeVideoDecoder(
182 BindToCurrentLoop(base::Bind(
183 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
184 decryptor_attached_cb
.Run(true);
187 void DecryptingVideoDecoder::FinishInitialization(bool success
) {
188 DVLOG(2) << "FinishInitialization()";
189 DCHECK(task_runner_
->BelongsToCurrentThread());
190 DCHECK_EQ(state_
, kPendingDecoderInit
) << state_
;
191 DCHECK(!init_cb_
.is_null());
192 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
193 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
196 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName()
197 << ": failed to init decoder on decryptor";
198 base::ResetAndReturn(&init_cb_
).Run(false);
204 decryptor_
->RegisterNewKeyCB(
207 base::Bind(&DecryptingVideoDecoder::OnKeyAdded
, weak_this_
)));
211 base::ResetAndReturn(&init_cb_
).Run(true);
215 void DecryptingVideoDecoder::DecodePendingBuffer() {
216 DCHECK(task_runner_
->BelongsToCurrentThread());
217 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
218 TRACE_EVENT_ASYNC_BEGIN0(
219 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_
);
222 if (!pending_buffer_to_decode_
->end_of_stream()) {
223 buffer_size
= pending_buffer_to_decode_
->data_size();
226 decryptor_
->DecryptAndDecodeVideo(
227 pending_buffer_to_decode_
, BindToCurrentLoop(base::Bind(
228 &DecryptingVideoDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
231 void DecryptingVideoDecoder::DeliverFrame(
233 Decryptor::Status status
,
234 const scoped_refptr
<VideoFrame
>& frame
) {
235 DVLOG(3) << "DeliverFrame() - status: " << status
;
236 DCHECK(task_runner_
->BelongsToCurrentThread());
237 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
238 DCHECK(!decode_cb_
.is_null());
239 DCHECK(pending_buffer_to_decode_
.get());
241 TRACE_EVENT_ASYNC_END2(
242 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_
,
243 "buffer_size", buffer_size
, "status", status
);
245 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
246 key_added_while_decode_pending_
= false;
248 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
249 pending_buffer_to_decode_
;
250 pending_buffer_to_decode_
= NULL
;
252 if (!reset_cb_
.is_null()) {
253 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
258 DCHECK_EQ(status
== Decryptor::kSuccess
, frame
.get() != NULL
);
260 if (status
== Decryptor::kError
) {
261 DVLOG(2) << "DeliverFrame() - kError";
262 MEDIA_LOG(ERROR
, media_log_
) << GetDisplayName() << ": decode error";
264 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
268 if (status
== Decryptor::kNoKey
) {
269 DVLOG(2) << "DeliverFrame() - kNoKey";
270 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName() << ": no key";
272 // Set |pending_buffer_to_decode_| back as we need to try decoding the
273 // pending buffer again when new key is added to the decryptor.
274 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
276 if (need_to_try_again_if_nokey_is_returned
) {
277 // The |state_| is still kPendingDecode.
278 DecodePendingBuffer();
282 state_
= kWaitingForKey
;
283 waiting_for_decryption_key_cb_
.Run();
287 if (status
== Decryptor::kNeedMoreData
) {
288 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
289 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
291 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
295 DCHECK_EQ(status
, Decryptor::kSuccess
);
296 // No frame returned with kSuccess should be end-of-stream frame.
297 DCHECK(!frame
->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM
));
298 output_cb_
.Run(frame
);
300 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
301 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
303 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
304 DecodePendingBuffer();
309 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
312 void DecryptingVideoDecoder::OnKeyAdded() {
313 DVLOG(2) << "OnKeyAdded()";
314 DCHECK(task_runner_
->BelongsToCurrentThread());
316 if (state_
== kPendingDecode
) {
317 key_added_while_decode_pending_
= true;
321 if (state_
== kWaitingForKey
) {
322 state_
= kPendingDecode
;
323 DecodePendingBuffer();
327 void DecryptingVideoDecoder::DoReset() {
328 DCHECK(init_cb_
.is_null());
329 DCHECK(decode_cb_
.is_null());
331 base::ResetAndReturn(&reset_cb_
).Run();