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 std::string
DecryptingVideoDecoder::GetDisplayName() const {
34 return "DecryptingVideoDecoder";
37 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
39 const PipelineStatusCB
& status_cb
,
40 const OutputCB
& output_cb
) {
41 DVLOG(2) << "Initialize()";
42 DCHECK(task_runner_
->BelongsToCurrentThread());
43 DCHECK(state_
== kUninitialized
||
45 state_
== kDecodeFinished
) << state_
;
46 DCHECK(decode_cb_
.is_null());
47 DCHECK(reset_cb_
.is_null());
48 DCHECK(config
.IsValidConfig());
49 DCHECK(config
.is_encrypted());
51 init_cb_
= BindToCurrentLoop(status_cb
);
52 output_cb_
= BindToCurrentLoop(output_cb
);
53 weak_this_
= weak_factory_
.GetWeakPtr();
56 if (state_
== kUninitialized
) {
57 state_
= kDecryptorRequested
;
58 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(base::Bind(
59 &DecryptingVideoDecoder::SetDecryptor
, weak_this_
)));
64 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
65 state_
= kPendingDecoderInit
;
66 decryptor_
->InitializeVideoDecoder(config
, BindToCurrentLoop(base::Bind(
67 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
70 void DecryptingVideoDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
71 const DecodeCB
& decode_cb
) {
72 DVLOG(3) << "Decode()";
73 DCHECK(task_runner_
->BelongsToCurrentThread());
74 DCHECK(state_
== kIdle
||
75 state_
== kDecodeFinished
||
76 state_
== kError
) << state_
;
77 DCHECK(!decode_cb
.is_null());
78 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
80 decode_cb_
= BindToCurrentLoop(decode_cb
);
82 if (state_
== kError
) {
83 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
87 // Return empty frames if decoding has finished.
88 if (state_
== kDecodeFinished
) {
89 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
93 pending_buffer_to_decode_
= buffer
;
94 state_
= kPendingDecode
;
95 DecodePendingBuffer();
98 void DecryptingVideoDecoder::Reset(const base::Closure
& closure
) {
99 DVLOG(2) << "Reset() - state: " << state_
;
100 DCHECK(task_runner_
->BelongsToCurrentThread());
101 DCHECK(state_
== kIdle
||
102 state_
== kPendingDecode
||
103 state_
== kWaitingForKey
||
104 state_
== kDecodeFinished
||
105 state_
== kError
) << state_
;
106 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
107 DCHECK(reset_cb_
.is_null());
109 reset_cb_
= BindToCurrentLoop(closure
);
111 decryptor_
->ResetDecoder(Decryptor::kVideo
);
113 // Reset() cannot complete if the decode callback is still pending.
114 // Defer the resetting process in this case. The |reset_cb_| will be fired
115 // after the decode callback is fired - see DecryptAndDecodeBuffer() and
117 if (state_
== kPendingDecode
) {
118 DCHECK(!decode_cb_
.is_null());
122 if (state_
== kWaitingForKey
) {
123 DCHECK(!decode_cb_
.is_null());
124 pending_buffer_to_decode_
= NULL
;
125 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
128 DCHECK(decode_cb_
.is_null());
132 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
133 DCHECK(task_runner_
->BelongsToCurrentThread());
135 if (state_
== kUninitialized
)
139 decryptor_
->DeinitializeDecoder(Decryptor::kVideo
);
142 if (!set_decryptor_ready_cb_
.is_null())
143 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
144 pending_buffer_to_decode_
= NULL
;
145 if (!init_cb_
.is_null())
146 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
147 if (!decode_cb_
.is_null())
148 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
149 if (!reset_cb_
.is_null())
150 base::ResetAndReturn(&reset_cb_
).Run();
153 void DecryptingVideoDecoder::SetDecryptor(
154 Decryptor
* decryptor
,
155 const DecryptorAttachedCB
& decryptor_attached_cb
) {
156 DVLOG(2) << "SetDecryptor()";
157 DCHECK(task_runner_
->BelongsToCurrentThread());
158 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
159 DCHECK(!init_cb_
.is_null());
160 DCHECK(!set_decryptor_ready_cb_
.is_null());
161 set_decryptor_ready_cb_
.Reset();
164 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
166 decryptor_attached_cb
.Run(false);
170 decryptor_
= decryptor
;
172 state_
= kPendingDecoderInit
;
173 decryptor_
->InitializeVideoDecoder(
175 BindToCurrentLoop(base::Bind(
176 &DecryptingVideoDecoder::FinishInitialization
, weak_this_
)));
177 decryptor_attached_cb
.Run(true);
180 void DecryptingVideoDecoder::FinishInitialization(bool success
) {
181 DVLOG(2) << "FinishInitialization()";
182 DCHECK(task_runner_
->BelongsToCurrentThread());
183 DCHECK_EQ(state_
, kPendingDecoderInit
) << state_
;
184 DCHECK(!init_cb_
.is_null());
185 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
186 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
189 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
195 decryptor_
->RegisterNewKeyCB(
198 base::Bind(&DecryptingVideoDecoder::OnKeyAdded
, weak_this_
)));
202 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
206 void DecryptingVideoDecoder::DecodePendingBuffer() {
207 DCHECK(task_runner_
->BelongsToCurrentThread());
208 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
209 TRACE_EVENT_ASYNC_BEGIN0(
210 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_
);
213 if (!pending_buffer_to_decode_
->end_of_stream()) {
214 buffer_size
= pending_buffer_to_decode_
->data_size();
217 decryptor_
->DecryptAndDecodeVideo(
218 pending_buffer_to_decode_
, BindToCurrentLoop(base::Bind(
219 &DecryptingVideoDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
222 void DecryptingVideoDecoder::DeliverFrame(
224 Decryptor::Status status
,
225 const scoped_refptr
<VideoFrame
>& frame
) {
226 DVLOG(3) << "DeliverFrame() - status: " << status
;
227 DCHECK(task_runner_
->BelongsToCurrentThread());
228 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
229 DCHECK(!decode_cb_
.is_null());
230 DCHECK(pending_buffer_to_decode_
.get());
232 TRACE_EVENT_ASYNC_END2(
233 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_
,
234 "buffer_size", buffer_size
, "status", status
);
236 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
237 key_added_while_decode_pending_
= false;
239 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
240 pending_buffer_to_decode_
;
241 pending_buffer_to_decode_
= NULL
;
243 if (!reset_cb_
.is_null()) {
244 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
249 DCHECK_EQ(status
== Decryptor::kSuccess
, frame
.get() != NULL
);
251 if (status
== Decryptor::kError
) {
252 DVLOG(2) << "DeliverFrame() - kError";
254 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
258 if (status
== Decryptor::kNoKey
) {
259 DVLOG(2) << "DeliverFrame() - kNoKey";
260 // Set |pending_buffer_to_decode_| back as we need to try decoding the
261 // pending buffer again when new key is added to the decryptor.
262 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
264 if (need_to_try_again_if_nokey_is_returned
) {
265 // The |state_| is still kPendingDecode.
266 DecodePendingBuffer();
270 state_
= kWaitingForKey
;
274 if (status
== Decryptor::kNeedMoreData
) {
275 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
276 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
278 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
282 DCHECK_EQ(status
, Decryptor::kSuccess
);
283 // No frame returned with kSuccess should be end-of-stream frame.
284 DCHECK(!frame
->end_of_stream());
285 output_cb_
.Run(frame
);
287 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
288 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
290 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
291 DecodePendingBuffer();
296 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
299 void DecryptingVideoDecoder::OnKeyAdded() {
300 DVLOG(2) << "OnKeyAdded()";
301 DCHECK(task_runner_
->BelongsToCurrentThread());
303 if (state_
== kPendingDecode
) {
304 key_added_while_decode_pending_
= true;
308 if (state_
== kWaitingForKey
) {
309 state_
= kPendingDecode
;
310 DecodePendingBuffer();
314 void DecryptingVideoDecoder::DoReset() {
315 DCHECK(init_cb_
.is_null());
316 DCHECK(decode_cb_
.is_null());
318 base::ResetAndReturn(&reset_cb_
).Run();