Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / filters / decrypting_demuxer_stream.cc
blobff981224eddd1bd0d813eac70a35534ae38e571d
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"
7 #include "base/bind.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"
17 namespace media {
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),
39 decryptor_(NULL),
40 key_added_while_decrypt_pending_(false),
41 weak_factory_(this) {
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);
93 DoReset();
94 return;
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());
105 return;
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());
115 DoReset();
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)
157 return;
159 if (decryptor_) {
160 decryptor_->CancelDecrypt(GetDecryptorStreamType());
161 decryptor_ = NULL;
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();
185 if (!decryptor) {
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);
190 return;
193 decryptor_ = decryptor;
195 decryptor_->RegisterNewKeyCB(
196 GetDecryptorStreamType(),
197 BindToCurrentLoop(
198 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_)));
200 state_ = kIdle;
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();
224 state_ = kIdle;
225 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL);
226 if (!reset_cb_.is_null())
227 DoReset();
228 return;
231 if (!reset_cb_.is_null()) {
232 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
233 DoReset();
234 return;
237 if (status == kAborted) {
238 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
239 state_ = kIdle;
240 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
241 return;
244 if (buffer->end_of_stream()) {
245 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
246 state_ = kIdle;
247 base::ResetAndReturn(&read_cb_).Run(status, buffer);
248 return;
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);
262 state_ = kIdle;
263 base::ResetAndReturn(&read_cb_).Run(kOk, decrypted);
264 return;
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_;
275 decryptor_->Decrypt(
276 GetDecryptorStreamType(),
277 pending_buffer_to_decrypt_,
278 BindToCurrentLoop(
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);
298 DoReset();
299 return;
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;
308 state_ = kIdle;
309 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
310 return;
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();
319 return;
322 state_ = kWaitingForKey;
323 waiting_for_decryption_key_cb_.Run();
324 return;
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;
335 state_ = kIdle;
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;
344 return;
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;
360 else
361 state_ = kIdle;
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()) {
380 case AUDIO: {
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());
392 break;
395 case VIDEO: {
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.
405 break;
408 default:
409 NOTREACHED();
410 return;
414 } // namespace media