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() {
125 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
126 return demuxer_stream_
->type();
129 void DecryptingDemuxerStream::EnableBitstreamConverter() {
130 demuxer_stream_
->EnableBitstreamConverter();
133 bool DecryptingDemuxerStream::SupportsConfigChanges() {
134 return demuxer_stream_
->SupportsConfigChanges();
137 VideoRotation
DecryptingDemuxerStream::video_rotation() {
138 return VIDEO_ROTATION_0
;
141 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
142 DVLOG(2) << __FUNCTION__
<< " : state_ = " << state_
;
143 DCHECK(task_runner_
->BelongsToCurrentThread());
145 if (state_
== kUninitialized
)
149 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
152 if (!set_decryptor_ready_cb_
.is_null())
153 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
154 if (!init_cb_
.is_null())
155 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
156 if (!read_cb_
.is_null())
157 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
158 if (!reset_cb_
.is_null())
159 base::ResetAndReturn(&reset_cb_
).Run();
160 pending_buffer_to_decrypt_
= NULL
;
163 void DecryptingDemuxerStream::SetDecryptor(
164 Decryptor
* decryptor
,
165 const DecryptorAttachedCB
& decryptor_attached_cb
) {
166 DVLOG(2) << __FUNCTION__
;
167 DCHECK(task_runner_
->BelongsToCurrentThread());
168 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
169 DCHECK(!init_cb_
.is_null());
170 DCHECK(!set_decryptor_ready_cb_
.is_null());
172 set_decryptor_ready_cb_
.Reset();
175 state_
= kUninitialized
;
176 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
177 decryptor_attached_cb
.Run(false);
181 decryptor_
= decryptor
;
183 decryptor_
->RegisterNewKeyCB(
184 GetDecryptorStreamType(),
186 base::Bind(&DecryptingDemuxerStream::OnKeyAdded
, weak_this_
)));
189 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
190 decryptor_attached_cb
.Run(true);
193 void DecryptingDemuxerStream::DecryptBuffer(
194 DemuxerStream::Status status
,
195 const scoped_refptr
<DecoderBuffer
>& buffer
) {
196 DVLOG(3) << __FUNCTION__
;
197 DCHECK(task_runner_
->BelongsToCurrentThread());
198 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
199 DCHECK(!read_cb_
.is_null());
200 DCHECK_EQ(buffer
.get() != NULL
, status
== kOk
) << status
;
202 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to
203 // the caller so that the downstream decoder can be properly reinitialized.
204 if (status
== kConfigChanged
) {
205 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
206 DCHECK_EQ(demuxer_stream_
->type() == AUDIO
, audio_config_
.IsValidConfig());
207 DCHECK_EQ(demuxer_stream_
->type() == VIDEO
, video_config_
.IsValidConfig());
209 // Update the decoder config, which the decoder will use when it is notified
210 // of kConfigChanged.
211 InitializeDecoderConfig();
213 base::ResetAndReturn(&read_cb_
).Run(kConfigChanged
, NULL
);
214 if (!reset_cb_
.is_null())
219 if (!reset_cb_
.is_null()) {
220 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
225 if (status
== kAborted
) {
226 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
228 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
232 if (buffer
->end_of_stream()) {
233 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
235 base::ResetAndReturn(&read_cb_
).Run(status
, buffer
);
239 DCHECK(buffer
->decrypt_config());
240 // An empty iv string signals that the frame is unencrypted.
241 if (buffer
->decrypt_config()->iv().empty()) {
242 DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
243 scoped_refptr
<DecoderBuffer
> decrypted
= DecoderBuffer::CopyFrom(
244 buffer
->data(), buffer
->data_size());
245 decrypted
->set_timestamp(buffer
->timestamp());
246 decrypted
->set_duration(buffer
->duration());
247 if (buffer
->is_key_frame())
248 decrypted
->set_is_key_frame(true);
251 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted
);
255 pending_buffer_to_decrypt_
= buffer
;
256 state_
= kPendingDecrypt
;
257 DecryptPendingBuffer();
260 void DecryptingDemuxerStream::DecryptPendingBuffer() {
261 DCHECK(task_runner_
->BelongsToCurrentThread());
262 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
264 GetDecryptorStreamType(),
265 pending_buffer_to_decrypt_
,
267 base::Bind(&DecryptingDemuxerStream::DeliverBuffer
, weak_this_
)));
270 void DecryptingDemuxerStream::DeliverBuffer(
271 Decryptor::Status status
,
272 const scoped_refptr
<DecoderBuffer
>& decrypted_buffer
) {
273 DVLOG(3) << __FUNCTION__
<< " - status: " << status
;
274 DCHECK(task_runner_
->BelongsToCurrentThread());
275 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
276 DCHECK_NE(status
, Decryptor::kNeedMoreData
);
277 DCHECK(!read_cb_
.is_null());
278 DCHECK(pending_buffer_to_decrypt_
.get());
280 bool need_to_try_again_if_nokey
= key_added_while_decrypt_pending_
;
281 key_added_while_decrypt_pending_
= false;
283 if (!reset_cb_
.is_null()) {
284 pending_buffer_to_decrypt_
= NULL
;
285 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
290 DCHECK_EQ(status
== Decryptor::kSuccess
, decrypted_buffer
.get() != NULL
);
292 if (status
== Decryptor::kError
) {
293 DVLOG(2) << "DoDeliverBuffer() - kError";
294 pending_buffer_to_decrypt_
= NULL
;
296 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
300 if (status
== Decryptor::kNoKey
) {
301 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
302 if (need_to_try_again_if_nokey
) {
303 // The |state_| is still kPendingDecrypt.
304 DecryptPendingBuffer();
308 state_
= kWaitingForKey
;
312 DCHECK_EQ(status
, Decryptor::kSuccess
);
314 // Copy the key frame flag from the encrypted to decrypted buffer, assuming
315 // that the decryptor initialized the flag to false.
316 if (pending_buffer_to_decrypt_
->is_key_frame())
317 decrypted_buffer
->set_is_key_frame(true);
319 pending_buffer_to_decrypt_
= NULL
;
321 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted_buffer
);
324 void DecryptingDemuxerStream::OnKeyAdded() {
325 DCHECK(task_runner_
->BelongsToCurrentThread());
327 if (state_
== kPendingDecrypt
) {
328 key_added_while_decrypt_pending_
= true;
332 if (state_
== kWaitingForKey
) {
333 state_
= kPendingDecrypt
;
334 DecryptPendingBuffer();
338 void DecryptingDemuxerStream::DoReset() {
339 DCHECK(state_
!= kUninitialized
);
340 DCHECK(init_cb_
.is_null());
341 DCHECK(read_cb_
.is_null());
343 if (state_
== kDecryptorRequested
)
344 state_
= kUninitialized
;
348 base::ResetAndReturn(&reset_cb_
).Run();
351 Decryptor::StreamType
DecryptingDemuxerStream::GetDecryptorStreamType() const {
352 if (demuxer_stream_
->type() == AUDIO
)
353 return Decryptor::kAudio
;
355 DCHECK_EQ(demuxer_stream_
->type(), VIDEO
);
356 return Decryptor::kVideo
;
359 void DecryptingDemuxerStream::InitializeDecoderConfig() {
360 // The decoder selector or upstream demuxer make sure the stream is valid and
361 // potentially encrypted.
362 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_
));
364 switch (demuxer_stream_
->type()) {
366 AudioDecoderConfig input_audio_config
=
367 demuxer_stream_
->audio_decoder_config();
368 audio_config_
.Initialize(input_audio_config
.codec(),
369 input_audio_config
.sample_format(),
370 input_audio_config
.channel_layout(),
371 input_audio_config
.samples_per_second(),
372 input_audio_config
.extra_data(),
373 input_audio_config
.extra_data_size(),
374 false, // Output audio is not encrypted.
376 input_audio_config
.seek_preroll(),
377 input_audio_config
.codec_delay());
382 VideoDecoderConfig input_video_config
=
383 demuxer_stream_
->video_decoder_config();
384 video_config_
.Initialize(input_video_config
.codec(),
385 input_video_config
.profile(),
386 input_video_config
.format(),
387 input_video_config
.coded_size(),
388 input_video_config
.visible_rect(),
389 input_video_config
.natural_size(),
390 input_video_config
.extra_data(),
391 input_video_config
.extra_data_size(),
392 false, // Output video is not encrypted.