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 : task_runner_(task_runner
),
28 state_(kUninitialized
),
29 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
31 key_added_while_decode_pending_(false),
33 weak_factory_(this) {}
35 std::string
DecryptingVideoDecoder::GetDisplayName() const {
39 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
41 const PipelineStatusCB
& status_cb
,
42 const OutputCB
& output_cb
) {
43 DVLOG(2) << "Initialize()";
44 DCHECK(task_runner_
->BelongsToCurrentThread());
45 DCHECK(state_
== kUninitialized
||
47 state_
== kDecodeFinished
) << state_
;
48 DCHECK(decode_cb_
.is_null());
49 DCHECK(reset_cb_
.is_null());
50 DCHECK(config
.IsValidConfig());
51 DCHECK(config
.is_encrypted());
53 init_cb_
= BindToCurrentLoop(status_cb
);
54 output_cb_
= BindToCurrentLoop(output_cb
);
55 weak_this_
= weak_factory_
.GetWeakPtr();
58 if (state_
== kUninitialized
) {
59 state_
= kDecryptorRequested
;
60 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(base::Bind(
61 &DecryptingVideoDecoder::SetDecryptor
, weak_this_
)));
66 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
67 state_
= kPendingDecoderInit
;
68 decryptor_
->InitializeVideoDecoder(config
, BindToCurrentLoop(base::Bind(
69 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
72 void DecryptingVideoDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
73 const DecodeCB
& decode_cb
) {
74 DVLOG(3) << "Decode()";
75 DCHECK(task_runner_
->BelongsToCurrentThread());
76 DCHECK(state_
== kIdle
||
77 state_
== kDecodeFinished
||
78 state_
== kError
) << state_
;
79 DCHECK(!decode_cb
.is_null());
80 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
82 decode_cb_
= BindToCurrentLoop(decode_cb
);
84 if (state_
== kError
) {
85 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
89 // Return empty frames if decoding has finished.
90 if (state_
== kDecodeFinished
) {
91 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
95 pending_buffer_to_decode_
= buffer
;
96 state_
= kPendingDecode
;
97 DecodePendingBuffer();
100 void DecryptingVideoDecoder::Reset(const base::Closure
& closure
) {
101 DVLOG(2) << "Reset() - state: " << state_
;
102 DCHECK(task_runner_
->BelongsToCurrentThread());
103 DCHECK(state_
== kIdle
||
104 state_
== kPendingDecode
||
105 state_
== kWaitingForKey
||
106 state_
== kDecodeFinished
||
107 state_
== kError
) << state_
;
108 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
109 DCHECK(reset_cb_
.is_null());
111 reset_cb_
= BindToCurrentLoop(closure
);
113 decryptor_
->ResetDecoder(Decryptor::kVideo
);
115 // Reset() cannot complete if the decode callback is still pending.
116 // Defer the resetting process in this case. The |reset_cb_| will be fired
117 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
119 if (state_
== kPendingDecode
) {
120 DCHECK(!decode_cb_
.is_null());
124 if (state_
== kWaitingForKey
) {
125 DCHECK(!decode_cb_
.is_null());
126 pending_buffer_to_decode_
= NULL
;
127 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
130 DCHECK(decode_cb_
.is_null());
134 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
135 DCHECK(task_runner_
->BelongsToCurrentThread());
137 if (state_
== kUninitialized
)
141 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
144 if (!set_decryptor_ready_cb_
.is_null())
145 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
146 pending_buffer_to_decode_
= NULL
;
147 if (!init_cb_
.is_null())
148 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
149 if (!decode_cb_
.is_null())
150 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
151 if (!reset_cb_
.is_null())
152 base::ResetAndReturn(&reset_cb_
).Run();
155 void DecryptingVideoDecoder::SetDecryptor(
156 Decryptor
* decryptor
,
157 const DecryptorAttachedCB
& decryptor_attached_cb
) {
158 DVLOG(2) << "SetDecryptor()";
159 DCHECK(task_runner_
->BelongsToCurrentThread());
160 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
161 DCHECK(!init_cb_
.is_null());
162 DCHECK(!set_decryptor_ready_cb_
.is_null());
163 set_decryptor_ready_cb_
.Reset();
166 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
168 decryptor_attached_cb
.Run(false);
172 decryptor_
= decryptor
;
174 state_
= kPendingDecoderInit
;
175 decryptor_
->InitializeVideoDecoder(
177 BindToCurrentLoop(base::Bind(
178 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
179 decryptor_attached_cb
.Run(true);
182 void DecryptingVideoDecoder::FinishInitialization(bool success
) {
183 DVLOG(2) << "FinishInitialization()";
184 DCHECK(task_runner_
->BelongsToCurrentThread());
185 DCHECK_EQ(state_
, kPendingDecoderInit
) << state_
;
186 DCHECK(!init_cb_
.is_null());
187 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
188 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
191 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
197 decryptor_
->RegisterNewKeyCB(
200 base::Bind(&DecryptingVideoDecoder::OnKeyAdded
, weak_this_
)));
204 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
208 void DecryptingVideoDecoder::DecodePendingBuffer() {
209 DCHECK(task_runner_
->BelongsToCurrentThread());
210 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
211 TRACE_EVENT_ASYNC_BEGIN0(
212 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_
);
215 if (!pending_buffer_to_decode_
->end_of_stream()) {
216 buffer_size
= pending_buffer_to_decode_
->data_size();
219 decryptor_
->DecryptAndDecodeVideo(
220 pending_buffer_to_decode_
, BindToCurrentLoop(base::Bind(
221 &DecryptingVideoDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
224 void DecryptingVideoDecoder::DeliverFrame(
226 Decryptor::Status status
,
227 const scoped_refptr
<VideoFrame
>& frame
) {
228 DVLOG(3) << "DeliverFrame() - status: " << status
;
229 DCHECK(task_runner_
->BelongsToCurrentThread());
230 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
231 DCHECK(!decode_cb_
.is_null());
232 DCHECK(pending_buffer_to_decode_
.get());
234 TRACE_EVENT_ASYNC_END2(
235 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_
,
236 "buffer_size", buffer_size
, "status", status
);
238 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
239 key_added_while_decode_pending_
= false;
241 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
242 pending_buffer_to_decode_
;
243 pending_buffer_to_decode_
= NULL
;
245 if (!reset_cb_
.is_null()) {
246 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
251 DCHECK_EQ(status
== Decryptor::kSuccess
, frame
.get() != NULL
);
253 if (status
== Decryptor::kError
) {
254 DVLOG(2) << "DeliverFrame() - kError";
256 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
260 if (status
== Decryptor::kNoKey
) {
261 DVLOG(2) << "DeliverFrame() - kNoKey";
262 // Set |pending_buffer_to_decode_| back as we need to try decoding the
263 // pending buffer again when new key is added to the decryptor.
264 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
266 if (need_to_try_again_if_nokey_is_returned
) {
267 // The |state_| is still kPendingDecode.
268 DecodePendingBuffer();
272 state_
= kWaitingForKey
;
276 if (status
== Decryptor::kNeedMoreData
) {
277 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
278 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
280 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
284 DCHECK_EQ(status
, Decryptor::kSuccess
);
285 // No frame returned with kSuccess should be end-of-stream frame.
286 DCHECK(!frame
->end_of_stream());
287 output_cb_
.Run(frame
);
289 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
290 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
292 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
293 DecodePendingBuffer();
298 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
301 void DecryptingVideoDecoder::OnKeyAdded() {
302 DVLOG(2) << "OnKeyAdded()";
303 DCHECK(task_runner_
->BelongsToCurrentThread());
305 if (state_
== kPendingDecode
) {
306 key_added_while_decode_pending_
= true;
310 if (state_
== kWaitingForKey
) {
311 state_
= kPendingDecode
;
312 DecodePendingBuffer();
316 void DecryptingVideoDecoder::DoReset() {
317 DCHECK(init_cb_
.is_null());
318 DCHECK(decode_cb_
.is_null());
320 base::ResetAndReturn(&reset_cb_
).Run();