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/decryptor.h"
16 #include "media/base/pipeline.h"
17 #include "media/base/video_decoder_config.h"
18 #include "media/base/video_frame.h"
22 const char DecryptingVideoDecoder::kDecoderName
[] = "DecryptingVideoDecoder";
24 DecryptingVideoDecoder::DecryptingVideoDecoder(
25 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
26 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
27 const base::Closure
& waiting_for_decryption_key_cb
)
28 : task_runner_(task_runner
),
29 state_(kUninitialized
),
30 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb
),
31 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
33 key_added_while_decode_pending_(false),
38 std::string
DecryptingVideoDecoder::GetDisplayName() const {
42 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
44 const PipelineStatusCB
& status_cb
,
45 const OutputCB
& output_cb
) {
46 DVLOG(2) << "Initialize()";
47 DCHECK(task_runner_
->BelongsToCurrentThread());
48 DCHECK(state_
== kUninitialized
||
50 state_
== kDecodeFinished
) << state_
;
51 DCHECK(decode_cb_
.is_null());
52 DCHECK(reset_cb_
.is_null());
53 DCHECK(config
.IsValidConfig());
54 DCHECK(config
.is_encrypted());
56 init_cb_
= BindToCurrentLoop(status_cb
);
57 output_cb_
= BindToCurrentLoop(output_cb
);
58 weak_this_
= weak_factory_
.GetWeakPtr();
61 if (state_
== kUninitialized
) {
62 state_
= kDecryptorRequested
;
63 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(base::Bind(
64 &DecryptingVideoDecoder::SetDecryptor
, weak_this_
)));
69 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
70 state_
= kPendingDecoderInit
;
71 decryptor_
->InitializeVideoDecoder(config
, BindToCurrentLoop(base::Bind(
72 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
75 void DecryptingVideoDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
76 const DecodeCB
& decode_cb
) {
77 DVLOG(3) << "Decode()";
78 DCHECK(task_runner_
->BelongsToCurrentThread());
79 DCHECK(state_
== kIdle
||
80 state_
== kDecodeFinished
||
81 state_
== kError
) << state_
;
82 DCHECK(!decode_cb
.is_null());
83 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
85 decode_cb_
= BindToCurrentLoop(decode_cb
);
87 if (state_
== kError
) {
88 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
92 // Return empty frames if decoding has finished.
93 if (state_
== kDecodeFinished
) {
94 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
98 pending_buffer_to_decode_
= buffer
;
99 state_
= kPendingDecode
;
100 DecodePendingBuffer();
103 void DecryptingVideoDecoder::Reset(const base::Closure
& closure
) {
104 DVLOG(2) << "Reset() - state: " << state_
;
105 DCHECK(task_runner_
->BelongsToCurrentThread());
106 DCHECK(state_
== kIdle
||
107 state_
== kPendingDecode
||
108 state_
== kWaitingForKey
||
109 state_
== kDecodeFinished
||
110 state_
== kError
) << state_
;
111 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
112 DCHECK(reset_cb_
.is_null());
114 reset_cb_
= BindToCurrentLoop(closure
);
116 decryptor_
->ResetDecoder(Decryptor::kVideo
);
118 // Reset() cannot complete if the decode callback is still pending.
119 // Defer the resetting process in this case. The |reset_cb_| will be fired
120 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
122 if (state_
== kPendingDecode
) {
123 DCHECK(!decode_cb_
.is_null());
127 if (state_
== kWaitingForKey
) {
128 DCHECK(!decode_cb_
.is_null());
129 pending_buffer_to_decode_
= NULL
;
130 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
133 DCHECK(decode_cb_
.is_null());
137 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
138 DCHECK(task_runner_
->BelongsToCurrentThread());
140 if (state_
== kUninitialized
)
144 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
147 if (!set_decryptor_ready_cb_
.is_null())
148 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
149 pending_buffer_to_decode_
= NULL
;
150 if (!init_cb_
.is_null())
151 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
152 if (!decode_cb_
.is_null())
153 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
154 if (!reset_cb_
.is_null())
155 base::ResetAndReturn(&reset_cb_
).Run();
158 void DecryptingVideoDecoder::SetDecryptor(
159 Decryptor
* decryptor
,
160 const DecryptorAttachedCB
& decryptor_attached_cb
) {
161 DVLOG(2) << "SetDecryptor()";
162 DCHECK(task_runner_
->BelongsToCurrentThread());
163 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
164 DCHECK(!init_cb_
.is_null());
165 DCHECK(!set_decryptor_ready_cb_
.is_null());
166 set_decryptor_ready_cb_
.Reset();
169 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
171 decryptor_attached_cb
.Run(false);
175 decryptor_
= decryptor
;
177 state_
= kPendingDecoderInit
;
178 decryptor_
->InitializeVideoDecoder(
180 BindToCurrentLoop(base::Bind(
181 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
182 decryptor_attached_cb
.Run(true);
185 void DecryptingVideoDecoder::FinishInitialization(bool success
) {
186 DVLOG(2) << "FinishInitialization()";
187 DCHECK(task_runner_
->BelongsToCurrentThread());
188 DCHECK_EQ(state_
, kPendingDecoderInit
) << state_
;
189 DCHECK(!init_cb_
.is_null());
190 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
191 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
194 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
200 decryptor_
->RegisterNewKeyCB(
203 base::Bind(&DecryptingVideoDecoder::OnKeyAdded
, weak_this_
)));
207 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
211 void DecryptingVideoDecoder::DecodePendingBuffer() {
212 DCHECK(task_runner_
->BelongsToCurrentThread());
213 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
214 TRACE_EVENT_ASYNC_BEGIN0(
215 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_
);
218 if (!pending_buffer_to_decode_
->end_of_stream()) {
219 buffer_size
= pending_buffer_to_decode_
->data_size();
222 decryptor_
->DecryptAndDecodeVideo(
223 pending_buffer_to_decode_
, BindToCurrentLoop(base::Bind(
224 &DecryptingVideoDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
227 void DecryptingVideoDecoder::DeliverFrame(
229 Decryptor::Status status
,
230 const scoped_refptr
<VideoFrame
>& frame
) {
231 DVLOG(3) << "DeliverFrame() - status: " << status
;
232 DCHECK(task_runner_
->BelongsToCurrentThread());
233 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
234 DCHECK(!decode_cb_
.is_null());
235 DCHECK(pending_buffer_to_decode_
.get());
237 TRACE_EVENT_ASYNC_END2(
238 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_
,
239 "buffer_size", buffer_size
, "status", status
);
241 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
242 key_added_while_decode_pending_
= false;
244 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
245 pending_buffer_to_decode_
;
246 pending_buffer_to_decode_
= NULL
;
248 if (!reset_cb_
.is_null()) {
249 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
254 DCHECK_EQ(status
== Decryptor::kSuccess
, frame
.get() != NULL
);
256 if (status
== Decryptor::kError
) {
257 DVLOG(2) << "DeliverFrame() - kError";
259 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
263 if (status
== Decryptor::kNoKey
) {
264 DVLOG(2) << "DeliverFrame() - kNoKey";
265 // Set |pending_buffer_to_decode_| back as we need to try decoding the
266 // pending buffer again when new key is added to the decryptor.
267 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
269 if (need_to_try_again_if_nokey_is_returned
) {
270 // The |state_| is still kPendingDecode.
271 DecodePendingBuffer();
275 state_
= kWaitingForKey
;
276 waiting_for_decryption_key_cb_
.Run();
280 if (status
== Decryptor::kNeedMoreData
) {
281 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
282 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
284 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
288 DCHECK_EQ(status
, Decryptor::kSuccess
);
289 // No frame returned with kSuccess should be end-of-stream frame.
290 DCHECK(!frame
->end_of_stream());
291 output_cb_
.Run(frame
);
293 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
294 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
296 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
297 DecodePendingBuffer();
302 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
305 void DecryptingVideoDecoder::OnKeyAdded() {
306 DVLOG(2) << "OnKeyAdded()";
307 DCHECK(task_runner_
->BelongsToCurrentThread());
309 if (state_
== kPendingDecode
) {
310 key_added_while_decode_pending_
= true;
314 if (state_
== kWaitingForKey
) {
315 state_
= kPendingDecode
;
316 DecodePendingBuffer();
320 void DecryptingVideoDecoder::DoReset() {
321 DCHECK(init_cb_
.is_null());
322 DCHECK(decode_cb_
.is_null());
324 base::ResetAndReturn(&reset_cb_
).Run();