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 14 namespace base { 15 class MessageLoopProxy; 16 } 17 18 namespace media { 19 20 // Class for managing all the decoding tasks. Each decoding task will be posted 21 // onto the same thread. The thread will be stopped once Stop() is called. 22 class MediaDecoderJob { 23 public: 24 struct Deleter { operatorDeleter25 inline void operator()(MediaDecoderJob* ptr) const { ptr->Release(); } 26 }; 27 28 // Callback when a decoder job finishes its work. Args: whether decode 29 // finished successfully, presentation time, audio output bytes. 30 // If the presentation time is equal to kNoTimestamp(), the decoder job 31 // skipped rendering of the decoded output and the callback target should 32 // update its clock to avoid introducing extra delays to the next frame. 33 typedef base::Callback<void(MediaCodecStatus, const base::TimeDelta&, 34 size_t)> DecoderCallback; 35 // Callback when a decoder job finishes releasing the output buffer. 36 // Args: audio output bytes, must be 0 for video. 37 typedef base::Callback<void(size_t)> ReleaseOutputCompletionCallback; 38 39 virtual ~MediaDecoderJob(); 40 41 // Called by MediaSourcePlayer when more data for this object has arrived. 42 void OnDataReceived(const DemuxerData& data); 43 44 // Prefetch so we know the decoder job has data when we call Decode(). 45 // |prefetch_cb| - Run when prefetching has completed. 46 void Prefetch(const base::Closure& prefetch_cb); 47 48 // Called by MediaSourcePlayer to decode some data. 49 // |callback| - Run when decode operation has completed. 50 // 51 // Returns true if the next decode was started and |callback| will be 52 // called when the decode operation is complete. 53 // Returns false if a config change is needed. |callback| is ignored 54 // and will not be called. 55 bool Decode(const base::TimeTicks& start_time_ticks, 56 const base::TimeDelta& start_presentation_timestamp, 57 const DecoderCallback& callback); 58 59 // Called to stop the last Decode() early. 60 // If the decoder is in the process of decoding the next frame, then 61 // this method will just allow the decode to complete as normal. If 62 // this object is waiting for a data request to complete, then this method 63 // will wait for the data to arrive and then call the |callback| 64 // passed to Decode() with a status of MEDIA_CODEC_STOPPED. This ensures that 65 // the |callback| passed to Decode() is always called and the status 66 // reflects whether data was actually decoded or the decode terminated early. 67 void StopDecode(); 68 69 // Flush the decoder. 70 void Flush(); 71 72 // Enter prerolling state. The job must not currently be decoding. 73 void BeginPrerolling(const base::TimeDelta& preroll_timestamp); 74 prerolling()75 bool prerolling() const { return prerolling_; } 76 is_decoding()77 bool is_decoding() const { return !decode_cb_.is_null(); } 78 79 protected: 80 MediaDecoderJob(const scoped_refptr<base::MessageLoopProxy>& decoder_loop, 81 MediaCodecBridge* media_codec_bridge, 82 const base::Closure& request_data_cb); 83 84 // Release the output buffer at index |output_buffer_index| and render it if 85 // |render_output| is true. Upon completion, |callback| will be called. 86 virtual void ReleaseOutputBuffer( 87 int output_buffer_index, 88 size_t size, 89 bool render_output, 90 const ReleaseOutputCompletionCallback& callback) = 0; 91 92 // Returns true if the "time to render" needs to be computed for frames in 93 // this decoder job. 94 virtual bool ComputeTimeToRender() const = 0; 95 96 private: 97 // Causes this instance to be deleted on the thread it is bound to. 98 void Release(); 99 100 MediaCodecStatus QueueInputBuffer(const AccessUnit& unit); 101 102 // Returns true if this object has data to decode. 103 bool HasData() const; 104 105 // Initiates a request for more data. 106 // |done_cb| is called when more data is available in |received_data_|. 107 void RequestData(const base::Closure& done_cb); 108 109 // Posts a task to start decoding the next access unit in |received_data_|. 110 void DecodeNextAccessUnit( 111 const base::TimeTicks& start_time_ticks, 112 const base::TimeDelta& start_presentation_timestamp); 113 114 // Helper function to decoder data on |thread_|. |unit| contains all the data 115 // to be decoded. |start_time_ticks| and |start_presentation_timestamp| 116 // represent the system time and the presentation timestamp when the first 117 // frame is rendered. We use these information to estimate when the current 118 // frame should be rendered. If |needs_flush| is true, codec needs to be 119 // flushed at the beginning of this call. 120 void DecodeInternal(const AccessUnit& unit, 121 const base::TimeTicks& start_time_ticks, 122 const base::TimeDelta& start_presentation_timestamp, 123 bool needs_flush, 124 const DecoderCallback& callback); 125 126 // Called on the UI thread to indicate that one decode cycle has completed. 127 // Completes any pending job destruction or any pending decode stop. If 128 // destruction was not pending, passes its arguments to |decode_cb_|. 129 void OnDecodeCompleted(MediaCodecStatus status, 130 const base::TimeDelta& presentation_timestamp, 131 size_t audio_output_bytes); 132 133 // The UI message loop where callbacks should be dispatched. 134 scoped_refptr<base::MessageLoopProxy> ui_loop_; 135 136 // The message loop that decoder job runs on. 137 scoped_refptr<base::MessageLoopProxy> decoder_loop_; 138 139 // The media codec bridge used for decoding. Owned by derived class. 140 // NOTE: This MUST NOT be accessed in the destructor. 141 MediaCodecBridge* media_codec_bridge_; 142 143 // Whether the decoder needs to be flushed. 144 bool needs_flush_; 145 146 // Whether input EOS is encountered. 147 // TODO(wolenetz/qinmin): Protect with a lock. See http://crbug.com/320043. 148 bool input_eos_encountered_; 149 150 // Whether output EOS is encountered. 151 bool output_eos_encountered_; 152 153 // Tracks whether DecodeInternal() should skip decoding if the first access 154 // unit is EOS or empty, and report |MEDIA_CODEC_OUTPUT_END_OF_STREAM|. This 155 // is to work around some decoders that could crash otherwise. See 156 // http://b/11696552. 157 bool skip_eos_enqueue_; 158 159 // The timestamp the decoder needs to preroll to. If an access unit's 160 // timestamp is smaller than |preroll_timestamp_|, don't render it. 161 // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_| 162 // is not very accurate. 163 base::TimeDelta preroll_timestamp_; 164 165 // Indicates prerolling state. If true, this job has not yet decoded output 166 // that it will render, since the most recent of job construction or 167 // BeginPrerolling(). If false, |preroll_timestamp_| has been reached. 168 // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_| 169 // is not very accurate. 170 bool prerolling_; 171 172 // Weak pointer passed to media decoder jobs for callbacks. It is bounded to 173 // the decoder thread. 174 base::WeakPtrFactory<MediaDecoderJob> weak_this_; 175 176 // Callback used to request more data. 177 base::Closure request_data_cb_; 178 179 // Callback to run when new data has been received. 180 base::Closure on_data_received_cb_; 181 182 // Callback to run when the current Decode() operation completes. 183 DecoderCallback decode_cb_; 184 185 // The current access unit being processed. 186 size_t access_unit_index_; 187 188 // Data received over IPC from last RequestData() operation. 189 DemuxerData received_data_; 190 191 // The index of input buffer that can be used by QueueInputBuffer(). 192 // If the index is uninitialized or invalid, it must be -1. 193 int input_buf_index_; 194 195 bool stop_decode_pending_; 196 197 // Indicates that this object should be destroyed once the current 198 // Decode() has completed. This gets set when Release() gets called 199 // while there is a decode in progress. 200 bool destroy_pending_; 201 202 DISALLOW_IMPLICIT_CONSTRUCTORS(MediaDecoderJob); 203 }; 204 205 } // namespace media 206 207 #endif // MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_ 208