Home | History | Annotate | Download | only in android
      1 // Copyright 2013 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 #ifndef MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
      6 #define MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
      7 
      8 #include "base/callback.h"
      9 #include "base/memory/weak_ptr.h"
     10 #include "base/time/time.h"
     11 #include "media/base/android/demuxer_stream_player_params.h"
     12 #include "media/base/android/media_codec_bridge.h"
     13 #include "ui/gl/android/scoped_java_surface.h"
     14 
     15 namespace base {
     16 class SingleThreadTaskRunner;
     17 }
     18 
     19 namespace media {
     20 
     21 class MediaDrmBridge;
     22 
     23 // Class for managing all the decoding tasks. Each decoding task will be posted
     24 // onto the same thread. The thread will be stopped once Stop() is called.
     25 // Data is stored in 2 chunks. When new data arrives, it is always stored in
     26 // an inactive chunk. And when the current active chunk becomes empty, a new
     27 // data request will be sent to the renderer.
     28 class MediaDecoderJob {
     29  public:
     30   struct Deleter {
     31     inline void operator()(MediaDecoderJob* ptr) const { ptr->Release(); }
     32   };
     33 
     34   // Callback when a decoder job finishes its work. Args: whether decode
     35   // finished successfully, current presentation time, max presentation time.
     36   // If the current presentation time is equal to kNoTimestamp(), the decoder
     37   // job skipped rendering of the decoded output and the callback target should
     38   // ignore the timestamps provided.
     39   typedef base::Callback<void(MediaCodecStatus, base::TimeDelta,
     40                               base::TimeDelta)> DecoderCallback;
     41   // Callback when a decoder job finishes releasing the output buffer.
     42   // Args: current presentation time, max presentation time.
     43   // If the current presentation time is equal to kNoTimestamp(), the callback
     44   // target should ignore the timestamps provided.
     45   typedef base::Callback<void(base::TimeDelta, base::TimeDelta)>
     46       ReleaseOutputCompletionCallback;
     47 
     48   virtual ~MediaDecoderJob();
     49 
     50   // Called by MediaSourcePlayer when more data for this object has arrived.
     51   void OnDataReceived(const DemuxerData& data);
     52 
     53   // Prefetch so we know the decoder job has data when we call Decode().
     54   // |prefetch_cb| - Run when prefetching has completed.
     55   void Prefetch(const base::Closure& prefetch_cb);
     56 
     57   // Called by MediaSourcePlayer to decode some data.
     58   // |callback| - Run when decode operation has completed.
     59   //
     60   // Returns true if the next decode was started and |callback| will be
     61   // called when the decode operation is complete.
     62   // Returns false if |media_codec_bridge_| cannot be created; |callback| is
     63   // ignored and will not be called.
     64   bool Decode(base::TimeTicks start_time_ticks,
     65               base::TimeDelta start_presentation_timestamp,
     66               const DecoderCallback& callback);
     67 
     68   // Called to stop the last Decode() early.
     69   // If the decoder is in the process of decoding the next frame, then
     70   // this method will just allow the decode to complete as normal. If
     71   // this object is waiting for a data request to complete, then this method
     72   // will wait for the data to arrive and then call the |callback|
     73   // passed to Decode() with a status of MEDIA_CODEC_STOPPED. This ensures that
     74   // the |callback| passed to Decode() is always called and the status
     75   // reflects whether data was actually decoded or the decode terminated early.
     76   void StopDecode();
     77 
     78   // Flushes the decoder and abandons all the data that is being decoded.
     79   virtual void Flush();
     80 
     81   // Enters prerolling state. The job must not currently be decoding.
     82   void BeginPrerolling(base::TimeDelta preroll_timestamp);
     83 
     84   // Releases all the decoder resources as the current tab is going background.
     85   virtual void ReleaseDecoderResources();
     86 
     87   // Sets the demuxer configs. Returns true if configs has changed, or false
     88   // otherwise.
     89   bool SetDemuxerConfigs(const DemuxerConfigs& configs);
     90 
     91   // Returns whether the decoder has finished decoding all the data.
     92   bool OutputEOSReached() const;
     93 
     94   // Returns true if the audio/video stream is available, implemented by child
     95   // classes.
     96   virtual bool HasStream() const = 0;
     97 
     98   void SetDrmBridge(MediaDrmBridge* drm_bridge);
     99 
    100   bool is_decoding() const { return !decode_cb_.is_null(); }
    101 
    102   bool is_content_encrypted() const { return is_content_encrypted_; }
    103 
    104  protected:
    105   // Creates a new MediaDecoderJob instance.
    106   // |decoder_task_runner| - Thread on which the decoder task will run.
    107   // |request_data_cb| - Callback to request more data for the decoder.
    108   // |config_changed_cb| - Callback to inform the caller that
    109   // demuxer config has changed.
    110   MediaDecoderJob(
    111       const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner,
    112       const base::Closure& request_data_cb,
    113       const base::Closure& config_changed_cb);
    114 
    115   // Release the output buffer at index |output_buffer_index| and render it if
    116   // |render_output| is true. Upon completion, |callback| will be called.
    117   virtual void ReleaseOutputBuffer(
    118       int output_buffer_index,
    119       size_t size,
    120       bool render_output,
    121       base::TimeDelta current_presentation_timestamp,
    122       const ReleaseOutputCompletionCallback& callback) = 0;
    123 
    124   // Returns true if the "time to render" needs to be computed for frames in
    125   // this decoder job.
    126   virtual bool ComputeTimeToRender() const = 0;
    127 
    128   // Gets MediaCrypto object from |drm_bridge_|.
    129   base::android::ScopedJavaLocalRef<jobject> GetMediaCrypto();
    130 
    131   // Releases the |media_codec_bridge_|.
    132   void ReleaseMediaCodecBridge();
    133 
    134   MediaDrmBridge* drm_bridge() { return drm_bridge_; }
    135 
    136   void set_is_content_encrypted(bool is_content_encrypted) {
    137     is_content_encrypted_ = is_content_encrypted;
    138   }
    139 
    140   bool need_to_reconfig_decoder_job_;
    141 
    142   scoped_ptr<MediaCodecBridge> media_codec_bridge_;
    143 
    144  private:
    145   friend class MediaSourcePlayerTest;
    146 
    147   // Causes this instance to be deleted on the thread it is bound to.
    148   void Release();
    149 
    150   // Queues an access unit into |media_codec_bridge_|'s input buffer.
    151   MediaCodecStatus QueueInputBuffer(const AccessUnit& unit);
    152 
    153   // Returns true if this object has data to decode.
    154   bool HasData() const;
    155 
    156   // Initiates a request for more data.
    157   // |done_cb| is called when more data is available in |received_data_|.
    158   void RequestData(const base::Closure& done_cb);
    159 
    160   // Posts a task to start decoding the current access unit in |received_data_|.
    161   void DecodeCurrentAccessUnit(
    162       base::TimeTicks start_time_ticks,
    163       base::TimeDelta start_presentation_timestamp);
    164 
    165   // Helper function to decode data on |decoder_task_runner_|. |unit| contains
    166   // the data to be decoded. |start_time_ticks| and
    167   // |start_presentation_timestamp| represent the system time and the
    168   // presentation timestamp when the first frame is rendered. We use these
    169   // information to estimate when the current frame should be rendered.
    170   // If |needs_flush| is true, codec needs to be flushed at the beginning of
    171   // this call.
    172   // It is possible that |stop_decode_pending_| or |release_resources_pending_|
    173   // becomes true while DecodeInternal() is called. However, they should have
    174   // no impact on DecodeInternal(). They will be handled after DecoderInternal()
    175   // finishes and OnDecodeCompleted() is posted on the UI thread.
    176   void DecodeInternal(const AccessUnit& unit,
    177                       base::TimeTicks start_time_ticks,
    178                       base::TimeDelta start_presentation_timestamp,
    179                       bool needs_flush,
    180                       const DecoderCallback& callback);
    181 
    182   // Called on the UI thread to indicate that one decode cycle has completed.
    183   // Completes any pending job destruction or any pending decode stop. If
    184   // destruction was not pending, passes its arguments to |decode_cb_|.
    185   void OnDecodeCompleted(MediaCodecStatus status,
    186                          base::TimeDelta current_presentation_timestamp,
    187                          base::TimeDelta max_presentation_timestamp);
    188 
    189   // Helper function to get the current access unit that is being decoded.
    190   const AccessUnit& CurrentAccessUnit() const;
    191 
    192   // Helper function to get the current data chunk index that is being decoded.
    193   size_t CurrentReceivedDataChunkIndex() const;
    194 
    195   // Check whether a chunk has no remaining access units to decode. If
    196   // |is_active_chunk| is true, this function returns whether decoder has
    197   // consumed all data in |received_data_[current_demuxer_data_index_]|.
    198   // Otherwise, it returns whether decoder has consumed all data in the inactive
    199   // chunk.
    200   bool NoAccessUnitsRemainingInChunk(bool is_active_chunk) const;
    201 
    202   // Requests new data for the current chunk if it runs out of data.
    203   void RequestCurrentChunkIfEmpty();
    204 
    205   // Initializes |received_data_| and |access_unit_index_|.
    206   void InitializeReceivedData();
    207 
    208   // Called when the decoder is completely drained and is ready to be released.
    209   void OnDecoderDrained();
    210 
    211   // Creates |media_codec_bridge_| for decoding purpose. Returns true if it is
    212   // created, or false otherwise.
    213   bool CreateMediaCodecBridge();
    214 
    215   // Called when an access unit is consumed by the decoder. |is_config_change|
    216   // indicates whether the current access unit is a config change. If it is
    217   // true, the next access unit is guarateed to be an I-frame.
    218   virtual void CurrentDataConsumed(bool is_config_change) {}
    219 
    220   // Called when |media_codec_bridge_| is released
    221   virtual void OnMediaCodecBridgeReleased() {}
    222 
    223   // Implemented by the child class to create |media_codec_bridge_| for a
    224   // particular stream. Returns true if it is created, or false otherwise.
    225   virtual bool CreateMediaCodecBridgeInternal() = 0;
    226 
    227   // Returns true if the |configs| doesn't match the current demuxer configs
    228   // the decoder job has.
    229   virtual bool AreDemuxerConfigsChanged(
    230       const DemuxerConfigs& configs) const = 0;
    231 
    232   // Updates the demuxer configs.
    233   virtual void UpdateDemuxerConfigs(const DemuxerConfigs& configs) = 0;
    234 
    235   // Returns true if |media_codec_bridge_| needs to be reconfigured for the
    236   // new DemuxerConfigs, or false otherwise.
    237   virtual bool IsCodecReconfigureNeeded(const DemuxerConfigs& configs) const;
    238 
    239   // Return the index to |received_data_| that is not currently being decoded.
    240   size_t inactive_demuxer_data_index() const {
    241     return 1 - current_demuxer_data_index_;
    242   }
    243 
    244   // The UI message loop where callbacks should be dispatched.
    245   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
    246 
    247   // The task runner that decoder job runs on.
    248   scoped_refptr<base::SingleThreadTaskRunner> decoder_task_runner_;
    249 
    250   // Whether the decoder needs to be flushed.
    251   bool needs_flush_;
    252 
    253   // Whether input EOS is encountered.
    254   // TODO(wolenetz/qinmin): Protect with a lock. See http://crbug.com/320043.
    255   bool input_eos_encountered_;
    256 
    257   // Whether output EOS is encountered.
    258   bool output_eos_encountered_;
    259 
    260   // Tracks whether DecodeInternal() should skip decoding if the first access
    261   // unit is EOS or empty, and report |MEDIA_CODEC_OUTPUT_END_OF_STREAM|. This
    262   // is to work around some decoders that could crash otherwise. See
    263   // http://b/11696552.
    264   bool skip_eos_enqueue_;
    265 
    266   // The timestamp the decoder needs to preroll to. If an access unit's
    267   // timestamp is smaller than |preroll_timestamp_|, don't render it.
    268   // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_|
    269   // is not very accurate.
    270   base::TimeDelta preroll_timestamp_;
    271 
    272   // Indicates prerolling state. If true, this job has not yet decoded output
    273   // that it will render, since the most recent of job construction or
    274   // BeginPrerolling(). If false, |preroll_timestamp_| has been reached.
    275   // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_|
    276   // is not very accurate.
    277   bool prerolling_;
    278 
    279   // Callback used to request more data.
    280   base::Closure request_data_cb_;
    281 
    282   // Callback to notify the caller config has changed.
    283   base::Closure config_changed_cb_;
    284 
    285   // Callback to run when new data has been received.
    286   base::Closure data_received_cb_;
    287 
    288   // Callback to run when the current Decode() operation completes.
    289   DecoderCallback decode_cb_;
    290 
    291   // Data received over IPC from last RequestData() operation.
    292   // We keep 2 chunks at the same time to reduce the IPC latency between chunks.
    293   // If data inside the current chunk are all decoded, we will request a new
    294   // chunk from the demuxer and swap the current chunk with the other one.
    295   // New data will always be stored in the other chunk since the current
    296   // one may be still in use.
    297   DemuxerData received_data_[2];
    298 
    299   // Index to the current data chunk that is being decoded.
    300   size_t current_demuxer_data_index_;
    301 
    302   // Index to the access unit inside each data chunk that is being decoded.
    303   size_t access_unit_index_[2];
    304 
    305   // The index of input buffer that can be used by QueueInputBuffer().
    306   // If the index is uninitialized or invalid, it must be -1.
    307   int input_buf_index_;
    308 
    309   // Indicates whether content is encrypted.
    310   bool is_content_encrypted_;
    311 
    312   // Indicates the decoder job should stop after decoding the current access
    313   // unit.
    314   bool stop_decode_pending_;
    315 
    316   // Indicates that this object should be destroyed once the current
    317   // Decode() has completed. This gets set when Release() gets called
    318   // while there is a decode in progress.
    319   bool destroy_pending_;
    320 
    321   // Indicates whether the decoder is in the middle of requesting new data.
    322   bool is_requesting_demuxer_data_;
    323 
    324   // Indicates whether the incoming data should be ignored.
    325   bool is_incoming_data_invalid_;
    326 
    327   // Indicates that |media_codec_bridge_| should be released once the current
    328   // Decode() has completed. This gets set when ReleaseDecoderResources() gets
    329   // called while there is a decode in progress.
    330   bool release_resources_pending_;
    331 
    332   // Pointer to a DRM object that will be used for encrypted streams.
    333   MediaDrmBridge* drm_bridge_;
    334 
    335   // Indicates whether |media_codec_bridge_| is in the middle of being drained
    336   // due to a config change.
    337   bool drain_decoder_;
    338 
    339   // This access unit is passed to the decoder during config changes to drain
    340   // the decoder.
    341   AccessUnit eos_unit_;
    342 
    343   DISALLOW_IMPLICIT_CONSTRUCTORS(MediaDecoderJob);
    344 };
    345 
    346 }  // namespace media
    347 
    348 #endif  // MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
    349