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/video_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/bind_to_loop.h"
     12 #include "media/base/demuxer_stream.h"
     13 #include "media/base/pipeline.h"
     14 #include "media/base/video_decoder_config.h"
     15 #include "media/filters/decrypting_demuxer_stream.h"
     16 #include "media/filters/decrypting_video_decoder.h"
     17 
     18 namespace media {
     19 
     20 VideoDecoderSelector::VideoDecoderSelector(
     21     const scoped_refptr<base::MessageLoopProxy>& message_loop,
     22     ScopedVector<VideoDecoder> 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 VideoDecoderSelector::~VideoDecoderSelector() {}
     32 
     33 void VideoDecoderSelector::SelectVideoDecoder(
     34     DemuxerStream* stream,
     35     const SelectDecoderCB& select_decoder_cb) {
     36   DVLOG(2) << "SelectVideoDecoder()";
     37   DCHECK(message_loop_->BelongsToCurrentThread());
     38   DCHECK(stream);
     39 
     40   // Make sure |select_decoder_cb| runs on a different execution stack.
     41   select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
     42 
     43   const VideoDecoderConfig& config = stream->video_decoder_config();
     44   if (!config.IsValidConfig()) {
     45     DLOG(ERROR) << "Invalid video stream config.";
     46     base::ResetAndReturn(&select_decoder_cb_).Run(
     47         scoped_ptr<VideoDecoder>(), scoped_ptr<DecryptingDemuxerStream>());
     48     return;
     49   }
     50 
     51   input_stream_ = stream;
     52 
     53   if (!config.is_encrypted()) {
     54     InitializeDecoder(decoders_.begin());
     55     return;
     56   }
     57 
     58   // This could happen if Encrypted Media Extension (EME) is not enabled.
     59   if (set_decryptor_ready_cb_.is_null()) {
     60     base::ResetAndReturn(&select_decoder_cb_).Run(
     61         scoped_ptr<VideoDecoder>(), scoped_ptr<DecryptingDemuxerStream>());
     62     return;
     63   }
     64 
     65   video_decoder_.reset(new DecryptingVideoDecoder(
     66       message_loop_, set_decryptor_ready_cb_));
     67 
     68   video_decoder_->Initialize(
     69       input_stream_->video_decoder_config(),
     70       BindToCurrentLoop(base::Bind(
     71           &VideoDecoderSelector::DecryptingVideoDecoderInitDone,
     72           weak_ptr_factory_.GetWeakPtr())));
     73 }
     74 
     75 void VideoDecoderSelector::DecryptingVideoDecoderInitDone(
     76     PipelineStatus status) {
     77   DCHECK(message_loop_->BelongsToCurrentThread());
     78 
     79   if (status == PIPELINE_OK) {
     80     base::ResetAndReturn(&select_decoder_cb_).Run(
     81         video_decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
     82     return;
     83   }
     84 
     85   decrypted_stream_.reset(new DecryptingDemuxerStream(
     86       message_loop_, set_decryptor_ready_cb_));
     87 
     88   decrypted_stream_->Initialize(
     89       input_stream_,
     90       BindToCurrentLoop(base::Bind(
     91           &VideoDecoderSelector::DecryptingDemuxerStreamInitDone,
     92           weak_ptr_factory_.GetWeakPtr())));
     93 }
     94 
     95 void VideoDecoderSelector::DecryptingDemuxerStreamInitDone(
     96     PipelineStatus status) {
     97   DCHECK(message_loop_->BelongsToCurrentThread());
     98 
     99   if (status != PIPELINE_OK) {
    100     decrypted_stream_.reset();
    101     base::ResetAndReturn(&select_decoder_cb_).Run(
    102         scoped_ptr<VideoDecoder>(), scoped_ptr<DecryptingDemuxerStream>());
    103     return;
    104   }
    105 
    106   DCHECK(!decrypted_stream_->video_decoder_config().is_encrypted());
    107   input_stream_ = decrypted_stream_.get();
    108   InitializeDecoder(decoders_.begin());
    109 }
    110 
    111 void VideoDecoderSelector::InitializeDecoder(
    112     ScopedVector<VideoDecoder>::iterator iter) {
    113   DCHECK(message_loop_->BelongsToCurrentThread());
    114 
    115   if (iter == decoders_.end()) {
    116     base::ResetAndReturn(&select_decoder_cb_).Run(
    117         scoped_ptr<VideoDecoder>(), scoped_ptr<DecryptingDemuxerStream>());
    118     return;
    119   }
    120 
    121   (*iter)->Initialize(
    122       input_stream_->video_decoder_config(),
    123       BindToCurrentLoop(base::Bind(&VideoDecoderSelector::DecoderInitDone,
    124                                    weak_ptr_factory_.GetWeakPtr(),
    125                                    iter)));
    126 }
    127 
    128 void VideoDecoderSelector::DecoderInitDone(
    129     ScopedVector<VideoDecoder>::iterator iter, PipelineStatus status) {
    130   DCHECK(message_loop_->BelongsToCurrentThread());
    131 
    132   if (status != PIPELINE_OK) {
    133     InitializeDecoder(++iter);
    134     return;
    135   }
    136 
    137   scoped_ptr<VideoDecoder> video_decoder(*iter);
    138   decoders_.weak_erase(iter);
    139 
    140   base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder.Pass(),
    141                                                 decrypted_stream_.Pass());
    142 }
    143 
    144 }  // namespace media
    145