Home | History | Annotate | Download | only in filters
      1 // Copyright 2014 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 "decoder_selector.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "base/logging.h"
     10 #include "base/single_thread_task_runner.h"
     11 #include "media/base/audio_decoder.h"
     12 #include "media/base/bind_to_current_loop.h"
     13 #include "media/base/demuxer_stream.h"
     14 #include "media/base/pipeline.h"
     15 #include "media/base/video_decoder.h"
     16 #include "media/filters/decoder_stream_traits.h"
     17 #include "media/filters/decrypting_audio_decoder.h"
     18 #include "media/filters/decrypting_demuxer_stream.h"
     19 #include "media/filters/decrypting_video_decoder.h"
     20 
     21 namespace media {
     22 
     23 static bool HasValidStreamConfig(DemuxerStream* stream) {
     24   switch (stream->type()) {
     25     case DemuxerStream::AUDIO:
     26       return stream->audio_decoder_config().IsValidConfig();
     27     case DemuxerStream::VIDEO:
     28       return stream->video_decoder_config().IsValidConfig();
     29     case DemuxerStream::UNKNOWN:
     30     case DemuxerStream::TEXT:
     31     case DemuxerStream::NUM_TYPES:
     32       NOTREACHED();
     33   }
     34   return false;
     35 }
     36 
     37 static bool IsStreamEncrypted(DemuxerStream* stream) {
     38   switch (stream->type()) {
     39     case DemuxerStream::AUDIO:
     40       return stream->audio_decoder_config().is_encrypted();
     41     case DemuxerStream::VIDEO:
     42       return stream->video_decoder_config().is_encrypted();
     43     case DemuxerStream::UNKNOWN:
     44     case DemuxerStream::TEXT:
     45     case DemuxerStream::NUM_TYPES:
     46       NOTREACHED();
     47   }
     48   return false;
     49 }
     50 
     51 template <DemuxerStream::Type StreamType>
     52 DecoderSelector<StreamType>::DecoderSelector(
     53     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     54     ScopedVector<Decoder> decoders,
     55     const SetDecryptorReadyCB& set_decryptor_ready_cb)
     56     : task_runner_(task_runner),
     57       decoders_(decoders.Pass()),
     58       set_decryptor_ready_cb_(set_decryptor_ready_cb),
     59       input_stream_(NULL),
     60       weak_ptr_factory_(this) {}
     61 
     62 template <DemuxerStream::Type StreamType>
     63 DecoderSelector<StreamType>::~DecoderSelector() {
     64   DVLOG(2) << __FUNCTION__;
     65   DCHECK(select_decoder_cb_.is_null());
     66 }
     67 
     68 template <DemuxerStream::Type StreamType>
     69 void DecoderSelector<StreamType>::SelectDecoder(
     70     DemuxerStream* stream,
     71     bool low_delay,
     72     const SelectDecoderCB& select_decoder_cb,
     73     const typename Decoder::OutputCB& output_cb) {
     74   DVLOG(2) << __FUNCTION__;
     75   DCHECK(task_runner_->BelongsToCurrentThread());
     76   DCHECK(stream);
     77 
     78   // Make sure |select_decoder_cb| runs on a different execution stack.
     79   select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
     80 
     81   if (!HasValidStreamConfig(stream)) {
     82     DLOG(ERROR) << "Invalid stream config.";
     83     ReturnNullDecoder();
     84     return;
     85   }
     86 
     87   input_stream_ = stream;
     88   low_delay_ = low_delay;
     89   output_cb_ = output_cb;
     90 
     91   if (!IsStreamEncrypted(input_stream_)) {
     92     InitializeDecoder();
     93     return;
     94   }
     95 
     96   // This could happen if Encrypted Media Extension (EME) is not enabled.
     97   if (set_decryptor_ready_cb_.is_null()) {
     98     ReturnNullDecoder();
     99     return;
    100   }
    101 
    102   decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
    103       task_runner_, set_decryptor_ready_cb_));
    104 
    105   DecoderStreamTraits<StreamType>::Initialize(
    106       decoder_.get(),
    107       StreamTraits::GetDecoderConfig(*input_stream_),
    108       low_delay_,
    109       base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
    110                  weak_ptr_factory_.GetWeakPtr()),
    111       output_cb_);
    112 }
    113 
    114 template <DemuxerStream::Type StreamType>
    115 void DecoderSelector<StreamType>::Abort() {
    116   DVLOG(2) << __FUNCTION__;
    117   DCHECK(task_runner_->BelongsToCurrentThread());
    118 
    119   // This could happen when SelectDecoder() was not called or when
    120   // |select_decoder_cb_| was already posted but not fired (e.g. in the
    121   // message loop queue).
    122   if (select_decoder_cb_.is_null())
    123     return;
    124 
    125   // We must be trying to initialize the |decoder_| or the
    126   // |decrypted_stream_|. Invalid all weak pointers so that all initialization
    127   // callbacks won't fire.
    128   weak_ptr_factory_.InvalidateWeakPtrs();
    129 
    130   if (decoder_) {
    131     // |decrypted_stream_| is either NULL or already initialized. We don't
    132     // need to Stop() |decrypted_stream_| in either case.
    133     decoder_->Stop();
    134     ReturnNullDecoder();
    135     return;
    136   }
    137 
    138   if (decrypted_stream_) {
    139     decrypted_stream_->Stop(
    140         base::Bind(&DecoderSelector<StreamType>::ReturnNullDecoder,
    141                    weak_ptr_factory_.GetWeakPtr()));
    142     return;
    143   }
    144 
    145   NOTREACHED();
    146 }
    147 
    148 template <DemuxerStream::Type StreamType>
    149 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
    150     PipelineStatus status) {
    151   DVLOG(2) << __FUNCTION__;
    152   DCHECK(task_runner_->BelongsToCurrentThread());
    153 
    154   if (status == PIPELINE_OK) {
    155     base::ResetAndReturn(&select_decoder_cb_)
    156         .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
    157     return;
    158   }
    159 
    160   decoder_.reset();
    161 
    162   decrypted_stream_.reset(
    163       new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_));
    164 
    165   decrypted_stream_->Initialize(
    166       input_stream_,
    167       base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
    168                  weak_ptr_factory_.GetWeakPtr()));
    169 }
    170 
    171 template <DemuxerStream::Type StreamType>
    172 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
    173     PipelineStatus status) {
    174   DVLOG(2) << __FUNCTION__;
    175   DCHECK(task_runner_->BelongsToCurrentThread());
    176 
    177   if (status != PIPELINE_OK) {
    178     ReturnNullDecoder();
    179     return;
    180   }
    181 
    182   DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
    183   input_stream_ = decrypted_stream_.get();
    184   InitializeDecoder();
    185 }
    186 
    187 template <DemuxerStream::Type StreamType>
    188 void DecoderSelector<StreamType>::InitializeDecoder() {
    189   DVLOG(2) << __FUNCTION__;
    190   DCHECK(task_runner_->BelongsToCurrentThread());
    191   DCHECK(!decoder_);
    192 
    193   if (decoders_.empty()) {
    194     ReturnNullDecoder();
    195     return;
    196   }
    197 
    198   decoder_.reset(decoders_.front());
    199   decoders_.weak_erase(decoders_.begin());
    200 
    201   DecoderStreamTraits<StreamType>::Initialize(
    202       decoder_.get(),
    203       StreamTraits::GetDecoderConfig(*input_stream_),
    204       low_delay_,
    205       base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
    206                  weak_ptr_factory_.GetWeakPtr()),
    207       output_cb_);
    208 }
    209 
    210 template <DemuxerStream::Type StreamType>
    211 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
    212   DVLOG(2) << __FUNCTION__;
    213   DCHECK(task_runner_->BelongsToCurrentThread());
    214 
    215   if (status != PIPELINE_OK) {
    216     decoder_.reset();
    217     InitializeDecoder();
    218     return;
    219   }
    220 
    221   base::ResetAndReturn(&select_decoder_cb_)
    222       .Run(decoder_.Pass(), decrypted_stream_.Pass());
    223 }
    224 
    225 template <DemuxerStream::Type StreamType>
    226 void DecoderSelector<StreamType>::ReturnNullDecoder() {
    227   DVLOG(2) << __FUNCTION__;
    228   DCHECK(task_runner_->BelongsToCurrentThread());
    229   base::ResetAndReturn(&select_decoder_cb_)
    230       .Run(scoped_ptr<Decoder>(),
    231            scoped_ptr<DecryptingDemuxerStream>());
    232 }
    233 
    234 // These forward declarations tell the compiler that we will use
    235 // DecoderSelector with these arguments, allowing us to keep these definitions
    236 // in our .cc without causing linker errors. This also means if anyone tries to
    237 // instantiate a DecoderSelector with anything but these two specializations
    238 // they'll most likely get linker errors.
    239 template class DecoderSelector<DemuxerStream::AUDIO>;
    240 template class DecoderSelector<DemuxerStream::VIDEO>;
    241 
    242 }  // namespace media
    243