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/message_loop/message_loop_proxy.h"
12 #include "media/base/audio_decoder_config.h"
13 #include "media/base/video_decoder_config.h"
14 #include "media/base/bind_to_loop.h"
15 #include "media/base/decoder_buffer.h"
16 #include "media/base/decryptor.h"
17 #include "media/base/demuxer_stream.h"
18 #include "media/base/pipeline.h"
22 #define BIND_TO_LOOP(function) \
23 media::BindToLoop(message_loop_, base::Bind(function, weak_this_))
25 static bool IsStreamValidAndEncrypted(DemuxerStream
* stream
) {
26 return ((stream
->type() == DemuxerStream::AUDIO
&&
27 stream
->audio_decoder_config().IsValidConfig() &&
28 stream
->audio_decoder_config().is_encrypted()) ||
29 (stream
->type() == DemuxerStream::VIDEO
&&
30 stream
->video_decoder_config().IsValidConfig() &&
31 stream
->video_decoder_config().is_encrypted()));
34 DecryptingDemuxerStream::DecryptingDemuxerStream(
35 const scoped_refptr
<base::MessageLoopProxy
>& message_loop
,
36 const SetDecryptorReadyCB
& set_decryptor_ready_cb
)
37 : message_loop_(message_loop
),
39 state_(kUninitialized
),
40 demuxer_stream_(NULL
),
41 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
43 key_added_while_decrypt_pending_(false) {
46 void DecryptingDemuxerStream::Initialize(
47 DemuxerStream
* stream
,
48 const PipelineStatusCB
& status_cb
) {
49 DVLOG(2) << "Initialize()";
50 DCHECK(message_loop_
->BelongsToCurrentThread());
51 DCHECK_EQ(state_
, kUninitialized
) << state_
;
53 DCHECK(!demuxer_stream_
);
54 weak_this_
= weak_factory_
.GetWeakPtr();
55 demuxer_stream_
= stream
;
58 InitializeDecoderConfig();
60 state_
= kDecryptorRequested
;
61 set_decryptor_ready_cb_
.Run(
62 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor
));
65 void DecryptingDemuxerStream::Read(const ReadCB
& read_cb
) {
67 DCHECK(message_loop_
->BelongsToCurrentThread());
68 DCHECK_EQ(state_
, kIdle
) << state_
;
69 DCHECK(!read_cb
.is_null());
70 CHECK(read_cb_
.is_null()) << "Overlapping reads are not supported.";
73 state_
= kPendingDemuxerRead
;
74 demuxer_stream_
->Read(
75 base::Bind(&DecryptingDemuxerStream::DecryptBuffer
, weak_this_
));
78 void DecryptingDemuxerStream::Reset(const base::Closure
& closure
) {
79 DVLOG(2) << "Reset() - state: " << state_
;
80 DCHECK(message_loop_
->BelongsToCurrentThread());
81 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
82 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
83 DCHECK(reset_cb_
.is_null());
85 reset_cb_
= BindToCurrentLoop(closure
);
87 decryptor_
->CancelDecrypt(GetDecryptorStreamType());
89 // Reset() cannot complete if the read callback is still pending.
90 // Defer the resetting process in this case. The |reset_cb_| will be fired
91 // after the read callback is fired - see DoDecryptBuffer() and
93 if (state_
== kPendingDemuxerRead
|| state_
== kPendingDecrypt
) {
94 DCHECK(!read_cb_
.is_null());
98 if (state_
== kWaitingForKey
) {
99 DCHECK(!read_cb_
.is_null());
100 pending_buffer_to_decrypt_
= NULL
;
101 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
104 DCHECK(read_cb_
.is_null());
108 AudioDecoderConfig
DecryptingDemuxerStream::audio_decoder_config() {
109 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
110 CHECK_EQ(demuxer_stream_
->type(), AUDIO
);
111 return audio_config_
;
114 VideoDecoderConfig
DecryptingDemuxerStream::video_decoder_config() {
115 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
116 CHECK_EQ(demuxer_stream_
->type(), VIDEO
);
117 return video_config_
;
120 DemuxerStream::Type
DecryptingDemuxerStream::type() {
121 DCHECK(state_
!= kUninitialized
&& state_
!= kDecryptorRequested
) << state_
;
122 return demuxer_stream_
->type();
125 void DecryptingDemuxerStream::EnableBitstreamConverter() {
126 demuxer_stream_
->EnableBitstreamConverter();
129 DecryptingDemuxerStream::~DecryptingDemuxerStream() {}
131 void DecryptingDemuxerStream::SetDecryptor(Decryptor
* decryptor
) {
132 DVLOG(2) << "SetDecryptor()";
133 DCHECK(message_loop_
->BelongsToCurrentThread());
134 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
135 DCHECK(!init_cb_
.is_null());
136 DCHECK(!set_decryptor_ready_cb_
.is_null());
138 set_decryptor_ready_cb_
.Reset();
141 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
142 state_
= kUninitialized
;
146 decryptor_
= decryptor
;
148 decryptor_
->RegisterNewKeyCB(
149 GetDecryptorStreamType(),
150 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded
));
153 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
156 void DecryptingDemuxerStream::DecryptBuffer(
157 DemuxerStream::Status status
,
158 const scoped_refptr
<DecoderBuffer
>& buffer
) {
159 DVLOG(3) << "DecryptBuffer()";
160 DCHECK(message_loop_
->BelongsToCurrentThread());
161 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
162 DCHECK(!read_cb_
.is_null());
163 DCHECK_EQ(buffer
.get() != NULL
, status
== kOk
) << status
;
165 if (!reset_cb_
.is_null()) {
166 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
171 if (status
== kAborted
) {
172 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
174 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
178 if (status
== kConfigChanged
) {
179 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
180 DCHECK_EQ(demuxer_stream_
->type() == AUDIO
, audio_config_
.IsValidConfig());
181 DCHECK_EQ(demuxer_stream_
->type() == VIDEO
, video_config_
.IsValidConfig());
183 // Update the decoder config, which the decoder will use when it is notified
184 // of kConfigChanged.
185 InitializeDecoderConfig();
187 base::ResetAndReturn(&read_cb_
).Run(kConfigChanged
, NULL
);
191 if (buffer
->end_of_stream()) {
192 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
194 base::ResetAndReturn(&read_cb_
).Run(status
, buffer
);
198 pending_buffer_to_decrypt_
= buffer
;
199 state_
= kPendingDecrypt
;
200 DecryptPendingBuffer();
203 void DecryptingDemuxerStream::DecryptPendingBuffer() {
204 DCHECK(message_loop_
->BelongsToCurrentThread());
205 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
207 GetDecryptorStreamType(),
208 pending_buffer_to_decrypt_
,
209 BIND_TO_LOOP(&DecryptingDemuxerStream::DeliverBuffer
));
212 void DecryptingDemuxerStream::DeliverBuffer(
213 Decryptor::Status status
,
214 const scoped_refptr
<DecoderBuffer
>& decrypted_buffer
) {
215 DVLOG(3) << "DeliverBuffer() - status: " << status
;
216 DCHECK(message_loop_
->BelongsToCurrentThread());
217 DCHECK_EQ(state_
, kPendingDecrypt
) << state_
;
218 DCHECK_NE(status
, Decryptor::kNeedMoreData
);
219 DCHECK(!read_cb_
.is_null());
220 DCHECK(pending_buffer_to_decrypt_
.get());
222 bool need_to_try_again_if_nokey
= key_added_while_decrypt_pending_
;
223 key_added_while_decrypt_pending_
= false;
225 if (!reset_cb_
.is_null()) {
226 pending_buffer_to_decrypt_
= NULL
;
227 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
232 DCHECK_EQ(status
== Decryptor::kSuccess
, decrypted_buffer
.get() != NULL
);
234 if (status
== Decryptor::kError
) {
235 DVLOG(2) << "DoDeliverBuffer() - kError";
236 pending_buffer_to_decrypt_
= NULL
;
238 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
242 if (status
== Decryptor::kNoKey
) {
243 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
244 if (need_to_try_again_if_nokey
) {
245 // The |state_| is still kPendingDecrypt.
246 DecryptPendingBuffer();
250 state_
= kWaitingForKey
;
254 DCHECK_EQ(status
, Decryptor::kSuccess
);
255 pending_buffer_to_decrypt_
= NULL
;
257 base::ResetAndReturn(&read_cb_
).Run(kOk
, decrypted_buffer
);
260 void DecryptingDemuxerStream::OnKeyAdded() {
261 DCHECK(message_loop_
->BelongsToCurrentThread());
263 if (state_
== kPendingDecrypt
) {
264 key_added_while_decrypt_pending_
= true;
268 if (state_
== kWaitingForKey
) {
269 state_
= kPendingDecrypt
;
270 DecryptPendingBuffer();
274 void DecryptingDemuxerStream::DoReset() {
275 DCHECK(init_cb_
.is_null());
276 DCHECK(read_cb_
.is_null());
278 base::ResetAndReturn(&reset_cb_
).Run();
281 Decryptor::StreamType
DecryptingDemuxerStream::GetDecryptorStreamType() const {
282 if (demuxer_stream_
->type() == AUDIO
)
283 return Decryptor::kAudio
;
285 DCHECK_EQ(demuxer_stream_
->type(), VIDEO
);
286 return Decryptor::kVideo
;
289 void DecryptingDemuxerStream::InitializeDecoderConfig() {
290 // The decoder selector or upstream demuxer make sure the stream is valid and
291 // potentially encrypted.
292 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_
));
294 switch (demuxer_stream_
->type()) {
296 AudioDecoderConfig input_audio_config
=
297 demuxer_stream_
->audio_decoder_config();
298 audio_config_
.Initialize(input_audio_config
.codec(),
299 input_audio_config
.sample_format(),
300 input_audio_config
.channel_layout(),
301 input_audio_config
.samples_per_second(),
302 input_audio_config
.extra_data(),
303 input_audio_config
.extra_data_size(),
304 false, // Output audio is not encrypted.
310 VideoDecoderConfig input_video_config
=
311 demuxer_stream_
->video_decoder_config();
312 video_config_
.Initialize(input_video_config
.codec(),
313 input_video_config
.profile(),
314 input_video_config
.format(),
315 input_video_config
.coded_size(),
316 input_video_config
.visible_rect(),
317 input_video_config
.natural_size(),
318 input_video_config
.extra_data(),
319 input_video_config
.extra_data_size(),
320 false, // Output video is not encrypted.