Home | History | Annotate | Download | only in filters
      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/audio_decoder_selector.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "base/logging.h"
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "media/base/audio_decoder_config.h"
     12 #include "media/base/bind_to_loop.h"
     13 #include "media/base/demuxer_stream.h"
     14 #include "media/base/pipeline.h"
     15 #include "media/filters/decrypting_audio_decoder.h"
     16 #include "media/filters/decrypting_demuxer_stream.h"
     17 
     18 namespace media {
     19 
     20 AudioDecoderSelector::AudioDecoderSelector(
     21     const scoped_refptr<base::MessageLoopProxy>& message_loop,
     22     ScopedVector<AudioDecoder> decoders,
     23     const SetDecryptorReadyCB& set_decryptor_ready_cb)
     24     : message_loop_(message_loop),
     25       decoders_(decoders.Pass()),
     26       set_decryptor_ready_cb_(set_decryptor_ready_cb),
     27       input_stream_(NULL),
     28       weak_ptr_factory_(this) {
     29 }
     30 
     31 AudioDecoderSelector::~AudioDecoderSelector() {
     32   DVLOG(2) << __FUNCTION__;
     33 }
     34 
     35 void AudioDecoderSelector::SelectAudioDecoder(
     36     DemuxerStream* stream,
     37     const StatisticsCB& statistics_cb,
     38     const SelectDecoderCB& select_decoder_cb) {
     39   DVLOG(2) << __FUNCTION__;
     40   DCHECK(message_loop_->BelongsToCurrentThread());
     41   DCHECK(stream);
     42 
     43   // Make sure |select_decoder_cb| runs on a different execution stack.
     44   select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
     45 
     46   const AudioDecoderConfig& config = stream->audio_decoder_config();
     47   if (!config.IsValidConfig()) {
     48     DLOG(ERROR) << "Invalid audio stream config.";
     49     ReturnNullDecoder();
     50     return;
     51   }
     52 
     53   input_stream_ = stream;
     54   statistics_cb_ = statistics_cb;
     55 
     56   if (!config.is_encrypted()) {
     57     InitializeDecoder();
     58     return;
     59   }
     60 
     61   // This could happen if Encrypted Media Extension (EME) is not enabled.
     62   if (set_decryptor_ready_cb_.is_null()) {
     63     ReturnNullDecoder();
     64     return;
     65   }
     66 
     67   audio_decoder_.reset(new DecryptingAudioDecoder(
     68       message_loop_, set_decryptor_ready_cb_));
     69 
     70   audio_decoder_->Initialize(
     71       input_stream_,
     72       base::Bind(&AudioDecoderSelector::DecryptingAudioDecoderInitDone,
     73                  weak_ptr_factory_.GetWeakPtr()),
     74       statistics_cb_);
     75 }
     76 
     77 void AudioDecoderSelector::Abort() {
     78   DVLOG(2) << __FUNCTION__;
     79   DCHECK(message_loop_->BelongsToCurrentThread());
     80 
     81   // This could happen when SelectAudioDecoder() was not called or when
     82   // |select_decoder_cb_| was already posted but not fired (e.g. in the
     83   // message loop queue).
     84   if (select_decoder_cb_.is_null())
     85     return;
     86 
     87   // We must be trying to initialize the |audio_decoder_| or the
     88   // |decrypted_stream_|. Invalid all weak pointers so that all initialization
     89   // callbacks won't fire.
     90   weak_ptr_factory_.InvalidateWeakPtrs();
     91 
     92   if (audio_decoder_) {
     93     // AudioDecoder doesn't provide a Stop() method. Also, |decrypted_stream_|
     94     // is either NULL or already initialized. We don't need to Stop()
     95     // |decrypted_stream_| in either case.
     96     ReturnNullDecoder();
     97     return;
     98   }
     99 
    100   if (decrypted_stream_) {
    101     decrypted_stream_->Stop(
    102         base::Bind(&AudioDecoderSelector::ReturnNullDecoder,
    103                    weak_ptr_factory_.GetWeakPtr()));
    104     return;
    105   }
    106 
    107   NOTREACHED();
    108 }
    109 
    110 void AudioDecoderSelector::DecryptingAudioDecoderInitDone(
    111     PipelineStatus status) {
    112   DVLOG(2) << __FUNCTION__;
    113   DCHECK(message_loop_->BelongsToCurrentThread());
    114 
    115   if (status == PIPELINE_OK) {
    116     base::ResetAndReturn(&select_decoder_cb_).Run(
    117         audio_decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
    118     return;
    119   }
    120 
    121   audio_decoder_.reset();
    122 
    123   decrypted_stream_.reset(new DecryptingDemuxerStream(
    124       message_loop_, set_decryptor_ready_cb_));
    125 
    126   decrypted_stream_->Initialize(
    127       input_stream_,
    128       base::Bind(&AudioDecoderSelector::DecryptingDemuxerStreamInitDone,
    129                  weak_ptr_factory_.GetWeakPtr()));
    130 }
    131 
    132 void AudioDecoderSelector::DecryptingDemuxerStreamInitDone(
    133     PipelineStatus status) {
    134   DVLOG(2) << __FUNCTION__;
    135   DCHECK(message_loop_->BelongsToCurrentThread());
    136 
    137   if (status != PIPELINE_OK) {
    138     ReturnNullDecoder();
    139     return;
    140   }
    141 
    142   DCHECK(!decrypted_stream_->audio_decoder_config().is_encrypted());
    143   input_stream_ = decrypted_stream_.get();
    144   InitializeDecoder();
    145 }
    146 
    147 void AudioDecoderSelector::InitializeDecoder() {
    148   DVLOG(2) << __FUNCTION__;
    149   DCHECK(message_loop_->BelongsToCurrentThread());
    150   DCHECK(!audio_decoder_);
    151 
    152   if (decoders_.empty()) {
    153     ReturnNullDecoder();
    154     return;
    155   }
    156 
    157   audio_decoder_.reset(decoders_.front());
    158   decoders_.weak_erase(decoders_.begin());
    159 
    160   audio_decoder_->Initialize(input_stream_,
    161                              base::Bind(&AudioDecoderSelector::DecoderInitDone,
    162                                         weak_ptr_factory_.GetWeakPtr()),
    163                              statistics_cb_);
    164 }
    165 
    166 void AudioDecoderSelector::DecoderInitDone(PipelineStatus status) {
    167   DVLOG(2) << __FUNCTION__;
    168   DCHECK(message_loop_->BelongsToCurrentThread());
    169 
    170   if (status != PIPELINE_OK) {
    171     audio_decoder_.reset();
    172     InitializeDecoder();
    173     return;
    174   }
    175 
    176   base::ResetAndReturn(&select_decoder_cb_).Run(audio_decoder_.Pass(),
    177                                                 decrypted_stream_.Pass());
    178 }
    179 
    180 void AudioDecoderSelector::ReturnNullDecoder() {
    181   DVLOG(2) << __FUNCTION__;
    182   DCHECK(message_loop_->BelongsToCurrentThread());
    183   base::ResetAndReturn(&select_decoder_cb_).Run(
    184       scoped_ptr<AudioDecoder>(), scoped_ptr<DecryptingDemuxerStream>());
    185 }
    186 
    187 }  // namespace media
    188