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