Remove some suppressions which are no longer needed. BitmapPlatformDeviceData was...
[chromium-blink-merge.git] / media / filters / decrypting_audio_decoder.cc
blob2c144b4fc7e3b7f2d57900c0c010d1c5a53e2cc7
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/message_loop_proxy.h"
14 #include "media/base/audio_buffer.h"
15 #include "media/base/audio_decoder_config.h"
16 #include "media/base/audio_timestamp_helper.h"
17 #include "media/base/bind_to_loop.h"
18 #include "media/base/buffers.h"
19 #include "media/base/decoder_buffer.h"
20 #include "media/base/decryptor.h"
21 #include "media/base/demuxer_stream.h"
22 #include "media/base/pipeline.h"
24 namespace media {
26 const int DecryptingAudioDecoder::kSupportedBitsPerChannel = 16;
28 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1,
29 const base::TimeDelta& timestamp_2) {
30 // Out of sync of 100ms would be pretty noticeable and we should keep any
31 // drift below that.
32 const int64 kOutOfSyncThresholdInMilliseconds = 100;
33 return std::abs(timestamp_1.InMilliseconds() - timestamp_2.InMilliseconds()) >
34 kOutOfSyncThresholdInMilliseconds;
37 DecryptingAudioDecoder::DecryptingAudioDecoder(
38 const scoped_refptr<base::MessageLoopProxy>& message_loop,
39 const SetDecryptorReadyCB& set_decryptor_ready_cb)
40 : message_loop_(message_loop),
41 weak_factory_(this),
42 state_(kUninitialized),
43 demuxer_stream_(NULL),
44 set_decryptor_ready_cb_(set_decryptor_ready_cb),
45 decryptor_(NULL),
46 key_added_while_decode_pending_(false),
47 bits_per_channel_(0),
48 channel_layout_(CHANNEL_LAYOUT_NONE),
49 samples_per_second_(0) {
52 void DecryptingAudioDecoder::Initialize(
53 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 weak_this_ = weak_factory_.GetWeakPtr();
62 init_cb_ = BindToCurrentLoop(status_cb);
64 const AudioDecoderConfig& config = stream->audio_decoder_config();
65 if (!config.IsValidConfig()) {
66 DLOG(ERROR) << "Invalid audio stream config.";
67 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE);
68 return;
71 // DecryptingAudioDecoder only accepts potentially encrypted stream.
72 if (!config.is_encrypted()) {
73 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
74 return;
77 DCHECK(!demuxer_stream_);
78 demuxer_stream_ = stream;
79 statistics_cb_ = statistics_cb;
81 state_ = kDecryptorRequested;
82 set_decryptor_ready_cb_.Run(BindToCurrentLoop(
83 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
86 void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
87 DVLOG(3) << "Read()";
88 DCHECK(message_loop_->BelongsToCurrentThread());
89 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
90 DCHECK(!read_cb.is_null());
91 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
93 read_cb_ = BindToCurrentLoop(read_cb);
95 // Return empty (end-of-stream) frames if decoding has finished.
96 if (state_ == kDecodeFinished) {
97 base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer());
98 return;
101 if (!queued_audio_frames_.empty()) {
102 base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
103 queued_audio_frames_.pop_front();
104 return;
107 state_ = kPendingDemuxerRead;
108 ReadFromDemuxerStream();
111 void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
112 DVLOG(2) << "Reset() - state: " << state_;
113 DCHECK(message_loop_->BelongsToCurrentThread());
114 DCHECK(state_ == kIdle ||
115 state_ == kPendingConfigChange ||
116 state_ == kPendingDemuxerRead ||
117 state_ == kPendingDecode ||
118 state_ == kWaitingForKey ||
119 state_ == kDecodeFinished) << state_;
120 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
121 DCHECK(reset_cb_.is_null());
123 reset_cb_ = closure;
125 decryptor_->ResetDecoder(Decryptor::kAudio);
127 // Reset() cannot complete if the read callback is still pending.
128 // Defer the resetting process in this case. The |reset_cb_| will be fired
129 // after the read callback is fired - see DecryptAndDecodeBuffer() and
130 // DeliverFrame().
131 if (state_ == kPendingConfigChange ||
132 state_ == kPendingDemuxerRead ||
133 state_ == kPendingDecode) {
134 DCHECK(!read_cb_.is_null());
135 return;
138 if (state_ == kWaitingForKey) {
139 DCHECK(!read_cb_.is_null());
140 pending_buffer_to_decode_ = NULL;
141 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
144 DCHECK(read_cb_.is_null());
145 DoReset();
148 int DecryptingAudioDecoder::bits_per_channel() {
149 DCHECK(message_loop_->BelongsToCurrentThread());
150 return bits_per_channel_;
153 ChannelLayout DecryptingAudioDecoder::channel_layout() {
154 DCHECK(message_loop_->BelongsToCurrentThread());
155 return channel_layout_;
158 int DecryptingAudioDecoder::samples_per_second() {
159 DCHECK(message_loop_->BelongsToCurrentThread());
160 return samples_per_second_;
163 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
166 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
167 DVLOG(2) << "SetDecryptor()";
168 DCHECK(message_loop_->BelongsToCurrentThread());
169 DCHECK_EQ(state_, kDecryptorRequested) << state_;
170 DCHECK(!init_cb_.is_null());
171 DCHECK(!set_decryptor_ready_cb_.is_null());
173 set_decryptor_ready_cb_.Reset();
175 if (!decryptor) {
176 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
177 // TODO(xhwang): Add kError state. See http://crbug.com/251503
178 state_ = kDecodeFinished;
179 return;
182 decryptor_ = decryptor;
184 const AudioDecoderConfig& input_config =
185 demuxer_stream_->audio_decoder_config();
186 AudioDecoderConfig config;
187 config.Initialize(input_config.codec(),
188 kSampleFormatS16,
189 input_config.channel_layout(),
190 input_config.samples_per_second(),
191 input_config.extra_data(),
192 input_config.extra_data_size(),
193 input_config.is_encrypted(),
194 false,
195 base::TimeDelta(),
196 base::TimeDelta());
198 state_ = kPendingDecoderInit;
199 decryptor_->InitializeAudioDecoder(
200 config,
201 BindToCurrentLoop(base::Bind(
202 &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
205 void DecryptingAudioDecoder::FinishInitialization(bool success) {
206 DVLOG(2) << "FinishInitialization()";
207 DCHECK(message_loop_->BelongsToCurrentThread());
208 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
209 DCHECK(!init_cb_.is_null());
210 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
211 DCHECK(read_cb_.is_null()); // No Read() before initialization finished.
213 if (!success) {
214 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
215 state_ = kDecodeFinished;
216 return;
219 // Success!
220 UpdateDecoderConfig();
222 decryptor_->RegisterNewKeyCB(
223 Decryptor::kAudio, BindToCurrentLoop(base::Bind(
224 &DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
226 state_ = kIdle;
227 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
230 void DecryptingAudioDecoder::FinishConfigChange(bool success) {
231 DVLOG(2) << "FinishConfigChange()";
232 DCHECK(message_loop_->BelongsToCurrentThread());
233 DCHECK_EQ(state_, kPendingConfigChange) << state_;
234 DCHECK(!read_cb_.is_null());
236 if (!success) {
237 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
238 state_ = kDecodeFinished;
239 if (!reset_cb_.is_null())
240 base::ResetAndReturn(&reset_cb_).Run();
241 return;
244 // Config change succeeded.
245 UpdateDecoderConfig();
247 if (!reset_cb_.is_null()) {
248 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
249 DoReset();
250 return;
253 state_ = kPendingDemuxerRead;
254 ReadFromDemuxerStream();
257 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
258 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
259 DCHECK(!read_cb_.is_null());
261 demuxer_stream_->Read(
262 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, weak_this_));
265 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
266 DemuxerStream::Status status,
267 const scoped_refptr<DecoderBuffer>& buffer) {
268 DVLOG(3) << "DecryptAndDecodeBuffer()";
269 DCHECK(message_loop_->BelongsToCurrentThread());
270 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
271 DCHECK(!read_cb_.is_null());
272 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
274 if (status == DemuxerStream::kConfigChanged) {
275 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
277 const AudioDecoderConfig& input_config =
278 demuxer_stream_->audio_decoder_config();
279 AudioDecoderConfig config;
280 config.Initialize(input_config.codec(),
281 kSampleFormatS16,
282 input_config.channel_layout(),
283 input_config.samples_per_second(),
284 input_config.extra_data(),
285 input_config.extra_data_size(),
286 input_config.is_encrypted(),
287 false,
288 base::TimeDelta(),
289 base::TimeDelta());
291 state_ = kPendingConfigChange;
292 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
293 decryptor_->InitializeAudioDecoder(
294 config, BindToCurrentLoop(base::Bind(
295 &DecryptingAudioDecoder::FinishConfigChange, weak_this_)));
296 return;
299 if (!reset_cb_.is_null()) {
300 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
301 DoReset();
302 return;
305 if (status == DemuxerStream::kAborted) {
306 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
307 state_ = kIdle;
308 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
309 return;
312 DCHECK_EQ(status, DemuxerStream::kOk);
314 // Initialize the |next_output_timestamp_| to be the timestamp of the first
315 // non-EOS buffer.
316 if (timestamp_helper_->base_timestamp() == kNoTimestamp() &&
317 !buffer->end_of_stream()) {
318 timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
321 pending_buffer_to_decode_ = buffer;
322 state_ = kPendingDecode;
323 DecodePendingBuffer();
326 void DecryptingAudioDecoder::DecodePendingBuffer() {
327 DCHECK(message_loop_->BelongsToCurrentThread());
328 DCHECK_EQ(state_, kPendingDecode) << state_;
330 int buffer_size = 0;
331 if (!pending_buffer_to_decode_->end_of_stream()) {
332 buffer_size = pending_buffer_to_decode_->data_size();
335 decryptor_->DecryptAndDecodeAudio(
336 pending_buffer_to_decode_,
337 BindToCurrentLoop(base::Bind(
338 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size)));
341 void DecryptingAudioDecoder::DeliverFrame(
342 int buffer_size,
343 Decryptor::Status status,
344 const Decryptor::AudioBuffers& frames) {
345 DVLOG(3) << "DeliverFrame() - status: " << status;
346 DCHECK(message_loop_->BelongsToCurrentThread());
347 DCHECK_EQ(state_, kPendingDecode) << state_;
348 DCHECK(!read_cb_.is_null());
349 DCHECK(pending_buffer_to_decode_.get());
350 DCHECK(queued_audio_frames_.empty());
352 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
353 key_added_while_decode_pending_ = false;
355 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
356 pending_buffer_to_decode_;
357 pending_buffer_to_decode_ = NULL;
359 if (!reset_cb_.is_null()) {
360 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
361 DoReset();
362 return;
365 DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());
367 if (status == Decryptor::kError) {
368 DVLOG(2) << "DeliverFrame() - kError";
369 state_ = kDecodeFinished;
370 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
371 return;
374 if (status == Decryptor::kNoKey) {
375 DVLOG(2) << "DeliverFrame() - kNoKey";
376 // Set |pending_buffer_to_decode_| back as we need to try decoding the
377 // pending buffer again when new key is added to the decryptor.
378 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
380 if (need_to_try_again_if_nokey_is_returned) {
381 // The |state_| is still kPendingDecode.
382 DecodePendingBuffer();
383 return;
386 state_ = kWaitingForKey;
387 return;
390 // The buffer has been accepted by the decoder, let's report statistics.
391 if (buffer_size) {
392 PipelineStatistics statistics;
393 statistics.audio_bytes_decoded = buffer_size;
394 statistics_cb_.Run(statistics);
397 if (status == Decryptor::kNeedMoreData) {
398 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
399 if (scoped_pending_buffer_to_decode->end_of_stream()) {
400 state_ = kDecodeFinished;
401 base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer());
402 return;
405 state_ = kPendingDemuxerRead;
406 ReadFromDemuxerStream();
407 return;
410 DCHECK_EQ(status, Decryptor::kSuccess);
411 DCHECK(!frames.empty());
412 EnqueueFrames(frames);
414 state_ = kIdle;
415 base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
416 queued_audio_frames_.pop_front();
419 void DecryptingAudioDecoder::OnKeyAdded() {
420 DCHECK(message_loop_->BelongsToCurrentThread());
422 if (state_ == kPendingDecode) {
423 key_added_while_decode_pending_ = true;
424 return;
427 if (state_ == kWaitingForKey) {
428 state_ = kPendingDecode;
429 DecodePendingBuffer();
433 void DecryptingAudioDecoder::DoReset() {
434 DCHECK(init_cb_.is_null());
435 DCHECK(read_cb_.is_null());
436 timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
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 timestamp_helper_.reset(new AudioTimestampHelper(samples_per_second_));
449 void DecryptingAudioDecoder::EnqueueFrames(
450 const Decryptor::AudioBuffers& frames) {
451 queued_audio_frames_ = frames;
453 for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin();
454 iter != queued_audio_frames_.end();
455 ++iter) {
456 scoped_refptr<AudioBuffer>& frame = *iter;
458 DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
459 DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
461 base::TimeDelta current_time = timestamp_helper_->GetTimestamp();
462 if (IsOutOfSync(current_time, frame->timestamp())) {
463 DVLOG(1) << "Timestamp returned by the decoder ("
464 << frame->timestamp().InMilliseconds() << " ms)"
465 << " does not match the input timestamp and number of samples"
466 << " decoded (" << current_time.InMilliseconds() << " ms).";
469 frame->set_timestamp(current_time);
470 frame->set_duration(
471 timestamp_helper_->GetFrameDuration(frame->frame_count()));
472 timestamp_helper_->AddFrames(frame->frame_count());
476 } // namespace media