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