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 const base::Closure
& waiting_for_decryption_key_cb
)
35 : task_runner_(task_runner
),
36 state_(kUninitialized
),
37 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb
),
38 demuxer_stream_(NULL
),
39 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
41 key_added_while_decrypt_pending_(false),
45 void DecryptingDemuxerStream::Initialize(DemuxerStream
* stream
,
46 const PipelineStatusCB
& status_cb
) {
47 DVLOG(2) << __FUNCTION__
;
48 DCHECK(task_runner_
->BelongsToCurrentThread());
49 DCHECK_EQ(state_
, kUninitialized
) << state_
;
51 DCHECK(!demuxer_stream_
);
52 weak_this_
= weak_factory_
.GetWeakPtr();
53 demuxer_stream_
= stream
;
54 init_cb_
= BindToCurrentLoop(status_cb
);
56 InitializeDecoderConfig();
58 state_
= kDecryptorRequested
;
59 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
60 base::Bind(&DecryptingDemuxerStream::SetDecryptor
, weak_this_
)));
63 void DecryptingDemuxerStream::Read(const ReadCB
& read_cb
) {
64 DVLOG(3) << __FUNCTION__
;
65 DCHECK(task_runner_
->BelongsToCurrentThread());
66 DCHECK_EQ(state_
, kIdle
) << state_
;
67 DCHECK(!read_cb
.is_null());
68 CHECK(read_cb_
.is_null()) << "Overlapping reads are not supported.";
70 read_cb_
= BindToCurrentLoop(read_cb
);
71 state_
= kPendingDemuxerRead
;
72 demuxer_stream_
->Read(
73 base::Bind(&DecryptingDemuxerStream::DecryptBuffer
, weak_this_
));
76 void DecryptingDemuxerStream::Reset(const base::Closure
& closure
) {
77 DVLOG(2) << __FUNCTION__
<< " - state: " << state_
;
78 DCHECK(task_runner_
->BelongsToCurrentThread());
79 DCHECK(state_
!= kUninitialized
) << state_
;
80 DCHECK(reset_cb_
.is_null());
82 reset_cb_
= BindToCurrentLoop(closure
);
84 // TODO(xhwang): This should not happen. Remove it, DCHECK against the
85 // condition and clean up related tests.
86 if (state_
== kDecryptorRequested
) {
87 DCHECK(!init_cb_
.is_null());
88 set_decryptor_ready_cb_
.Run(DecryptorReadyCB());
89 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
94 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
96 // Reset() cannot complete if the read callback is still pending.
97 // Defer the resetting process in this case. The |reset_cb_| will be fired
98 // after the read callback is fired - see DoDecryptBuffer() and
100 if (state_
== kPendingDemuxerRead
|| state_
== kPendingDecrypt
) {
101 DCHECK(!read_cb_
.is_null());
105 if (state_
== kWaitingForKey
) {
106 DCHECK(!read_cb_
.is_null());
107 pending_buffer_to_decrypt_
= NULL
;
108 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
111 DCHECK(read_cb_
.is_null());
115 AudioDecoderConfig
DecryptingDemuxerStream::audio_decoder_config() {
116 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
117 CHECK_EQ(demuxer_stream_
->type(), AUDIO
);
118 return audio_config_
;
121 VideoDecoderConfig
DecryptingDemuxerStream::video_decoder_config() {
122 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
123 CHECK_EQ(demuxer_stream_
->type(), VIDEO
);
124 return video_config_
;
127 DemuxerStream::Type
DecryptingDemuxerStream::type() const {
128 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
129 return demuxer_stream_
->type();
132 DemuxerStream::Liveness
DecryptingDemuxerStream::liveness() const {
133 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
134 return demuxer_stream_
->liveness();
137 void DecryptingDemuxerStream::EnableBitstreamConverter() {
138 demuxer_stream_
->EnableBitstreamConverter();
141 bool DecryptingDemuxerStream::SupportsConfigChanges() {
142 return demuxer_stream_
->SupportsConfigChanges();
145 VideoRotation
DecryptingDemuxerStream::video_rotation() {
146 return VIDEO_ROTATION_0
;
149 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
150 DVLOG(2) << __FUNCTION__
<< " : state_ = " << state_
;
151 DCHECK(task_runner_
->BelongsToCurrentThread());
153 if (state_
== kUninitialized
)
157 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
160 if (!set_decryptor_ready_cb_
.is_null())
161 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
162 if (!init_cb_
.is_null())
163 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
164 if (!read_cb_
.is_null())
165 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
166 if (!reset_cb_
.is_null())
167 base::ResetAndReturn(&reset_cb_
).Run();
168 pending_buffer_to_decrypt_
= NULL
;
171 void DecryptingDemuxerStream::SetDecryptor(
172 Decryptor
* decryptor
,
173 const DecryptorAttachedCB
& decryptor_attached_cb
) {
174 DVLOG(2) << __FUNCTION__
;
175 DCHECK(task_runner_
->BelongsToCurrentThread());
176 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
177 DCHECK(!init_cb_
.is_null());
178 DCHECK(!set_decryptor_ready_cb_
.is_null());
180 set_decryptor_ready_cb_
.Reset();
183 state_
= kUninitialized
;
184 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
185 decryptor_attached_cb
.Run(false);
189 decryptor_
= decryptor
;
191 decryptor_
->RegisterNewKeyCB(
192 GetDecryptorStreamType(),
194 base::Bind(&DecryptingDemuxerStream::OnKeyAdded
, weak_this_
)));
197 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
198 decryptor_attached_cb
.Run(true);
201 void DecryptingDemuxerStream::DecryptBuffer(
202 DemuxerStream::Status status
,
203 const scoped_refptr
<DecoderBuffer
>& buffer
) {
204 DVLOG(3) << __FUNCTION__
;
205 DCHECK(task_runner_
->BelongsToCurrentThread());
206 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
207 DCHECK(!read_cb_
.is_null());
208 DCHECK_EQ(buffer
.get() != NULL
, status
== kOk
) << status
;
210 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to
211 // the caller so that the downstream decoder can be properly reinitialized.
212 if (status
== kConfigChanged
) {
213 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
214 DCHECK_EQ(demuxer_stream_
->type() == AUDIO
, audio_config_
.IsValidConfig());
215 DCHECK_EQ(demuxer_stream_
->type() == VIDEO
, video_config_
.IsValidConfig());
217 // Update the decoder config, which the decoder will use when it is notified
218 // of kConfigChanged.
219 InitializeDecoderConfig();
221 base::ResetAndReturn(&read_cb_
).Run(kConfigChanged
, NULL
);
222 if (!reset_cb_
.is_null())
227 if (!reset_cb_
.is_null()) {
228 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
233 if (status
== kAborted
) {
234 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
236 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
240 if (buffer
->end_of_stream()) {
241 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
243 base::ResetAndReturn(&read_cb_
).Run(status
, buffer
);
247 DCHECK(buffer
->decrypt_config());
248 // An empty iv string signals that the frame is unencrypted.
249 if (buffer
->decrypt_config()->iv().empty()) {
250 DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
251 scoped_refptr
<DecoderBuffer
> decrypted
= DecoderBuffer::CopyFrom(
252 buffer
->data(), buffer
->data_size());
253 decrypted
->set_timestamp(buffer
->timestamp());
254 decrypted
->set_duration(buffer
->duration());
255 if (buffer
->is_key_frame())
256 decrypted
->set_is_key_frame(true);
259 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted
);
263 pending_buffer_to_decrypt_
= buffer
;
264 state_
= kPendingDecrypt
;
265 DecryptPendingBuffer();
268 void DecryptingDemuxerStream::DecryptPendingBuffer() {
269 DCHECK(task_runner_
->BelongsToCurrentThread());
270 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
272 GetDecryptorStreamType(),
273 pending_buffer_to_decrypt_
,
275 base::Bind(&DecryptingDemuxerStream::DeliverBuffer
, weak_this_
)));
278 void DecryptingDemuxerStream::DeliverBuffer(
279 Decryptor::Status status
,
280 const scoped_refptr
<DecoderBuffer
>& decrypted_buffer
) {
281 DVLOG(3) << __FUNCTION__
<< " - status: " << status
;
282 DCHECK(task_runner_
->BelongsToCurrentThread());
283 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
284 DCHECK_NE(status
, Decryptor::kNeedMoreData
);
285 DCHECK(!read_cb_
.is_null());
286 DCHECK(pending_buffer_to_decrypt_
.get());
288 bool need_to_try_again_if_nokey
= key_added_while_decrypt_pending_
;
289 key_added_while_decrypt_pending_
= false;
291 if (!reset_cb_
.is_null()) {
292 pending_buffer_to_decrypt_
= NULL
;
293 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
298 DCHECK_EQ(status
== Decryptor::kSuccess
, decrypted_buffer
.get() != NULL
);
300 if (status
== Decryptor::kError
) {
301 DVLOG(2) << "DoDeliverBuffer() - kError";
302 pending_buffer_to_decrypt_
= NULL
;
304 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
308 if (status
== Decryptor::kNoKey
) {
309 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
310 if (need_to_try_again_if_nokey
) {
311 // The |state_| is still kPendingDecrypt.
312 DecryptPendingBuffer();
316 state_
= kWaitingForKey
;
317 waiting_for_decryption_key_cb_
.Run();
321 DCHECK_EQ(status
, Decryptor::kSuccess
);
323 // Copy the key frame flag from the encrypted to decrypted buffer, assuming
324 // that the decryptor initialized the flag to false.
325 if (pending_buffer_to_decrypt_
->is_key_frame())
326 decrypted_buffer
->set_is_key_frame(true);
328 pending_buffer_to_decrypt_
= NULL
;
330 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted_buffer
);
333 void DecryptingDemuxerStream::OnKeyAdded() {
334 DCHECK(task_runner_
->BelongsToCurrentThread());
336 if (state_
== kPendingDecrypt
) {
337 key_added_while_decrypt_pending_
= true;
341 if (state_
== kWaitingForKey
) {
342 state_
= kPendingDecrypt
;
343 DecryptPendingBuffer();
347 void DecryptingDemuxerStream::DoReset() {
348 DCHECK(state_
!= kUninitialized
);
349 DCHECK(init_cb_
.is_null());
350 DCHECK(read_cb_
.is_null());
352 if (state_
== kDecryptorRequested
)
353 state_
= kUninitialized
;
357 base::ResetAndReturn(&reset_cb_
).Run();
360 Decryptor::StreamType
DecryptingDemuxerStream::GetDecryptorStreamType() const {
361 if (demuxer_stream_
->type() == AUDIO
)
362 return Decryptor::kAudio
;
364 DCHECK_EQ(demuxer_stream_
->type(), VIDEO
);
365 return Decryptor::kVideo
;
368 void DecryptingDemuxerStream::InitializeDecoderConfig() {
369 // The decoder selector or upstream demuxer make sure the stream is valid and
370 // potentially encrypted.
371 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_
));
373 switch (demuxer_stream_
->type()) {
375 AudioDecoderConfig input_audio_config
=
376 demuxer_stream_
->audio_decoder_config();
377 audio_config_
.Initialize(input_audio_config
.codec(),
378 input_audio_config
.sample_format(),
379 input_audio_config
.channel_layout(),
380 input_audio_config
.samples_per_second(),
381 input_audio_config
.extra_data(),
382 input_audio_config
.extra_data_size(),
383 false, // Output audio is not encrypted.
385 input_audio_config
.seek_preroll(),
386 input_audio_config
.codec_delay());
391 VideoDecoderConfig input_video_config
=
392 demuxer_stream_
->video_decoder_config();
393 video_config_
.Initialize(input_video_config
.codec(),
394 input_video_config
.profile(),
395 input_video_config
.format(),
396 input_video_config
.coded_size(),
397 input_video_config
.visible_rect(),
398 input_video_config
.natural_size(),
399 input_video_config
.extra_data(),
400 input_video_config
.extra_data_size(),
401 false, // Output video is not encrypted.