Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / filters / decrypting_audio_decoder.cc
index a96c9db..c5494f0 100644 (file)
@@ -38,30 +38,28 @@ DecryptingAudioDecoder::DecryptingAudioDecoder(
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     const SetDecryptorReadyCB& set_decryptor_ready_cb)
     : task_runner_(task_runner),
-      weak_factory_(this),
       state_(kUninitialized),
-      demuxer_stream_(NULL),
       set_decryptor_ready_cb_(set_decryptor_ready_cb),
       decryptor_(NULL),
       key_added_while_decode_pending_(false),
-      bits_per_channel_(0),
-      channel_layout_(CHANNEL_LAYOUT_NONE),
-      samples_per_second_(0) {
+      weak_factory_(this) {}
+
+std::string DecryptingAudioDecoder::GetDisplayName() const {
+  return "DecryptingAudioDecoder";
 }
 
-void DecryptingAudioDecoder::Initialize(
-    DemuxerStream* stream,
-    const PipelineStatusCB& status_cb,
-    const StatisticsCB& statistics_cb) {
+void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
+                                        const PipelineStatusCB& status_cb,
+                                        const OutputCB& output_cb) {
   DVLOG(2) << "Initialize()";
   DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK_EQ(state_, kUninitialized) << state_;
-  DCHECK(stream);
+  DCHECK(decode_cb_.is_null());
+  DCHECK(reset_cb_.is_null());
 
   weak_this_ = weak_factory_.GetWeakPtr();
   init_cb_ = BindToCurrentLoop(status_cb);
+  output_cb_ = BindToCurrentLoop(output_cb);
 
-  const AudioDecoderConfig& config = stream->audio_decoder_config();
   if (!config.IsValidConfig()) {
     DLOG(ERROR) << "Invalid audio stream config.";
     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE);
@@ -74,46 +72,53 @@ void DecryptingAudioDecoder::Initialize(
     return;
   }
 
-  DCHECK(!demuxer_stream_);
-  demuxer_stream_ = stream;
-  statistics_cb_ = statistics_cb;
+  config_ = config;
+
+  if (state_ == kUninitialized) {
+    state_ = kDecryptorRequested;
+    set_decryptor_ready_cb_.Run(BindToCurrentLoop(
+        base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
+    return;
+  }
 
-  state_ = kDecryptorRequested;
-  set_decryptor_ready_cb_.Run(BindToCurrentLoop(
-      base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
+  // Reinitialization (i.e. upon a config change)
+  decryptor_->DeinitializeDecoder(Decryptor::kAudio);
+  InitializeDecoder();
 }
 
-void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
-  DVLOG(3) << "Read()";
+void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
+                                    const DecodeCB& decode_cb) {
+  DVLOG(3) << "Decode()";
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
-  DCHECK(!read_cb.is_null());
-  CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
+  DCHECK(!decode_cb.is_null());
+  CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
 
-  read_cb_ = BindToCurrentLoop(read_cb);
+  decode_cb_ = BindToCurrentLoop(decode_cb);
 
   // Return empty (end-of-stream) frames if decoding has finished.
   if (state_ == kDecodeFinished) {
-    base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer());
+    output_cb_.Run(AudioBuffer::CreateEOSBuffer());
+    base::ResetAndReturn(&decode_cb_).Run(kOk);
     return;
   }
 
-  if (!queued_audio_frames_.empty()) {
-    base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
-    queued_audio_frames_.pop_front();
-    return;
+  // Initialize the |next_output_timestamp_| to be the timestamp of the first
+  // non-EOS buffer.
+  if (timestamp_helper_->base_timestamp() == kNoTimestamp() &&
+      !buffer->end_of_stream()) {
+    timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
   }
 
-  state_ = kPendingDemuxerRead;
-  ReadFromDemuxerStream();
+  pending_buffer_to_decode_ = buffer;
+  state_ = kPendingDecode;
+  DecodePendingBuffer();
 }
 
 void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
   DVLOG(2) << "Reset() - state: " << state_;
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(state_ == kIdle ||
-         state_ == kPendingConfigChange ||
-         state_ == kPendingDemuxerRead ||
          state_ == kPendingDecode ||
          state_ == kWaitingForKey ||
          state_ == kDecodeFinished) << state_;
@@ -128,30 +133,27 @@ void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
   // Defer the resetting process in this case. The |reset_cb_| will be fired
   // after the read callback is fired - see DecryptAndDecodeBuffer() and
   // DeliverFrame().
-  if (state_ == kPendingConfigChange ||
-      state_ == kPendingDemuxerRead ||
-      state_ == kPendingDecode) {
-    DCHECK(!read_cb_.is_null());
+  if (state_ == kPendingDecode) {
+    DCHECK(!decode_cb_.is_null());
     return;
   }
 
   if (state_ == kWaitingForKey) {
-    DCHECK(!read_cb_.is_null());
+    DCHECK(!decode_cb_.is_null());
     pending_buffer_to_decode_ = NULL;
-    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
+    base::ResetAndReturn(&decode_cb_).Run(kAborted);
   }
 
-  DCHECK(read_cb_.is_null());
+  DCHECK(decode_cb_.is_null());
   DoReset();
 }
 
-void DecryptingAudioDecoder::Stop(const base::Closure& closure) {
-  DVLOG(2) << "Stop() - state: " << state_;
+DecryptingAudioDecoder::~DecryptingAudioDecoder() {
+  DVLOG(2) << __FUNCTION__;
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  // Invalidate all weak pointers so that pending callbacks won't be fired into
-  // this object.
-  weak_factory_.InvalidateWeakPtrs();
+  if (state_ == kUninitialized)
+    return;
 
   if (decryptor_) {
     decryptor_->DeinitializeDecoder(Decryptor::kAudio);
@@ -162,35 +164,15 @@ void DecryptingAudioDecoder::Stop(const base::Closure& closure) {
   pending_buffer_to_decode_ = NULL;
   if (!init_cb_.is_null())
     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
-  if (!read_cb_.is_null())
-    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
+  if (!decode_cb_.is_null())
+    base::ResetAndReturn(&decode_cb_).Run(kAborted);
   if (!reset_cb_.is_null())
     base::ResetAndReturn(&reset_cb_).Run();
-
-  state_ = kStopped;
-  task_runner_->PostTask(FROM_HERE, closure);
 }
 
-int DecryptingAudioDecoder::bits_per_channel() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return bits_per_channel_;
-}
-
-ChannelLayout DecryptingAudioDecoder::channel_layout() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return channel_layout_;
-}
-
-int DecryptingAudioDecoder::samples_per_second() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return samples_per_second_;
-}
-
-DecryptingAudioDecoder::~DecryptingAudioDecoder() {
-  DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
-}
-
-void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
+void DecryptingAudioDecoder::SetDecryptor(
+    Decryptor* decryptor,
+    const DecryptorAttachedCB& decryptor_attached_cb) {
   DVLOG(2) << "SetDecryptor()";
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK_EQ(state_, kDecryptorRequested) << state_;
@@ -201,30 +183,21 @@ void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
 
   if (!decryptor) {
     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
-    // TODO(xhwang): Add kError state. See http://crbug.com/251503
-    state_ = kStopped;
+    state_ = kError;
+    decryptor_attached_cb.Run(false);
     return;
   }
 
   decryptor_ = decryptor;
 
-  const AudioDecoderConfig& input_config =
-      demuxer_stream_->audio_decoder_config();
-  AudioDecoderConfig config;
-  config.Initialize(input_config.codec(),
-                    kSampleFormatS16,
-                    input_config.channel_layout(),
-                    input_config.samples_per_second(),
-                    input_config.extra_data(),
-                    input_config.extra_data_size(),
-                    input_config.is_encrypted(),
-                    false,
-                    base::TimeDelta(),
-                    base::TimeDelta());
+  InitializeDecoder();
+  decryptor_attached_cb.Run(true);
+}
 
+void DecryptingAudioDecoder::InitializeDecoder() {
   state_ = kPendingDecoderInit;
   decryptor_->InitializeAudioDecoder(
-      config,
+      config_,
       BindToCurrentLoop(base::Bind(
           &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
 }
@@ -232,19 +205,21 @@ void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
 void DecryptingAudioDecoder::FinishInitialization(bool success) {
   DVLOG(2) << "FinishInitialization()";
   DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK_EQ(state_, kPendingDecoderInit) << state_;
+  DCHECK(state_ == kPendingDecoderInit) << state_;
   DCHECK(!init_cb_.is_null());
   DCHECK(reset_cb_.is_null());  // No Reset() before initialization finished.
-  DCHECK(read_cb_.is_null());  // No Read() before initialization finished.
+  DCHECK(decode_cb_.is_null());  // No Decode() before initialization finished.
 
   if (!success) {
     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
-    state_ = kStopped;
+    decryptor_ = NULL;
+    state_ = kError;
     return;
   }
 
   // Success!
-  UpdateDecoderConfig();
+  timestamp_helper_.reset(
+      new AudioTimestampHelper(config_.samples_per_second()));
 
   decryptor_->RegisterNewKeyCB(
       Decryptor::kAudio,
@@ -255,102 +230,6 @@ void DecryptingAudioDecoder::FinishInitialization(bool success) {
   base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
 }
 
-void DecryptingAudioDecoder::FinishConfigChange(bool success) {
-  DVLOG(2) << "FinishConfigChange()";
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK_EQ(state_, kPendingConfigChange) << state_;
-  DCHECK(!read_cb_.is_null());
-
-  if (!success) {
-    base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
-    state_ = kDecodeFinished;
-    if (!reset_cb_.is_null())
-      base::ResetAndReturn(&reset_cb_).Run();
-    return;
-  }
-
-  // Config change succeeded.
-  UpdateDecoderConfig();
-
-  if (!reset_cb_.is_null()) {
-    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
-    DoReset();
-    return;
-  }
-
-  state_ = kPendingDemuxerRead;
-  ReadFromDemuxerStream();
-}
-
-void DecryptingAudioDecoder::ReadFromDemuxerStream() {
-  DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
-  DCHECK(!read_cb_.is_null());
-
-  demuxer_stream_->Read(
-      base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, weak_this_));
-}
-
-void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
-    DemuxerStream::Status status,
-    const scoped_refptr<DecoderBuffer>& buffer) {
-  DVLOG(3) << "DecryptAndDecodeBuffer()";
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
-  DCHECK(!read_cb_.is_null());
-  DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
-
-  if (status == DemuxerStream::kConfigChanged) {
-    DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
-
-  const AudioDecoderConfig& input_config =
-      demuxer_stream_->audio_decoder_config();
-  AudioDecoderConfig config;
-  config.Initialize(input_config.codec(),
-                    kSampleFormatS16,
-                    input_config.channel_layout(),
-                    input_config.samples_per_second(),
-                    input_config.extra_data(),
-                    input_config.extra_data_size(),
-                    input_config.is_encrypted(),
-                    false,
-                    base::TimeDelta(),
-                    base::TimeDelta());
-
-    state_ = kPendingConfigChange;
-    decryptor_->DeinitializeDecoder(Decryptor::kAudio);
-    decryptor_->InitializeAudioDecoder(
-        config, BindToCurrentLoop(base::Bind(
-            &DecryptingAudioDecoder::FinishConfigChange, weak_this_)));
-    return;
-  }
-
-  if (!reset_cb_.is_null()) {
-    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
-    DoReset();
-    return;
-  }
-
-  if (status == DemuxerStream::kAborted) {
-    DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
-    state_ = kIdle;
-    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
-    return;
-  }
-
-  DCHECK_EQ(status, DemuxerStream::kOk);
-
-  // Initialize the |next_output_timestamp_| to be the timestamp of the first
-  // non-EOS buffer.
-  if (timestamp_helper_->base_timestamp() == kNoTimestamp() &&
-      !buffer->end_of_stream()) {
-    timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
-  }
-
-  pending_buffer_to_decode_ = buffer;
-  state_ = kPendingDecode;
-  DecodePendingBuffer();
-}
-
 void DecryptingAudioDecoder::DecodePendingBuffer() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK_EQ(state_, kPendingDecode) << state_;
@@ -373,9 +252,8 @@ void DecryptingAudioDecoder::DeliverFrame(
   DVLOG(3) << "DeliverFrame() - status: " << status;
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK_EQ(state_, kPendingDecode) << state_;
-  DCHECK(!read_cb_.is_null());
+  DCHECK(!decode_cb_.is_null());
   DCHECK(pending_buffer_to_decode_.get());
-  DCHECK(queued_audio_frames_.empty());
 
   bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
   key_added_while_decode_pending_ = false;
@@ -385,7 +263,7 @@ void DecryptingAudioDecoder::DeliverFrame(
   pending_buffer_to_decode_ = NULL;
 
   if (!reset_cb_.is_null()) {
-    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
+    base::ResetAndReturn(&decode_cb_).Run(kAborted);
     DoReset();
     return;
   }
@@ -394,8 +272,8 @@ void DecryptingAudioDecoder::DeliverFrame(
 
   if (status == Decryptor::kError) {
     DVLOG(2) << "DeliverFrame() - kError";
-    state_ = kDecodeFinished;
-    base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
+    state_ = kDecodeFinished; // TODO add kError state
+    base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
     return;
   }
 
@@ -415,33 +293,28 @@ void DecryptingAudioDecoder::DeliverFrame(
     return;
   }
 
-  // The buffer has been accepted by the decoder, let's report statistics.
-  if (buffer_size) {
-    PipelineStatistics statistics;
-    statistics.audio_bytes_decoded = buffer_size;
-    statistics_cb_.Run(statistics);
-  }
-
   if (status == Decryptor::kNeedMoreData) {
     DVLOG(2) << "DeliverFrame() - kNeedMoreData";
-    if (scoped_pending_buffer_to_decode->end_of_stream()) {
-      state_ = kDecodeFinished;
-      base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer());
-      return;
-    }
-
-    state_ = kPendingDemuxerRead;
-    ReadFromDemuxerStream();
+    state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
+                                                              : kIdle;
+    base::ResetAndReturn(&decode_cb_).Run(kOk);
     return;
   }
 
   DCHECK_EQ(status, Decryptor::kSuccess);
   DCHECK(!frames.empty());
-  EnqueueFrames(frames);
+  ProcessDecodedFrames(frames);
+
+  if (scoped_pending_buffer_to_decode->end_of_stream()) {
+    // Set |pending_buffer_to_decode_| back as we need to keep flushing the
+    // decryptor until kNeedMoreData is returned.
+    pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
+    DecodePendingBuffer();
+    return;
+  }
 
   state_ = kIdle;
-  base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
-  queued_audio_frames_.pop_front();
+  base::ResetAndReturn(&decode_cb_).Run(kOk);
 }
 
 void DecryptingAudioDecoder::OnKeyAdded() {
@@ -460,28 +333,18 @@ void DecryptingAudioDecoder::OnKeyAdded() {
 
 void DecryptingAudioDecoder::DoReset() {
   DCHECK(init_cb_.is_null());
-  DCHECK(read_cb_.is_null());
+  DCHECK(decode_cb_.is_null());
   timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
   state_ = kIdle;
   base::ResetAndReturn(&reset_cb_).Run();
 }
 
-void DecryptingAudioDecoder::UpdateDecoderConfig() {
-  const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config();
-  bits_per_channel_ = kSupportedBitsPerChannel;
-  channel_layout_ = config.channel_layout();
-  samples_per_second_ = config.samples_per_second();
-  timestamp_helper_.reset(new AudioTimestampHelper(samples_per_second_));
-}
-
-void DecryptingAudioDecoder::EnqueueFrames(
+void DecryptingAudioDecoder::ProcessDecodedFrames(
     const Decryptor::AudioBuffers& frames) {
-  queued_audio_frames_ = frames;
-
-  for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin();
-       iter != queued_audio_frames_.end();
+  for (Decryptor::AudioBuffers::const_iterator iter = frames.begin();
+       iter != frames.end();
        ++iter) {
-    scoped_refptr<AudioBuffer>& frame = *iter;
+    scoped_refptr<AudioBuffer> frame = *iter;
 
     DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
     DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
@@ -495,9 +358,9 @@ void DecryptingAudioDecoder::EnqueueFrames(
     }
 
     frame->set_timestamp(current_time);
-    frame->set_duration(
-        timestamp_helper_->GetFrameDuration(frame->frame_count()));
     timestamp_helper_->AddFrames(frame->frame_count());
+
+    output_cb_.Run(frame);
   }
 }