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_demuxer_stream.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 "media/base/audio_decoder_config.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/demuxer_stream.h"
17 #include "media/base/pipeline.h"
18 #include "media/base/video_decoder_config.h"
22 static bool IsStreamValidAndEncrypted(DemuxerStream
* stream
) {
23 return ((stream
->type() == DemuxerStream::AUDIO
&&
24 stream
->audio_decoder_config().IsValidConfig() &&
25 stream
->audio_decoder_config().is_encrypted()) ||
26 (stream
->type() == DemuxerStream::VIDEO
&&
27 stream
->video_decoder_config().IsValidConfig() &&
28 stream
->video_decoder_config().is_encrypted()));
31 DecryptingDemuxerStream::DecryptingDemuxerStream(
32 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
33 const SetDecryptorReadyCB
& set_decryptor_ready_cb
)
34 : task_runner_(task_runner
),
35 state_(kUninitialized
),
36 demuxer_stream_(NULL
),
37 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
39 key_added_while_decrypt_pending_(false),
40 weak_factory_(this) {}
42 void DecryptingDemuxerStream::Initialize(DemuxerStream
* stream
,
43 const PipelineStatusCB
& status_cb
) {
44 DVLOG(2) << __FUNCTION__
;
45 DCHECK(task_runner_
->BelongsToCurrentThread());
46 DCHECK_EQ(state_
, kUninitialized
) << state_
;
48 DCHECK(!demuxer_stream_
);
49 weak_this_
= weak_factory_
.GetWeakPtr();
50 demuxer_stream_
= stream
;
51 init_cb_
= BindToCurrentLoop(status_cb
);
53 InitializeDecoderConfig();
55 state_
= kDecryptorRequested
;
56 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
57 base::Bind(&DecryptingDemuxerStream::SetDecryptor
, weak_this_
)));
60 void DecryptingDemuxerStream::Read(const ReadCB
& read_cb
) {
61 DVLOG(3) << __FUNCTION__
;
62 DCHECK(task_runner_
->BelongsToCurrentThread());
63 DCHECK_EQ(state_
, kIdle
) << state_
;
64 DCHECK(!read_cb
.is_null());
65 CHECK(read_cb_
.is_null()) << "Overlapping reads are not supported.";
67 read_cb_
= BindToCurrentLoop(read_cb
);
68 state_
= kPendingDemuxerRead
;
69 demuxer_stream_
->Read(
70 base::Bind(&DecryptingDemuxerStream::DecryptBuffer
, weak_this_
));
73 void DecryptingDemuxerStream::Reset(const base::Closure
& closure
) {
74 DVLOG(2) << __FUNCTION__
<< " - state: " << state_
;
75 DCHECK(task_runner_
->BelongsToCurrentThread());
76 DCHECK(state_
!= kUninitialized
) << state_
;
77 DCHECK(reset_cb_
.is_null());
79 reset_cb_
= BindToCurrentLoop(closure
);
81 // TODO(xhwang): This should not happen. Remove it, DCHECK against the
82 // condition and clean up related tests.
83 if (state_
== kDecryptorRequested
) {
84 DCHECK(!init_cb_
.is_null());
85 set_decryptor_ready_cb_
.Run(DecryptorReadyCB());
86 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
91 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
93 // Reset() cannot complete if the read callback is still pending.
94 // Defer the resetting process in this case. The |reset_cb_| will be fired
95 // after the read callback is fired - see DoDecryptBuffer() and
97 if (state_
== kPendingDemuxerRead
|| state_
== kPendingDecrypt
) {
98 DCHECK(!read_cb_
.is_null());
102 if (state_
== kWaitingForKey
) {
103 DCHECK(!read_cb_
.is_null());
104 pending_buffer_to_decrypt_
= NULL
;
105 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
108 DCHECK(read_cb_
.is_null());
112 AudioDecoderConfig
DecryptingDemuxerStream::audio_decoder_config() {
113 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
114 CHECK_EQ(demuxer_stream_
->type(), AUDIO
);
115 return audio_config_
;
118 VideoDecoderConfig
DecryptingDemuxerStream::video_decoder_config() {
119 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
120 CHECK_EQ(demuxer_stream_
->type(), VIDEO
);
121 return video_config_
;
124 DemuxerStream::Type
DecryptingDemuxerStream::type() const {
125 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
126 return demuxer_stream_
->type();
129 DemuxerStream::Liveness
DecryptingDemuxerStream::liveness() const {
130 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
131 return demuxer_stream_
->liveness();
134 void DecryptingDemuxerStream::EnableBitstreamConverter() {
135 demuxer_stream_
->EnableBitstreamConverter();
138 bool DecryptingDemuxerStream::SupportsConfigChanges() {
139 return demuxer_stream_
->SupportsConfigChanges();
142 VideoRotation
DecryptingDemuxerStream::video_rotation() {
143 return VIDEO_ROTATION_0
;
146 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
147 DVLOG(2) << __FUNCTION__
<< " : state_ = " << state_
;
148 DCHECK(task_runner_
->BelongsToCurrentThread());
150 if (state_
== kUninitialized
)
154 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
157 if (!set_decryptor_ready_cb_
.is_null())
158 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
159 if (!init_cb_
.is_null())
160 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
161 if (!read_cb_
.is_null())
162 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
163 if (!reset_cb_
.is_null())
164 base::ResetAndReturn(&reset_cb_
).Run();
165 pending_buffer_to_decrypt_
= NULL
;
168 void DecryptingDemuxerStream::SetDecryptor(
169 Decryptor
* decryptor
,
170 const DecryptorAttachedCB
& decryptor_attached_cb
) {
171 DVLOG(2) << __FUNCTION__
;
172 DCHECK(task_runner_
->BelongsToCurrentThread());
173 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
174 DCHECK(!init_cb_
.is_null());
175 DCHECK(!set_decryptor_ready_cb_
.is_null());
177 set_decryptor_ready_cb_
.Reset();
180 state_
= kUninitialized
;
181 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
182 decryptor_attached_cb
.Run(false);
186 decryptor_
= decryptor
;
188 decryptor_
->RegisterNewKeyCB(
189 GetDecryptorStreamType(),
191 base::Bind(&DecryptingDemuxerStream::OnKeyAdded
, weak_this_
)));
194 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
195 decryptor_attached_cb
.Run(true);
198 void DecryptingDemuxerStream::DecryptBuffer(
199 DemuxerStream::Status status
,
200 const scoped_refptr
<DecoderBuffer
>& buffer
) {
201 DVLOG(3) << __FUNCTION__
;
202 DCHECK(task_runner_
->BelongsToCurrentThread());
203 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
204 DCHECK(!read_cb_
.is_null());
205 DCHECK_EQ(buffer
.get() != NULL
, status
== kOk
) << status
;
207 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to
208 // the caller so that the downstream decoder can be properly reinitialized.
209 if (status
== kConfigChanged
) {
210 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
211 DCHECK_EQ(demuxer_stream_
->type() == AUDIO
, audio_config_
.IsValidConfig());
212 DCHECK_EQ(demuxer_stream_
->type() == VIDEO
, video_config_
.IsValidConfig());
214 // Update the decoder config, which the decoder will use when it is notified
215 // of kConfigChanged.
216 InitializeDecoderConfig();
218 base::ResetAndReturn(&read_cb_
).Run(kConfigChanged
, NULL
);
219 if (!reset_cb_
.is_null())
224 if (!reset_cb_
.is_null()) {
225 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
230 if (status
== kAborted
) {
231 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
233 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
237 if (buffer
->end_of_stream()) {
238 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
240 base::ResetAndReturn(&read_cb_
).Run(status
, buffer
);
244 DCHECK(buffer
->decrypt_config());
245 // An empty iv string signals that the frame is unencrypted.
246 if (buffer
->decrypt_config()->iv().empty()) {
247 DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
248 scoped_refptr
<DecoderBuffer
> decrypted
= DecoderBuffer::CopyFrom(
249 buffer
->data(), buffer
->data_size());
250 decrypted
->set_timestamp(buffer
->timestamp());
251 decrypted
->set_duration(buffer
->duration());
252 if (buffer
->is_key_frame())
253 decrypted
->set_is_key_frame(true);
256 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted
);
260 pending_buffer_to_decrypt_
= buffer
;
261 state_
= kPendingDecrypt
;
262 DecryptPendingBuffer();
265 void DecryptingDemuxerStream::DecryptPendingBuffer() {
266 DCHECK(task_runner_
->BelongsToCurrentThread());
267 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
269 GetDecryptorStreamType(),
270 pending_buffer_to_decrypt_
,
272 base::Bind(&DecryptingDemuxerStream::DeliverBuffer
, weak_this_
)));
275 void DecryptingDemuxerStream::DeliverBuffer(
276 Decryptor::Status status
,
277 const scoped_refptr
<DecoderBuffer
>& decrypted_buffer
) {
278 DVLOG(3) << __FUNCTION__
<< " - status: " << status
;
279 DCHECK(task_runner_
->BelongsToCurrentThread());
280 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
281 DCHECK_NE(status
, Decryptor::kNeedMoreData
);
282 DCHECK(!read_cb_
.is_null());
283 DCHECK(pending_buffer_to_decrypt_
.get());
285 bool need_to_try_again_if_nokey
= key_added_while_decrypt_pending_
;
286 key_added_while_decrypt_pending_
= false;
288 if (!reset_cb_
.is_null()) {
289 pending_buffer_to_decrypt_
= NULL
;
290 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
295 DCHECK_EQ(status
== Decryptor::kSuccess
, decrypted_buffer
.get() != NULL
);
297 if (status
== Decryptor::kError
) {
298 DVLOG(2) << "DoDeliverBuffer() - kError";
299 pending_buffer_to_decrypt_
= NULL
;
301 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
305 if (status
== Decryptor::kNoKey
) {
306 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
307 if (need_to_try_again_if_nokey
) {
308 // The |state_| is still kPendingDecrypt.
309 DecryptPendingBuffer();
313 state_
= kWaitingForKey
;
317 DCHECK_EQ(status
, Decryptor::kSuccess
);
319 // Copy the key frame flag from the encrypted to decrypted buffer, assuming
320 // that the decryptor initialized the flag to false.
321 if (pending_buffer_to_decrypt_
->is_key_frame())
322 decrypted_buffer
->set_is_key_frame(true);
324 pending_buffer_to_decrypt_
= NULL
;
326 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted_buffer
);
329 void DecryptingDemuxerStream::OnKeyAdded() {
330 DCHECK(task_runner_
->BelongsToCurrentThread());
332 if (state_
== kPendingDecrypt
) {
333 key_added_while_decrypt_pending_
= true;
337 if (state_
== kWaitingForKey
) {
338 state_
= kPendingDecrypt
;
339 DecryptPendingBuffer();
343 void DecryptingDemuxerStream::DoReset() {
344 DCHECK(state_
!= kUninitialized
);
345 DCHECK(init_cb_
.is_null());
346 DCHECK(read_cb_
.is_null());
348 if (state_
== kDecryptorRequested
)
349 state_
= kUninitialized
;
353 base::ResetAndReturn(&reset_cb_
).Run();
356 Decryptor::StreamType
DecryptingDemuxerStream::GetDecryptorStreamType() const {
357 if (demuxer_stream_
->type() == AUDIO
)
358 return Decryptor::kAudio
;
360 DCHECK_EQ(demuxer_stream_
->type(), VIDEO
);
361 return Decryptor::kVideo
;
364 void DecryptingDemuxerStream::InitializeDecoderConfig() {
365 // The decoder selector or upstream demuxer make sure the stream is valid and
366 // potentially encrypted.
367 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_
));
369 switch (demuxer_stream_
->type()) {
371 AudioDecoderConfig input_audio_config
=
372 demuxer_stream_
->audio_decoder_config();
373 audio_config_
.Initialize(input_audio_config
.codec(),
374 input_audio_config
.sample_format(),
375 input_audio_config
.channel_layout(),
376 input_audio_config
.samples_per_second(),
377 input_audio_config
.extra_data(),
378 input_audio_config
.extra_data_size(),
379 false, // Output audio is not encrypted.
381 input_audio_config
.seek_preroll(),
382 input_audio_config
.codec_delay());
387 VideoDecoderConfig input_video_config
=
388 demuxer_stream_
->video_decoder_config();
389 video_config_
.Initialize(input_video_config
.codec(),
390 input_video_config
.profile(),
391 input_video_config
.format(),
392 input_video_config
.coded_size(),
393 input_video_config
.visible_rect(),
394 input_video_config
.natural_size(),
395 input_video_config
.extra_data(),
396 input_video_config
.extra_data_size(),
397 false, // Output video is not encrypted.