Make use of CreateWebUIForRenderManager (doesn't change the actual behavior)
[chromium-blink-merge.git] / media / filters / decrypting_audio_decoder.cc
blob4ae6718f14d42a78c75cbe383f17d0dbe5db2683
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_audio_decoder.h"
7 #include <cstdlib>
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/message_loop_proxy.h"
14 #include "media/base/audio_decoder_config.h"
15 #include "media/base/bind_to_loop.h"
16 #include "media/base/buffers.h"
17 #include "media/base/data_buffer.h"
18 #include "media/base/decoder_buffer.h"
19 #include "media/base/decryptor.h"
20 #include "media/base/demuxer_stream.h"
21 #include "media/base/pipeline.h"
23 namespace media {
25 const int DecryptingAudioDecoder::kSupportedBitsPerChannel = 16;
27 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1,
28 const base::TimeDelta& timestamp_2) {
29 // Out of sync of 100ms would be pretty noticeable and we should keep any
30 // drift below that.
31 const int64 kOutOfSyncThresholdInMicroseconds = 100000;
32 return std::abs(timestamp_1.InMicroseconds() - timestamp_2.InMicroseconds()) >
33 kOutOfSyncThresholdInMicroseconds;
36 DecryptingAudioDecoder::DecryptingAudioDecoder(
37 const scoped_refptr<base::MessageLoopProxy>& message_loop,
38 const SetDecryptorReadyCB& set_decryptor_ready_cb)
39 : message_loop_(message_loop),
40 state_(kUninitialized),
41 set_decryptor_ready_cb_(set_decryptor_ready_cb),
42 decryptor_(NULL),
43 key_added_while_decode_pending_(false),
44 bits_per_channel_(0),
45 channel_layout_(CHANNEL_LAYOUT_NONE),
46 samples_per_second_(0),
47 bytes_per_sample_(0),
48 output_timestamp_base_(kNoTimestamp()),
49 total_samples_decoded_(0) {
52 void DecryptingAudioDecoder::Initialize(
53 const scoped_refptr<DemuxerStream>& stream,
54 const PipelineStatusCB& status_cb,
55 const StatisticsCB& statistics_cb) {
56 DVLOG(2) << "Initialize()";
57 DCHECK(message_loop_->BelongsToCurrentThread());
58 DCHECK_EQ(state_, kUninitialized) << state_;
59 DCHECK(stream);
61 init_cb_ = BindToCurrentLoop(status_cb);
63 const AudioDecoderConfig& config = stream->audio_decoder_config();
64 if (!config.IsValidConfig()) {
65 DLOG(ERROR) << "Invalid audio stream config.";
66 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE);
67 return;
70 // DecryptingAudioDecoder only accepts potentially encrypted stream.
71 if (!config.is_encrypted()) {
72 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
73 return;
76 DCHECK(!demuxer_stream_);
77 demuxer_stream_ = stream;
78 statistics_cb_ = statistics_cb;
80 state_ = kDecryptorRequested;
81 set_decryptor_ready_cb_.Run(BindToCurrentLoop(
82 base::Bind(&DecryptingAudioDecoder::SetDecryptor, this)));
85 void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
86 DVLOG(3) << "Read()";
87 DCHECK(message_loop_->BelongsToCurrentThread());
88 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
89 DCHECK(!read_cb.is_null());
90 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
92 read_cb_ = BindToCurrentLoop(read_cb);
94 // Return empty (end-of-stream) frames if decoding has finished.
95 if (state_ == kDecodeFinished) {
96 base::ResetAndReturn(&read_cb_).Run(kOk, DataBuffer::CreateEOSBuffer());
97 return;
100 if (!queued_audio_frames_.empty()) {
101 base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
102 queued_audio_frames_.pop_front();
103 return;
106 state_ = kPendingDemuxerRead;
107 ReadFromDemuxerStream();
110 void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
111 DVLOG(2) << "Reset() - state: " << state_;
112 DCHECK(message_loop_->BelongsToCurrentThread());
113 DCHECK(state_ == kIdle ||
114 state_ == kPendingConfigChange ||
115 state_ == kPendingDemuxerRead ||
116 state_ == kPendingDecode ||
117 state_ == kWaitingForKey ||
118 state_ == kDecodeFinished) << state_;
119 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
120 DCHECK(reset_cb_.is_null());
122 reset_cb_ = closure;
124 decryptor_->ResetDecoder(Decryptor::kAudio);
126 // Reset() cannot complete if the read callback is still pending.
127 // Defer the resetting process in this case. The |reset_cb_| will be fired
128 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and
129 // DoDeliverFrame().
130 if (state_ == kPendingConfigChange ||
131 state_ == kPendingDemuxerRead ||
132 state_ == kPendingDecode) {
133 DCHECK(!read_cb_.is_null());
134 return;
137 if (state_ == kWaitingForKey) {
138 DCHECK(!read_cb_.is_null());
139 pending_buffer_to_decode_ = NULL;
140 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
143 DCHECK(read_cb_.is_null());
144 DoReset();
147 int DecryptingAudioDecoder::bits_per_channel() {
148 DCHECK(message_loop_->BelongsToCurrentThread());
149 return bits_per_channel_;
152 ChannelLayout DecryptingAudioDecoder::channel_layout() {
153 DCHECK(message_loop_->BelongsToCurrentThread());
154 return channel_layout_;
157 int DecryptingAudioDecoder::samples_per_second() {
158 DCHECK(message_loop_->BelongsToCurrentThread());
159 return samples_per_second_;
162 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
165 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
166 DVLOG(2) << "SetDecryptor()";
167 DCHECK(message_loop_->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();
173 decryptor_ = decryptor;
175 const AudioDecoderConfig& input_config =
176 demuxer_stream_->audio_decoder_config();
177 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
178 scoped_config->Initialize(input_config.codec(),
179 kSampleFormatS16,
180 input_config.channel_layout(),
181 input_config.samples_per_second(),
182 input_config.extra_data(),
183 input_config.extra_data_size(),
184 input_config.is_encrypted(),
185 false);
187 state_ = kPendingDecoderInit;
188 decryptor_->InitializeAudioDecoder(
189 scoped_config.Pass(),
190 BindToCurrentLoop(base::Bind(
191 &DecryptingAudioDecoder::FinishInitialization, this)));
194 void DecryptingAudioDecoder::FinishInitialization(bool success) {
195 DVLOG(2) << "FinishInitialization()";
196 DCHECK(message_loop_->BelongsToCurrentThread());
197 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
198 DCHECK(!init_cb_.is_null());
199 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
200 DCHECK(read_cb_.is_null()); // No Read() before initialization finished.
202 if (!success) {
203 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
204 state_ = kDecodeFinished;
205 return;
208 // Success!
209 UpdateDecoderConfig();
211 decryptor_->RegisterNewKeyCB(
212 Decryptor::kAudio, BindToCurrentLoop(base::Bind(
213 &DecryptingAudioDecoder::OnKeyAdded, this)));
215 state_ = kIdle;
216 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
219 void DecryptingAudioDecoder::FinishConfigChange(bool success) {
220 DVLOG(2) << "FinishConfigChange()";
221 DCHECK(message_loop_->BelongsToCurrentThread());
222 DCHECK_EQ(state_, kPendingConfigChange) << state_;
223 DCHECK(!read_cb_.is_null());
225 if (!success) {
226 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
227 state_ = kDecodeFinished;
228 if (!reset_cb_.is_null())
229 base::ResetAndReturn(&reset_cb_).Run();
230 return;
233 // Config change succeeded.
234 UpdateDecoderConfig();
236 if (!reset_cb_.is_null()) {
237 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
238 DoReset();
239 return;
242 state_ = kPendingDemuxerRead;
243 ReadFromDemuxerStream();
246 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
247 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
248 DCHECK(!read_cb_.is_null());
250 demuxer_stream_->Read(
251 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this));
254 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
255 DemuxerStream::Status status,
256 const scoped_refptr<DecoderBuffer>& buffer) {
257 DVLOG(3) << "DecryptAndDecodeBuffer()";
258 DCHECK(message_loop_->BelongsToCurrentThread());
259 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
260 DCHECK(!read_cb_.is_null());
261 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;
263 if (status == DemuxerStream::kConfigChanged) {
264 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
266 const AudioDecoderConfig& input_config =
267 demuxer_stream_->audio_decoder_config();
268 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
269 scoped_config->Initialize(input_config.codec(),
270 kSampleFormatS16,
271 input_config.channel_layout(),
272 input_config.samples_per_second(),
273 input_config.extra_data(),
274 input_config.extra_data_size(),
275 input_config.is_encrypted(),
276 false);
278 state_ = kPendingConfigChange;
279 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
280 decryptor_->InitializeAudioDecoder(
281 scoped_config.Pass(), BindToCurrentLoop(base::Bind(
282 &DecryptingAudioDecoder::FinishConfigChange, this)));
283 return;
286 if (!reset_cb_.is_null()) {
287 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
288 DoReset();
289 return;
292 if (status == DemuxerStream::kAborted) {
293 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
294 state_ = kIdle;
295 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
296 return;
299 DCHECK_EQ(status, DemuxerStream::kOk);
301 // Initialize the |next_output_timestamp_| to be the timestamp of the first
302 // non-EOS buffer.
303 if (output_timestamp_base_ == kNoTimestamp() && !buffer->IsEndOfStream()) {
304 DCHECK_EQ(total_samples_decoded_, 0);
305 output_timestamp_base_ = buffer->GetTimestamp();
308 pending_buffer_to_decode_ = buffer;
309 state_ = kPendingDecode;
310 DecodePendingBuffer();
313 void DecryptingAudioDecoder::DecodePendingBuffer() {
314 DCHECK(message_loop_->BelongsToCurrentThread());
315 DCHECK_EQ(state_, kPendingDecode) << state_;
317 int buffer_size = 0;
318 if (!pending_buffer_to_decode_->IsEndOfStream()) {
319 buffer_size = pending_buffer_to_decode_->GetDataSize();
322 decryptor_->DecryptAndDecodeAudio(
323 pending_buffer_to_decode_,
324 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this, buffer_size));
327 void DecryptingAudioDecoder::DeliverFrame(
328 int buffer_size,
329 Decryptor::Status status,
330 const Decryptor::AudioBuffers& frames) {
331 // We need to force task post here because the AudioDecodeCB can be executed
332 // synchronously in Reset(). Instead of using more complicated logic in
333 // those function to fix it, why not force task post here to make everything
334 // simple and clear?
335 message_loop_->PostTask(FROM_HERE, base::Bind(
336 &DecryptingAudioDecoder::DoDeliverFrame, this,
337 buffer_size, status, frames));
340 void DecryptingAudioDecoder::DoDeliverFrame(
341 int buffer_size,
342 Decryptor::Status status,
343 const Decryptor::AudioBuffers& frames) {
344 DVLOG(3) << "DoDeliverFrame() - status: " << status;
345 DCHECK(message_loop_->BelongsToCurrentThread());
346 DCHECK_EQ(state_, kPendingDecode) << state_;
347 DCHECK(!read_cb_.is_null());
348 DCHECK(pending_buffer_to_decode_);
349 DCHECK(queued_audio_frames_.empty());
351 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
352 key_added_while_decode_pending_ = false;
354 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
355 pending_buffer_to_decode_;
356 pending_buffer_to_decode_ = NULL;
358 if (!reset_cb_.is_null()) {
359 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
360 DoReset();
361 return;
364 DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());
366 if (status == Decryptor::kError) {
367 DVLOG(2) << "DoDeliverFrame() - kError";
368 state_ = kDecodeFinished;
369 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
370 return;
373 if (status == Decryptor::kNoKey) {
374 DVLOG(2) << "DoDeliverFrame() - kNoKey";
375 // Set |pending_buffer_to_decode_| back as we need to try decoding the
376 // pending buffer again when new key is added to the decryptor.
377 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
379 if (need_to_try_again_if_nokey_is_returned) {
380 // The |state_| is still kPendingDecode.
381 DecodePendingBuffer();
382 return;
385 state_ = kWaitingForKey;
386 return;
389 // The buffer has been accepted by the decoder, let's report statistics.
390 if (buffer_size) {
391 PipelineStatistics statistics;
392 statistics.audio_bytes_decoded = buffer_size;
393 statistics_cb_.Run(statistics);
396 if (status == Decryptor::kNeedMoreData) {
397 DVLOG(2) << "DoDeliverFrame() - kNeedMoreData";
398 if (scoped_pending_buffer_to_decode->IsEndOfStream()) {
399 state_ = kDecodeFinished;
400 base::ResetAndReturn(&read_cb_).Run(kOk, DataBuffer::CreateEOSBuffer());
401 return;
404 state_ = kPendingDemuxerRead;
405 ReadFromDemuxerStream();
406 return;
409 DCHECK_EQ(status, Decryptor::kSuccess);
410 DCHECK(!frames.empty());
411 EnqueueFrames(frames);
413 state_ = kIdle;
414 base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
415 queued_audio_frames_.pop_front();
418 void DecryptingAudioDecoder::OnKeyAdded() {
419 DCHECK(message_loop_->BelongsToCurrentThread());
421 if (state_ == kPendingDecode) {
422 key_added_while_decode_pending_ = true;
423 return;
426 if (state_ == kWaitingForKey) {
427 state_ = kPendingDecode;
428 DecodePendingBuffer();
432 void DecryptingAudioDecoder::DoReset() {
433 DCHECK(init_cb_.is_null());
434 DCHECK(read_cb_.is_null());
435 output_timestamp_base_ = kNoTimestamp();
436 total_samples_decoded_ = 0;
437 state_ = kIdle;
438 base::ResetAndReturn(&reset_cb_).Run();
441 void DecryptingAudioDecoder::UpdateDecoderConfig() {
442 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config();
443 bits_per_channel_ = kSupportedBitsPerChannel;
444 channel_layout_ = config.channel_layout();
445 samples_per_second_ = config.samples_per_second();
446 const int kBitsPerByte = 8;
447 bytes_per_sample_ = ChannelLayoutToChannelCount(channel_layout_) *
448 bits_per_channel_ / kBitsPerByte;
449 output_timestamp_base_ = kNoTimestamp();
450 total_samples_decoded_ = 0;
453 void DecryptingAudioDecoder::EnqueueFrames(
454 const Decryptor::AudioBuffers& frames) {
455 queued_audio_frames_ = frames;
457 for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin();
458 iter != queued_audio_frames_.end();
459 ++iter) {
460 scoped_refptr<DataBuffer>& frame = *iter;
462 DCHECK(!frame->IsEndOfStream()) << "EOS frame returned.";
463 DCHECK_GT(frame->GetDataSize(), 0) << "Empty frame returned.";
465 base::TimeDelta cur_timestamp = output_timestamp_base_ +
466 NumberOfSamplesToDuration(total_samples_decoded_);
467 if (IsOutOfSync(cur_timestamp, frame->GetTimestamp())) {
468 DVLOG(1) << "Timestamp returned by the decoder ("
469 << frame->GetTimestamp().InMilliseconds() << " ms)"
470 << " does not match the input timestamp and number of samples"
471 << " decoded (" << cur_timestamp.InMilliseconds() << " ms).";
473 frame->SetTimestamp(cur_timestamp);
475 int frame_size = frame->GetDataSize();
476 DCHECK_EQ(frame_size % bytes_per_sample_, 0) <<
477 "Decoder didn't output full samples";
478 int samples_decoded = frame_size / bytes_per_sample_;
479 total_samples_decoded_ += samples_decoded;
481 base::TimeDelta next_timestamp = output_timestamp_base_ +
482 NumberOfSamplesToDuration(total_samples_decoded_);
483 base::TimeDelta duration = next_timestamp - cur_timestamp;
484 frame->SetDuration(duration);
488 base::TimeDelta DecryptingAudioDecoder::NumberOfSamplesToDuration(
489 int number_of_samples) const {
490 DCHECK(samples_per_second_);
491 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
492 number_of_samples /
493 samples_per_second_);
496 } // namespace media