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/bind_to_current_loop.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/media_log.h"
15 #include "media/base/pipeline.h"
19 static bool IsStreamValidAndEncrypted(DemuxerStream
* stream
) {
20 return ((stream
->type() == DemuxerStream::AUDIO
&&
21 stream
->audio_decoder_config().IsValidConfig() &&
22 stream
->audio_decoder_config().is_encrypted()) ||
23 (stream
->type() == DemuxerStream::VIDEO
&&
24 stream
->video_decoder_config().IsValidConfig() &&
25 stream
->video_decoder_config().is_encrypted()));
28 DecryptingDemuxerStream::DecryptingDemuxerStream(
29 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
30 const scoped_refptr
<MediaLog
>& media_log
,
31 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
32 const base::Closure
& waiting_for_decryption_key_cb
)
33 : task_runner_(task_runner
),
34 media_log_(media_log
),
35 state_(kUninitialized
),
36 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb
),
37 demuxer_stream_(NULL
),
38 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
40 key_added_while_decrypt_pending_(false),
44 std::string
DecryptingDemuxerStream::GetDisplayName() const {
45 return "DecryptingDemuxerStream";
48 void DecryptingDemuxerStream::Initialize(DemuxerStream
* stream
,
49 const PipelineStatusCB
& status_cb
) {
50 DVLOG(2) << __FUNCTION__
;
51 DCHECK(task_runner_
->BelongsToCurrentThread());
52 DCHECK_EQ(state_
, kUninitialized
) << state_
;
54 DCHECK(!demuxer_stream_
);
55 weak_this_
= weak_factory_
.GetWeakPtr();
56 demuxer_stream_
= stream
;
57 init_cb_
= BindToCurrentLoop(status_cb
);
59 InitializeDecoderConfig();
61 state_
= kDecryptorRequested
;
62 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
63 base::Bind(&DecryptingDemuxerStream::SetDecryptor
, weak_this_
)));
66 void DecryptingDemuxerStream::Read(const ReadCB
& read_cb
) {
67 DVLOG(3) << __FUNCTION__
;
68 DCHECK(task_runner_
->BelongsToCurrentThread());
69 DCHECK_EQ(state_
, kIdle
) << state_
;
70 DCHECK(!read_cb
.is_null());
71 CHECK(read_cb_
.is_null()) << "Overlapping reads are not supported.";
73 read_cb_
= BindToCurrentLoop(read_cb
);
74 state_
= kPendingDemuxerRead
;
75 demuxer_stream_
->Read(
76 base::Bind(&DecryptingDemuxerStream::DecryptBuffer
, weak_this_
));
79 void DecryptingDemuxerStream::Reset(const base::Closure
& closure
) {
80 DVLOG(2) << __FUNCTION__
<< " - state: " << state_
;
81 DCHECK(task_runner_
->BelongsToCurrentThread());
82 DCHECK(state_
!= kUninitialized
) << state_
;
83 DCHECK(reset_cb_
.is_null());
85 reset_cb_
= BindToCurrentLoop(closure
);
87 // TODO(xhwang): This should not happen. Remove it, DCHECK against the
88 // condition and clean up related tests.
89 if (state_
== kDecryptorRequested
) {
90 DCHECK(!init_cb_
.is_null());
91 set_decryptor_ready_cb_
.Run(DecryptorReadyCB());
92 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
97 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
99 // Reset() cannot complete if the read callback is still pending.
100 // Defer the resetting process in this case. The |reset_cb_| will be fired
101 // after the read callback is fired - see DoDecryptBuffer() and
102 // DoDeliverBuffer().
103 if (state_
== kPendingDemuxerRead
|| state_
== kPendingDecrypt
) {
104 DCHECK(!read_cb_
.is_null());
108 if (state_
== kWaitingForKey
) {
109 DCHECK(!read_cb_
.is_null());
110 pending_buffer_to_decrypt_
= NULL
;
111 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
114 DCHECK(read_cb_
.is_null());
118 AudioDecoderConfig
DecryptingDemuxerStream::audio_decoder_config() {
119 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
120 CHECK_EQ(demuxer_stream_
->type(), AUDIO
);
121 return audio_config_
;
124 VideoDecoderConfig
DecryptingDemuxerStream::video_decoder_config() {
125 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
126 CHECK_EQ(demuxer_stream_
->type(), VIDEO
);
127 return video_config_
;
130 DemuxerStream::Type
DecryptingDemuxerStream::type() const {
131 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
132 return demuxer_stream_
->type();
135 DemuxerStream::Liveness
DecryptingDemuxerStream::liveness() const {
136 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
137 return demuxer_stream_
->liveness();
140 void DecryptingDemuxerStream::EnableBitstreamConverter() {
141 demuxer_stream_
->EnableBitstreamConverter();
144 bool DecryptingDemuxerStream::SupportsConfigChanges() {
145 return demuxer_stream_
->SupportsConfigChanges();
148 VideoRotation
DecryptingDemuxerStream::video_rotation() {
149 return demuxer_stream_
->video_rotation();
152 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
153 DVLOG(2) << __FUNCTION__
<< " : state_ = " << state_
;
154 DCHECK(task_runner_
->BelongsToCurrentThread());
156 if (state_
== kUninitialized
)
160 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
163 if (!set_decryptor_ready_cb_
.is_null())
164 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
165 if (!init_cb_
.is_null())
166 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
167 if (!read_cb_
.is_null())
168 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
169 if (!reset_cb_
.is_null())
170 base::ResetAndReturn(&reset_cb_
).Run();
171 pending_buffer_to_decrypt_
= NULL
;
174 void DecryptingDemuxerStream::SetDecryptor(
175 Decryptor
* decryptor
,
176 const DecryptorAttachedCB
& decryptor_attached_cb
) {
177 DVLOG(2) << __FUNCTION__
;
178 DCHECK(task_runner_
->BelongsToCurrentThread());
179 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
180 DCHECK(!init_cb_
.is_null());
181 DCHECK(!set_decryptor_ready_cb_
.is_null());
183 set_decryptor_ready_cb_
.Reset();
186 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName() << ": decryptor not set";
187 state_
= kUninitialized
;
188 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
189 decryptor_attached_cb
.Run(false);
193 decryptor_
= decryptor
;
195 decryptor_
->RegisterNewKeyCB(
196 GetDecryptorStreamType(),
198 base::Bind(&DecryptingDemuxerStream::OnKeyAdded
, weak_this_
)));
201 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
202 decryptor_attached_cb
.Run(true);
205 void DecryptingDemuxerStream::DecryptBuffer(
206 DemuxerStream::Status status
,
207 const scoped_refptr
<DecoderBuffer
>& buffer
) {
208 DVLOG(3) << __FUNCTION__
;
209 DCHECK(task_runner_
->BelongsToCurrentThread());
210 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
211 DCHECK(!read_cb_
.is_null());
212 DCHECK_EQ(buffer
.get() != NULL
, status
== kOk
) << status
;
214 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to
215 // the caller so that the downstream decoder can be properly reinitialized.
216 if (status
== kConfigChanged
) {
217 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
218 DCHECK_EQ(demuxer_stream_
->type() == AUDIO
, audio_config_
.IsValidConfig());
219 DCHECK_EQ(demuxer_stream_
->type() == VIDEO
, video_config_
.IsValidConfig());
221 // Update the decoder config, which the decoder will use when it is notified
222 // of kConfigChanged.
223 InitializeDecoderConfig();
225 base::ResetAndReturn(&read_cb_
).Run(kConfigChanged
, NULL
);
226 if (!reset_cb_
.is_null())
231 if (!reset_cb_
.is_null()) {
232 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
237 if (status
== kAborted
) {
238 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
240 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
244 if (buffer
->end_of_stream()) {
245 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
247 base::ResetAndReturn(&read_cb_
).Run(status
, buffer
);
251 DCHECK(buffer
->decrypt_config());
252 // An empty iv string signals that the frame is unencrypted.
253 if (buffer
->decrypt_config()->iv().empty()) {
254 DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
255 scoped_refptr
<DecoderBuffer
> decrypted
= DecoderBuffer::CopyFrom(
256 buffer
->data(), buffer
->data_size());
257 decrypted
->set_timestamp(buffer
->timestamp());
258 decrypted
->set_duration(buffer
->duration());
259 if (buffer
->is_key_frame())
260 decrypted
->set_is_key_frame(true);
263 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted
);
267 pending_buffer_to_decrypt_
= buffer
;
268 state_
= kPendingDecrypt
;
269 DecryptPendingBuffer();
272 void DecryptingDemuxerStream::DecryptPendingBuffer() {
273 DCHECK(task_runner_
->BelongsToCurrentThread());
274 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
276 GetDecryptorStreamType(),
277 pending_buffer_to_decrypt_
,
279 base::Bind(&DecryptingDemuxerStream::DeliverBuffer
, weak_this_
)));
282 void DecryptingDemuxerStream::DeliverBuffer(
283 Decryptor::Status status
,
284 const scoped_refptr
<DecoderBuffer
>& decrypted_buffer
) {
285 DVLOG(3) << __FUNCTION__
<< " - status: " << status
;
286 DCHECK(task_runner_
->BelongsToCurrentThread());
287 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
288 DCHECK_NE(status
, Decryptor::kNeedMoreData
);
289 DCHECK(!read_cb_
.is_null());
290 DCHECK(pending_buffer_to_decrypt_
.get());
292 bool need_to_try_again_if_nokey
= key_added_while_decrypt_pending_
;
293 key_added_while_decrypt_pending_
= false;
295 if (!reset_cb_
.is_null()) {
296 pending_buffer_to_decrypt_
= NULL
;
297 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
302 DCHECK_EQ(status
== Decryptor::kSuccess
, decrypted_buffer
.get() != NULL
);
304 if (status
== Decryptor::kError
) {
305 DVLOG(2) << "DoDeliverBuffer() - kError";
306 MEDIA_LOG(ERROR
, media_log_
) << GetDisplayName() << ": decrypt error";
307 pending_buffer_to_decrypt_
= NULL
;
309 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
313 if (status
== Decryptor::kNoKey
) {
314 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
315 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName() << ": no key";
316 if (need_to_try_again_if_nokey
) {
317 // The |state_| is still kPendingDecrypt.
318 DecryptPendingBuffer();
322 state_
= kWaitingForKey
;
323 waiting_for_decryption_key_cb_
.Run();
327 DCHECK_EQ(status
, Decryptor::kSuccess
);
329 // Copy the key frame flag from the encrypted to decrypted buffer, assuming
330 // that the decryptor initialized the flag to false.
331 if (pending_buffer_to_decrypt_
->is_key_frame())
332 decrypted_buffer
->set_is_key_frame(true);
334 pending_buffer_to_decrypt_
= NULL
;
336 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted_buffer
);
339 void DecryptingDemuxerStream::OnKeyAdded() {
340 DCHECK(task_runner_
->BelongsToCurrentThread());
342 if (state_
== kPendingDecrypt
) {
343 key_added_while_decrypt_pending_
= true;
347 if (state_
== kWaitingForKey
) {
348 state_
= kPendingDecrypt
;
349 DecryptPendingBuffer();
353 void DecryptingDemuxerStream::DoReset() {
354 DCHECK(state_
!= kUninitialized
);
355 DCHECK(init_cb_
.is_null());
356 DCHECK(read_cb_
.is_null());
358 if (state_
== kDecryptorRequested
)
359 state_
= kUninitialized
;
363 base::ResetAndReturn(&reset_cb_
).Run();
366 Decryptor::StreamType
DecryptingDemuxerStream::GetDecryptorStreamType() const {
367 if (demuxer_stream_
->type() == AUDIO
)
368 return Decryptor::kAudio
;
370 DCHECK_EQ(demuxer_stream_
->type(), VIDEO
);
371 return Decryptor::kVideo
;
374 void DecryptingDemuxerStream::InitializeDecoderConfig() {
375 // The decoder selector or upstream demuxer make sure the stream is valid and
376 // potentially encrypted.
377 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_
));
379 switch (demuxer_stream_
->type()) {
381 AudioDecoderConfig input_audio_config
=
382 demuxer_stream_
->audio_decoder_config();
383 audio_config_
.Initialize(input_audio_config
.codec(),
384 input_audio_config
.sample_format(),
385 input_audio_config
.channel_layout(),
386 input_audio_config
.samples_per_second(),
387 input_audio_config
.extra_data(),
388 input_audio_config
.extra_data_size(),
389 false, // Output audio is not encrypted.
390 input_audio_config
.seek_preroll(),
391 input_audio_config
.codec_delay());
396 VideoDecoderConfig input_video_config
=
397 demuxer_stream_
->video_decoder_config();
398 video_config_
.Initialize(
399 input_video_config
.codec(), input_video_config
.profile(),
400 input_video_config
.format(), input_video_config
.color_space(),
401 input_video_config
.coded_size(), input_video_config
.visible_rect(),
402 input_video_config
.natural_size(), input_video_config
.extra_data(),
403 input_video_config
.extra_data_size(),
404 false); // Output video is not encrypted.