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(task_runner_->BelongsToCurrentThread());
     66 
     67   if (!select_decoder_cb_.is_null())
     68     ReturnNullDecoder();
     69 
     70   decoder_.reset();
     71   decrypted_stream_.reset();
     72 }
     73 
     74 template <DemuxerStream::Type StreamType>
     75 void DecoderSelector<StreamType>::SelectDecoder(
     76     DemuxerStream* stream,
     77     bool low_delay,
     78     const SelectDecoderCB& select_decoder_cb,
     79     const typename Decoder::OutputCB& output_cb) {
     80   DVLOG(2) << __FUNCTION__;
     81   DCHECK(task_runner_->BelongsToCurrentThread());
     82   DCHECK(stream);
     83 
     84   // Make sure |select_decoder_cb| runs on a different execution stack.
     85   select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
     86 
     87   if (!HasValidStreamConfig(stream)) {
     88     DLOG(ERROR) << "Invalid stream config.";
     89     ReturnNullDecoder();
     90     return;
     91   }
     92 
     93   input_stream_ = stream;
     94   low_delay_ = low_delay;
     95   output_cb_ = output_cb;
     96 
     97   if (!IsStreamEncrypted(input_stream_)) {
     98     InitializeDecoder();
     99     return;
    100   }
    101 
    102   // This could happen if Encrypted Media Extension (EME) is not enabled.
    103   if (set_decryptor_ready_cb_.is_null()) {
    104     ReturnNullDecoder();
    105     return;
    106   }
    107 
    108   decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
    109       task_runner_, set_decryptor_ready_cb_));
    110 
    111   DecoderStreamTraits<StreamType>::Initialize(
    112       decoder_.get(),
    113       StreamTraits::GetDecoderConfig(*input_stream_),
    114       low_delay_,
    115       base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
    116                  weak_ptr_factory_.GetWeakPtr()),
    117       output_cb_);
    118 }
    119 
    120 template <DemuxerStream::Type StreamType>
    121 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
    122     PipelineStatus status) {
    123   DVLOG(2) << __FUNCTION__;
    124   DCHECK(task_runner_->BelongsToCurrentThread());
    125 
    126   if (status == PIPELINE_OK) {
    127     base::ResetAndReturn(&select_decoder_cb_)
    128         .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
    129     return;
    130   }
    131 
    132   decoder_.reset();
    133 
    134   decrypted_stream_.reset(
    135       new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_));
    136 
    137   decrypted_stream_->Initialize(
    138       input_stream_,
    139       base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
    140                  weak_ptr_factory_.GetWeakPtr()));
    141 }
    142 
    143 template <DemuxerStream::Type StreamType>
    144 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
    145     PipelineStatus status) {
    146   DVLOG(2) << __FUNCTION__;
    147   DCHECK(task_runner_->BelongsToCurrentThread());
    148 
    149   if (status != PIPELINE_OK) {
    150     ReturnNullDecoder();
    151     return;
    152   }
    153 
    154   DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
    155   input_stream_ = decrypted_stream_.get();
    156   InitializeDecoder();
    157 }
    158 
    159 template <DemuxerStream::Type StreamType>
    160 void DecoderSelector<StreamType>::InitializeDecoder() {
    161   DVLOG(2) << __FUNCTION__;
    162   DCHECK(task_runner_->BelongsToCurrentThread());
    163   DCHECK(!decoder_);
    164 
    165   if (decoders_.empty()) {
    166     ReturnNullDecoder();
    167     return;
    168   }
    169 
    170   decoder_.reset(decoders_.front());
    171   decoders_.weak_erase(decoders_.begin());
    172 
    173   DecoderStreamTraits<StreamType>::Initialize(
    174       decoder_.get(),
    175       StreamTraits::GetDecoderConfig(*input_stream_),
    176       low_delay_,
    177       base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
    178                  weak_ptr_factory_.GetWeakPtr()),
    179       output_cb_);
    180 }
    181 
    182 template <DemuxerStream::Type StreamType>
    183 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
    184   DVLOG(2) << __FUNCTION__;
    185   DCHECK(task_runner_->BelongsToCurrentThread());
    186 
    187   if (status != PIPELINE_OK) {
    188     decoder_.reset();
    189     InitializeDecoder();
    190     return;
    191   }
    192 
    193   base::ResetAndReturn(&select_decoder_cb_)
    194       .Run(decoder_.Pass(), decrypted_stream_.Pass());
    195 }
    196 
    197 template <DemuxerStream::Type StreamType>
    198 void DecoderSelector<StreamType>::ReturnNullDecoder() {
    199   DVLOG(2) << __FUNCTION__;
    200   DCHECK(task_runner_->BelongsToCurrentThread());
    201   base::ResetAndReturn(&select_decoder_cb_)
    202       .Run(scoped_ptr<Decoder>(),
    203            scoped_ptr<DecryptingDemuxerStream>());
    204 }
    205 
    206 // These forward declarations tell the compiler that we will use
    207 // DecoderSelector with these arguments, allowing us to keep these definitions
    208 // in our .cc without causing linker errors. This also means if anyone tries to
    209 // instantiate a DecoderSelector with anything but these two specializations
    210 // they'll most likely get linker errors.
    211 template class DecoderSelector<DemuxerStream::AUDIO>;
    212 template class DecoderSelector<DemuxerStream::VIDEO>;
    213 
    214 }  // namespace media
    215