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(state_
!= kStopped
) << state_
;
78 DCHECK(reset_cb_
.is_null());
80 reset_cb_
= BindToCurrentLoop(closure
);
82 // TODO(xhwang): This should not happen. Remove it, DCHECK against the
83 // condition and clean up related tests.
84 if (state_
== kDecryptorRequested
) {
85 DCHECK(!init_cb_
.is_null());
86 set_decryptor_ready_cb_
.Run(DecryptorReadyCB());
87 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
92 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
94 // Reset() cannot complete if the read callback is still pending.
95 // Defer the resetting process in this case. The |reset_cb_| will be fired
96 // after the read callback is fired - see DoDecryptBuffer() and
98 if (state_
== kPendingDemuxerRead
|| state_
== kPendingDecrypt
) {
99 DCHECK(!read_cb_
.is_null());
103 if (state_
== kWaitingForKey
) {
104 DCHECK(!read_cb_
.is_null());
105 pending_buffer_to_decrypt_
= NULL
;
106 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
109 DCHECK(read_cb_
.is_null());
113 void DecryptingDemuxerStream::Stop(const base::Closure
& closure
) {
114 DVLOG(2) << __FUNCTION__
<< " - state: " << state_
;
115 DCHECK(task_runner_
->BelongsToCurrentThread());
116 DCHECK(state_
!= kUninitialized
) << state_
;
118 // Invalidate all weak pointers so that pending callbacks won't be fired into
120 weak_factory_
.InvalidateWeakPtrs();
122 // At this point the render thread is likely paused (in WebMediaPlayerImpl's
123 // Destroy()), so running |closure| can't wait for anything that requires the
124 // render thread to process messages to complete (such as PPAPI methods).
126 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
129 if (!set_decryptor_ready_cb_
.is_null())
130 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
131 if (!init_cb_
.is_null())
132 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
133 if (!read_cb_
.is_null())
134 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
135 if (!reset_cb_
.is_null())
136 base::ResetAndReturn(&reset_cb_
).Run();
137 pending_buffer_to_decrypt_
= NULL
;
140 BindToCurrentLoop(closure
).Run();
143 AudioDecoderConfig
DecryptingDemuxerStream::audio_decoder_config() {
144 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
145 CHECK_EQ(demuxer_stream_
->type(), AUDIO
);
146 return audio_config_
;
149 VideoDecoderConfig
DecryptingDemuxerStream::video_decoder_config() {
150 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
151 CHECK_EQ(demuxer_stream_
->type(), VIDEO
);
152 return video_config_
;
155 DemuxerStream::Type
DecryptingDemuxerStream::type() {
156 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
157 return demuxer_stream_
->type();
160 void DecryptingDemuxerStream::EnableBitstreamConverter() {
161 demuxer_stream_
->EnableBitstreamConverter();
164 bool DecryptingDemuxerStream::SupportsConfigChanges() {
165 return demuxer_stream_
->SupportsConfigChanges();
168 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
169 DVLOG(2) << __FUNCTION__
<< " : state_ = " << state_
;
172 void DecryptingDemuxerStream::SetDecryptor(Decryptor
* decryptor
) {
173 DVLOG(2) << __FUNCTION__
;
174 DCHECK(task_runner_
->BelongsToCurrentThread());
175 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
176 DCHECK(!init_cb_
.is_null());
177 DCHECK(!set_decryptor_ready_cb_
.is_null());
179 set_decryptor_ready_cb_
.Reset();
182 state_
= kUninitialized
;
183 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
187 decryptor_
= decryptor
;
189 decryptor_
->RegisterNewKeyCB(
190 GetDecryptorStreamType(),
192 base::Bind(&DecryptingDemuxerStream::OnKeyAdded
, weak_this_
)));
195 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
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());
253 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted
);
257 pending_buffer_to_decrypt_
= buffer
;
258 state_
= kPendingDecrypt
;
259 DecryptPendingBuffer();
262 void DecryptingDemuxerStream::DecryptPendingBuffer() {
263 DCHECK(task_runner_
->BelongsToCurrentThread());
264 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
266 GetDecryptorStreamType(),
267 pending_buffer_to_decrypt_
,
269 base::Bind(&DecryptingDemuxerStream::DeliverBuffer
, weak_this_
)));
272 void DecryptingDemuxerStream::DeliverBuffer(
273 Decryptor::Status status
,
274 const scoped_refptr
<DecoderBuffer
>& decrypted_buffer
) {
275 DVLOG(3) << __FUNCTION__
<< " - status: " << status
;
276 DCHECK(task_runner_
->BelongsToCurrentThread());
277 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
278 DCHECK_NE(status
, Decryptor::kNeedMoreData
);
279 DCHECK(!read_cb_
.is_null());
280 DCHECK(pending_buffer_to_decrypt_
.get());
282 bool need_to_try_again_if_nokey
= key_added_while_decrypt_pending_
;
283 key_added_while_decrypt_pending_
= false;
285 if (!reset_cb_
.is_null()) {
286 pending_buffer_to_decrypt_
= NULL
;
287 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
292 DCHECK_EQ(status
== Decryptor::kSuccess
, decrypted_buffer
.get() != NULL
);
294 if (status
== Decryptor::kError
) {
295 DVLOG(2) << "DoDeliverBuffer() - kError";
296 pending_buffer_to_decrypt_
= NULL
;
298 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
302 if (status
== Decryptor::kNoKey
) {
303 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
304 if (need_to_try_again_if_nokey
) {
305 // The |state_| is still kPendingDecrypt.
306 DecryptPendingBuffer();
310 state_
= kWaitingForKey
;
314 DCHECK_EQ(status
, Decryptor::kSuccess
);
315 pending_buffer_to_decrypt_
= NULL
;
317 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted_buffer
);
320 void DecryptingDemuxerStream::OnKeyAdded() {
321 DCHECK(task_runner_
->BelongsToCurrentThread());
323 if (state_
== kPendingDecrypt
) {
324 key_added_while_decrypt_pending_
= true;
328 if (state_
== kWaitingForKey
) {
329 state_
= kPendingDecrypt
;
330 DecryptPendingBuffer();
334 void DecryptingDemuxerStream::DoReset() {
335 DCHECK(state_
!= kUninitialized
);
336 DCHECK(init_cb_
.is_null());
337 DCHECK(read_cb_
.is_null());
339 if (state_
== kDecryptorRequested
)
340 state_
= kUninitialized
;
344 base::ResetAndReturn(&reset_cb_
).Run();
347 Decryptor::StreamType
DecryptingDemuxerStream::GetDecryptorStreamType() const {
348 if (demuxer_stream_
->type() == AUDIO
)
349 return Decryptor::kAudio
;
351 DCHECK_EQ(demuxer_stream_
->type(), VIDEO
);
352 return Decryptor::kVideo
;
355 void DecryptingDemuxerStream::InitializeDecoderConfig() {
356 // The decoder selector or upstream demuxer make sure the stream is valid and
357 // potentially encrypted.
358 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_
));
360 switch (demuxer_stream_
->type()) {
362 AudioDecoderConfig input_audio_config
=
363 demuxer_stream_
->audio_decoder_config();
364 audio_config_
.Initialize(input_audio_config
.codec(),
365 input_audio_config
.sample_format(),
366 input_audio_config
.channel_layout(),
367 input_audio_config
.samples_per_second(),
368 input_audio_config
.extra_data(),
369 input_audio_config
.extra_data_size(),
370 false, // Output audio is not encrypted.
378 VideoDecoderConfig input_video_config
=
379 demuxer_stream_
->video_decoder_config();
380 video_config_
.Initialize(input_video_config
.codec(),
381 input_video_config
.profile(),
382 input_video_config
.format(),
383 input_video_config
.coded_size(),
384 input_video_config
.visible_rect(),
385 input_video_config
.natural_size(),
386 input_video_config
.extra_data(),
387 input_video_config
.extra_data_size(),
388 false, // Output video is not encrypted.