- add sources.
[platform/framework/web/crosswalk.git] / src / media / filters / decrypting_audio_decoder.cc
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.
4
5 #include "media/filters/decrypting_audio_decoder.h"
6
7 #include <cstdlib>
8
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"
23
24 namespace media {
25
26 const int DecryptingAudioDecoder::kSupportedBitsPerChannel = 16;
27
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;
35 }
36
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) {
50 }
51
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);
60
61   weak_this_ = weak_factory_.GetWeakPtr();
62   init_cb_ = BindToCurrentLoop(status_cb);
63
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;
69   }
70
71   // DecryptingAudioDecoder only accepts potentially encrypted stream.
72   if (!config.is_encrypted()) {
73     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
74     return;
75   }
76
77   DCHECK(!demuxer_stream_);
78   demuxer_stream_ = stream;
79   statistics_cb_ = statistics_cb;
80
81   state_ = kDecryptorRequested;
82   set_decryptor_ready_cb_.Run(BindToCurrentLoop(
83       base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
84 }
85
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.";
92
93   read_cb_ = BindToCurrentLoop(read_cb);
94
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;
99   }
100
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;
105   }
106
107   state_ = kPendingDemuxerRead;
108   ReadFromDemuxerStream();
109 }
110
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());
122
123   reset_cb_ = closure;
124
125   decryptor_->ResetDecoder(Decryptor::kAudio);
126
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;
136   }
137
138   if (state_ == kWaitingForKey) {
139     DCHECK(!read_cb_.is_null());
140     pending_buffer_to_decode_ = NULL;
141     base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
142   }
143
144   DCHECK(read_cb_.is_null());
145   DoReset();
146 }
147
148 int DecryptingAudioDecoder::bits_per_channel() {
149   DCHECK(message_loop_->BelongsToCurrentThread());
150   return bits_per_channel_;
151 }
152
153 ChannelLayout DecryptingAudioDecoder::channel_layout() {
154   DCHECK(message_loop_->BelongsToCurrentThread());
155   return channel_layout_;
156 }
157
158 int DecryptingAudioDecoder::samples_per_second() {
159   DCHECK(message_loop_->BelongsToCurrentThread());
160   return samples_per_second_;
161 }
162
163 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
164 }
165
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());
172
173   set_decryptor_ready_cb_.Reset();
174
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;
180   }
181
182   decryptor_ = decryptor;
183
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());
197
198   state_ = kPendingDecoderInit;
199   decryptor_->InitializeAudioDecoder(
200       config,
201       BindToCurrentLoop(base::Bind(
202           &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
203 }
204
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.
212
213   if (!success) {
214     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
215     state_ = kDecodeFinished;
216     return;
217   }
218
219   // Success!
220   UpdateDecoderConfig();
221
222   decryptor_->RegisterNewKeyCB(
223       Decryptor::kAudio, BindToCurrentLoop(base::Bind(
224           &DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
225
226   state_ = kIdle;
227   base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
228 }
229
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());
235
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;
242   }
243
244   // Config change succeeded.
245   UpdateDecoderConfig();
246
247   if (!reset_cb_.is_null()) {
248     base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
249     DoReset();
250     return;
251   }
252
253   state_ = kPendingDemuxerRead;
254   ReadFromDemuxerStream();
255 }
256
257 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
258   DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
259   DCHECK(!read_cb_.is_null());
260
261   demuxer_stream_->Read(
262       base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, weak_this_));
263 }
264
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;
273
274   if (status == DemuxerStream::kConfigChanged) {
275     DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
276
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());
290
291     state_ = kPendingConfigChange;
292     decryptor_->DeinitializeDecoder(Decryptor::kAudio);
293     decryptor_->InitializeAudioDecoder(
294         config, BindToCurrentLoop(base::Bind(
295             &DecryptingAudioDecoder::FinishConfigChange, weak_this_)));
296     return;
297   }
298
299   if (!reset_cb_.is_null()) {
300     base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
301     DoReset();
302     return;
303   }
304
305   if (status == DemuxerStream::kAborted) {
306     DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
307     state_ = kIdle;
308     base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
309     return;
310   }
311
312   DCHECK_EQ(status, DemuxerStream::kOk);
313
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());
319   }
320
321   pending_buffer_to_decode_ = buffer;
322   state_ = kPendingDecode;
323   DecodePendingBuffer();
324 }
325
326 void DecryptingAudioDecoder::DecodePendingBuffer() {
327   DCHECK(message_loop_->BelongsToCurrentThread());
328   DCHECK_EQ(state_, kPendingDecode) << state_;
329
330   int buffer_size = 0;
331   if (!pending_buffer_to_decode_->end_of_stream()) {
332     buffer_size = pending_buffer_to_decode_->data_size();
333   }
334
335   decryptor_->DecryptAndDecodeAudio(
336       pending_buffer_to_decode_,
337       BindToCurrentLoop(base::Bind(
338           &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size)));
339 }
340
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());
351
352   bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
353   key_added_while_decode_pending_ = false;
354
355   scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
356       pending_buffer_to_decode_;
357   pending_buffer_to_decode_ = NULL;
358
359   if (!reset_cb_.is_null()) {
360     base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
361     DoReset();
362     return;
363   }
364
365   DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());
366
367   if (status == Decryptor::kError) {
368     DVLOG(2) << "DeliverFrame() - kError";
369     state_ = kDecodeFinished;
370     base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
371     return;
372   }
373
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;
379
380     if (need_to_try_again_if_nokey_is_returned) {
381       // The |state_| is still kPendingDecode.
382       DecodePendingBuffer();
383       return;
384     }
385
386     state_ = kWaitingForKey;
387     return;
388   }
389
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);
395   }
396
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;
403     }
404
405     state_ = kPendingDemuxerRead;
406     ReadFromDemuxerStream();
407     return;
408   }
409
410   DCHECK_EQ(status, Decryptor::kSuccess);
411   DCHECK(!frames.empty());
412   EnqueueFrames(frames);
413
414   state_ = kIdle;
415   base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
416   queued_audio_frames_.pop_front();
417 }
418
419 void DecryptingAudioDecoder::OnKeyAdded() {
420   DCHECK(message_loop_->BelongsToCurrentThread());
421
422   if (state_ == kPendingDecode) {
423     key_added_while_decode_pending_ = true;
424     return;
425   }
426
427   if (state_ == kWaitingForKey) {
428     state_ = kPendingDecode;
429     DecodePendingBuffer();
430   }
431 }
432
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();
439 }
440
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_));
447 }
448
449 void DecryptingAudioDecoder::EnqueueFrames(
450     const Decryptor::AudioBuffers& frames) {
451   queued_audio_frames_ = frames;
452
453   for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin();
454        iter != queued_audio_frames_.end();
455        ++iter) {
456     scoped_refptr<AudioBuffer>& frame = *iter;
457
458     DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
459     DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
460
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).";
467     }
468
469     frame->set_timestamp(current_time);
470     frame->set_duration(
471         timestamp_helper_->GetFrameDuration(frame->frame_count()));
472     timestamp_helper_->AddFrames(frame->frame_count());
473   }
474 }
475
476 }  // namespace media