text: // Copyright 2014 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef MEDIA_FILTERS_DECODER_SELECTOR_H_
  #define MEDIA_FILTERS_DECODER_SELECTOR_H_
  
  #include <memory>
  
  #include "base/callback.h"
  #include "base/macros.h"
  #include "base/memory/ref_counted.h"
  #include "base/memory/scoped_vector.h"
  #include "base/memory/weak_ptr.h"
  #include "build/build_config.h"
  #include "media/base/demuxer_stream.h"
  #include "media/base/pipeline_status.h"
  #include "media/filters/decoder_stream_traits.h"
  
  namespace base {
  class SingleThreadTaskRunner;
  }
  
  namespace media {
  
  class CdmContext;
  class DecoderBuffer;
  class DecryptingDemuxerStream;
  class MediaLog;
  
  // DecoderSelector (creates if necessary and) initializes the proper
  // Decoder for a given DemuxerStream. If the given DemuxerStream is
  // encrypted, a DecryptingDemuxerStream may also be created.
  // The template parameter |StreamType| is the type of stream we will be
  // selecting a decoder for.
  template<DemuxerStream::Type StreamType>
  class MEDIA_EXPORT DecoderSelector {
   public:
    typedef DecoderStreamTraits<StreamType> StreamTraits;
    typedef typename StreamTraits::DecoderType Decoder;
  
    // Indicates completion of Decoder selection.
    // - First parameter: The initialized Decoder. If it's set to NULL, then
    // Decoder initialization failed.
    // - Second parameter: The initialized DecryptingDemuxerStream. If it's not
    // NULL, then a DecryptingDemuxerStream is created and initialized to do
    // decryption for the initialized Decoder.
    // Note: The caller owns selected Decoder and DecryptingDemuxerStream.
    // The caller should call DecryptingDemuxerStream::Reset() before
    // calling Decoder::Reset() to release any pending decryption or read.
    typedef base::Callback<void(std::unique_ptr<Decoder>,
                                std::unique_ptr<DecryptingDemuxerStream>)>
        SelectDecoderCB;
  
    // |decoders| contains the Decoders to use when initializing.
    DecoderSelector(
        const scoped_refptr<base::SingleThreadTaskRunner>& message_loop,
        ScopedVector<Decoder> decoders,
        const scoped_refptr<MediaLog>& media_log);
  
    // Aborts pending Decoder selection and fires |select_decoder_cb| with
    // NULL and NULL immediately if it's pending.
    ~DecoderSelector();
  
    // Initializes and selects the first Decoder that can decode the |stream|.
    // The selected Decoder (and DecryptingDemuxerStream) is returned via
    // the |select_decoder_cb|.
    // Notes:
    // 1. This must not be called again before |select_decoder_cb| is run.
    // 2. Decoders that fail to initialize will be deleted. Future calls will
    //    select from the decoders following the decoder that was last returned.
    // 3. |cdm_context| is optional. If |cdm_context| is
    //    null, no CDM will be available to perform decryption.
    void SelectDecoder(StreamTraits* traits,
                       DemuxerStream* stream,
                       CdmContext* cdm_context,
                       const SelectDecoderCB& select_decoder_cb,
                       const typename Decoder::OutputCB& output_cb,
                       const base::Closure& waiting_for_decryption_key_cb);
  
   private:
  #if !defined(OS_ANDROID)
    void InitializeDecryptingDecoder();
    void DecryptingDecoderInitDone(bool success);
  #endif
    void InitializeDecryptingDemuxerStream();
    void DecryptingDemuxerStreamInitDone(PipelineStatus status);
    void InitializeDecoder();
    void DecoderInitDone(bool success);
    void ReturnNullDecoder();
  
    scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
    ScopedVector<Decoder> decoders_;
    scoped_refptr<MediaLog> media_log_;
  
    StreamTraits* traits_;
    DemuxerStream* input_stream_;
    CdmContext* cdm_context_;
    SelectDecoderCB select_decoder_cb_;
    typename Decoder::OutputCB output_cb_;
    base::Closure waiting_for_decryption_key_cb_;
  
    std::unique_ptr<Decoder> decoder_;
    std::unique_ptr<DecryptingDemuxerStream> decrypted_stream_;
  
    // NOTE: Weak pointers must be invalidated before all other member variables.
    base::WeakPtrFactory<DecoderSelector> weak_ptr_factory_;
  
    DISALLOW_IMPLICIT_CONSTRUCTORS(DecoderSelector);
  };
  
  typedef DecoderSelector<DemuxerStream::VIDEO> VideoDecoderSelector;
  typedef DecoderSelector<DemuxerStream::AUDIO> AudioDecoderSelector;
  
  }  // namespace media
  
  #endif  // MEDIA_FILTERS_DECODER_SELECTOR_H_
  