Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: media/base/android/media_decoder_job.h

Issue 254473010: Refactor MSE implementation on Android to simplify the logic and improve the performance (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase after recent config IPC change Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_ 5 #ifndef MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
6 #define MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_ 6 #define MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
7 7
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/memory/weak_ptr.h" 9 #include "base/memory/weak_ptr.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
11 #include "media/base/android/demuxer_stream_player_params.h" 11 #include "media/base/android/demuxer_stream_player_params.h"
12 #include "media/base/android/media_codec_bridge.h" 12 #include "media/base/android/media_codec_bridge.h"
13 #include "ui/gl/android/scoped_java_surface.h"
13 14
14 namespace base { 15 namespace base {
15 class SingleThreadTaskRunner; 16 class SingleThreadTaskRunner;
16 } 17 }
17 18
18 namespace media { 19 namespace media {
19 20
21 class MediaDrmBridge;
22
20 // Class for managing all the decoding tasks. Each decoding task will be posted 23 // 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. 24 // onto the same thread. The thread will be stopped once Stop() is called.
22 // Data is stored in 2 chunks. When new data arrives, it is always stored in 25 // Data is stored in 2 chunks. When new data arrives, it is always stored in
23 // an inactive chunk. And when the current active chunk becomes empty, a new 26 // an inactive chunk. And when the current active chunk becomes empty, a new
24 // data request will be sent to the renderer. 27 // data request will be sent to the renderer.
25 class MediaDecoderJob { 28 class MediaDecoderJob {
26 public: 29 public:
27 struct Deleter { 30 struct Deleter {
28 inline void operator()(MediaDecoderJob* ptr) const { ptr->Release(); } 31 inline void operator()(MediaDecoderJob* ptr) const { ptr->Release(); }
29 }; 32 };
(...skipping 17 matching lines...) Expand all
47 // Called by MediaSourcePlayer when more data for this object has arrived. 50 // Called by MediaSourcePlayer when more data for this object has arrived.
48 void OnDataReceived(const DemuxerData& data); 51 void OnDataReceived(const DemuxerData& data);
49 52
50 // Prefetch so we know the decoder job has data when we call Decode(). 53 // Prefetch so we know the decoder job has data when we call Decode().
51 // |prefetch_cb| - Run when prefetching has completed. 54 // |prefetch_cb| - Run when prefetching has completed.
52 void Prefetch(const base::Closure& prefetch_cb); 55 void Prefetch(const base::Closure& prefetch_cb);
53 56
54 // Called by MediaSourcePlayer to decode some data. 57 // Called by MediaSourcePlayer to decode some data.
55 // |callback| - Run when decode operation has completed. 58 // |callback| - Run when decode operation has completed.
56 // 59 //
57 // Returns a scoped pointer to a DemuxerConfig if a config change is detected, 60 // Returns true if the next decode was started and |callback| will be
58 // or an empty scoped pointer otherwise. In the case of requiring further data 61 // called when the decode operation is complete.
59 // before commencing decode, an empty scoped pointer will also be returned 62 // Returns false if |media_codec_bridge_| cannot be created. |callback| is
wolenetz 2014/05/21 00:48:04 nit: s/./;/
qinmin 2014/05/22 00:35:55 Done.
60 // although config change may be the next received access unit. |callback| 63 // ignored and will not be called.
61 // will be called when the decode operation is complete. If a config change 64 bool Decode(base::TimeTicks start_time_ticks,
62 // is detected, |callback| is ignored and will not be called. 65 base::TimeDelta start_presentation_timestamp,
63 scoped_ptr<DemuxerConfigs> Decode( 66 const DecoderCallback& callback);
64 base::TimeTicks start_time_ticks,
65 base::TimeDelta start_presentation_timestamp,
66 const DecoderCallback& callback);
67 67
68 // Called to stop the last Decode() early. 68 // Called to stop the last Decode() early.
69 // If the decoder is in the process of decoding the next frame, then 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 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 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| 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 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 74 // the |callback| passed to Decode() is always called and the status
75 // reflects whether data was actually decoded or the decode terminated early. 75 // reflects whether data was actually decoded or the decode terminated early.
76 void StopDecode(); 76 void StopDecode();
77 77
78 // Flush the decoder. 78 // Flushes the decoder and abandons all the data that is being decoded.
79 void Flush(); 79 void Flush();
80 80
81 // Enter prerolling state. The job must not currently be decoding. 81 // Enter prerolling state. The job must not currently be decoding.
82 void BeginPrerolling(base::TimeDelta preroll_timestamp); 82 void BeginPrerolling(base::TimeDelta preroll_timestamp);
83 83
84 bool prerolling() const { return prerolling_; } 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 virtual bool SetDemuxerConfigs(const DemuxerConfigs& configs);
wolenetz 2014/05/21 00:48:04 Does this need to be virtual? Neither {audio,video
qinmin 2014/05/22 00:35:55 No, removed the virtual keyword. On 2014/05/21 00
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;
85 97
86 bool is_decoding() const { return !decode_cb_.is_null(); } 98 bool is_decoding() const { return !decode_cb_.is_null(); }
87 99
88 bool is_requesting_demuxer_data() const { 100 void set_drm_bridge(MediaDrmBridge* drm_bridge) { drm_bridge_ = drm_bridge; }
89 return is_requesting_demuxer_data_; 101
90 } 102 bool is_content_encrypted() const { return is_content_encrypted_; }
91 103
92 protected: 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 // |on_demuxer_config_changed_cb| - Callback to inform the caller that
109 // demuxer config has changed.
93 MediaDecoderJob( 110 MediaDecoderJob(
94 const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner, 111 const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner,
95 MediaCodecBridge* media_codec_bridge, 112 const base::Closure& request_data_cb,
96 const base::Closure& request_data_cb); 113 const base::Closure& on_demuxer_config_changed_cb);
97 114
98 // Release the output buffer at index |output_buffer_index| and render it if 115 // Release the output buffer at index |output_buffer_index| and render it if
99 // |render_output| is true. Upon completion, |callback| will be called. 116 // |render_output| is true. Upon completion, |callback| will be called.
100 virtual void ReleaseOutputBuffer( 117 virtual void ReleaseOutputBuffer(
101 int output_buffer_index, 118 int output_buffer_index,
102 size_t size, 119 size_t size,
103 bool render_output, 120 bool render_output,
104 base::TimeDelta current_presentation_timestamp, 121 base::TimeDelta current_presentation_timestamp,
105 const ReleaseOutputCompletionCallback& callback) = 0; 122 const ReleaseOutputCompletionCallback& callback) = 0;
106 123
107 // Returns true if the "time to render" needs to be computed for frames in 124 // Returns true if the "time to render" needs to be computed for frames in
108 // this decoder job. 125 // this decoder job.
109 virtual bool ComputeTimeToRender() const = 0; 126 virtual bool ComputeTimeToRender() const = 0;
110 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
111 private: 144 private:
112 friend class MediaSourcePlayerTest; 145 friend class MediaSourcePlayerTest;
113 146
114 // Causes this instance to be deleted on the thread it is bound to. 147 // Causes this instance to be deleted on the thread it is bound to.
115 void Release(); 148 void Release();
116 149
117 MediaCodecStatus QueueInputBuffer(const AccessUnit& unit); 150 // Queues an access unit into |media_codec_bridge_|'s input buffer. If
151 // |drain_decoder| is true, the access unit is replaced with an EOS unit so
152 // that we can drain the current buffer in |media_codec_bridge_|.
153 MediaCodecStatus QueueInputBuffer(const AccessUnit& unit, bool drain_decoder);
118 154
119 // Returns true if this object has data to decode. 155 // Returns true if this object has data to decode.
120 bool HasData() const; 156 bool HasData() const;
121 157
122 // Initiates a request for more data. 158 // Initiates a request for more data.
123 // |done_cb| is called when more data is available in |received_data_|. 159 // |done_cb| is called when more data is available in |received_data_|.
124 void RequestData(const base::Closure& done_cb); 160 void RequestData(const base::Closure& done_cb);
125 161
126 // Posts a task to start decoding the current access unit in |received_data_|. 162 // Posts a task to start decoding the current access unit in |received_data_|.
127 void DecodeCurrentAccessUnit( 163 void DecodeCurrentAccessUnit(
128 base::TimeTicks start_time_ticks, 164 base::TimeTicks start_time_ticks,
129 base::TimeDelta start_presentation_timestamp); 165 base::TimeDelta start_presentation_timestamp);
130 166
131 // Helper function to decoder data on |thread_|. |unit| contains all the data 167 // Helper function to decoder data on |thread_|. |unit| contains all the data
wolenetz 2014/05/21 00:48:04 nit: s/decoder/decode/ && s/thread_/decoder_task_r
qinmin 2014/05/22 00:35:55 Done.
132 // to be decoded. |start_time_ticks| and |start_presentation_timestamp| 168 // to be decoded. |start_time_ticks| and |start_presentation_timestamp|
133 // represent the system time and the presentation timestamp when the first 169 // represent the system time and the presentation timestamp when the first
134 // frame is rendered. We use these information to estimate when the current 170 // frame is rendered. We use these information to estimate when the current
135 // frame should be rendered. If |needs_flush| is true, codec needs to be 171 // frame should be rendered. If |needs_flush| is true, codec needs to be
136 // flushed at the beginning of this call. 172 // flushed at the beginning of this call.
wolenetz 2014/05/21 00:48:04 nit: comment drain_decoder to help clarify differe
qinmin 2014/05/22 00:35:55 added comments here. And added a DCHECK in functio
137 void DecodeInternal(const AccessUnit& unit, 173 void DecodeInternal(const AccessUnit& unit,
138 base::TimeTicks start_time_ticks, 174 base::TimeTicks start_time_ticks,
139 base::TimeDelta start_presentation_timestamp, 175 base::TimeDelta start_presentation_timestamp,
140 bool needs_flush, 176 bool needs_flush,
177 bool drain_decoder,
141 const DecoderCallback& callback); 178 const DecoderCallback& callback);
142 179
143 // Called on the UI thread to indicate that one decode cycle has completed. 180 // Called on the UI thread to indicate that one decode cycle has completed.
144 // Completes any pending job destruction or any pending decode stop. If 181 // Completes any pending job destruction or any pending decode stop. If
145 // destruction was not pending, passes its arguments to |decode_cb_|. 182 // destruction was not pending, passes its arguments to |decode_cb_|.
146 void OnDecodeCompleted(MediaCodecStatus status, 183 void OnDecodeCompleted(MediaCodecStatus status,
147 base::TimeDelta current_presentation_timestamp, 184 base::TimeDelta current_presentation_timestamp,
148 base::TimeDelta max_presentation_timestamp); 185 base::TimeDelta max_presentation_timestamp);
149 186
150 // Helper function to get the current access unit that is being decoded. 187 // Helper function to get the current access unit that is being decoded.
151 const AccessUnit& CurrentAccessUnit() const; 188 const AccessUnit& CurrentAccessUnit() const;
152 189
153 // Helper function to get the current data chunk index that is being decoded. 190 // Helper function to get the current data chunk index that is being decoded.
154 size_t CurrentReceivedDataChunkIndex() const; 191 size_t CurrentReceivedDataChunkIndex() const;
155 192
156 // Check whether a chunk has no remaining access units to decode. If 193 // Check whether a chunk has no remaining access units to decode. If
157 // |is_active_chunk| is true, this function returns whether decoder has 194 // |is_active_chunk| is true, this function returns whether decoder has
158 // consumed all data in |received_data_[current_demuxer_data_index_]|. 195 // consumed all data in |received_data_[current_demuxer_data_index_]|.
159 // Otherwise, it returns whether decoder has consumed all data in the inactive 196 // Otherwise, it returns whether decoder has consumed all data in the inactive
160 // chunk. 197 // chunk.
161 bool NoAccessUnitsRemainingInChunk(bool is_active_chunk) const; 198 bool NoAccessUnitsRemainingInChunk(bool is_active_chunk) const;
162 199
163 // Clearn all the received data. 200 // Requests new data for the current chunk if it runs out of data.
164 void ClearData();
165
166 // Request new data for the current chunk if it runs out of data.
167 void RequestCurrentChunkIfEmpty(); 201 void RequestCurrentChunkIfEmpty();
168 202
169 // Initialize |received_data_| and |access_unit_index_|. 203 // Initializes |received_data_| and |access_unit_index_|.
170 void InitializeReceivedData(); 204 void InitializeReceivedData();
171 205
206 // Called when the decoder is completely drained and is ready to be released.
207 void OnDecoderDrained();
208
209 // Creates |media_codec_bridge_| for decoding purpose.
wolenetz 2014/05/21 00:48:04 nit: doc retval
qinmin 2014/05/22 00:35:55 Done.
210 bool CreateMediaCodecBridge();
211
212 // Called when an access unit is consumed by the decoder. |is_config_change|
213 // indicates whether the current access unit is a config change. If it is
214 // true, the next access unit is guarateed to be an I-frame.
215 virtual void CurrentDataConsumed(bool is_config_change) {}
216
217 // Called when |media_codec_bridge_| is released
218 virtual void OnMediaCodecBridgeReleased() {}
219
220 // Implemented by the child class to create |media_codec_bridge_| for a
221 // particular stream.
wolenetz 2014/05/21 00:48:04 nit: doc retval
qinmin 2014/05/22 00:35:55 Done.
222 virtual bool CreateMediaCodecBridgeInternal() = 0;
223
224 // Returns true if the |configs| doesn't match the current demuxer configs
225 // the decoder job has.
226 virtual bool IsDemuxerConfigChanged(const DemuxerConfigs& configs) const = 0;
227
228 // Update the demuxer configs.
229 virtual void UpdateDemuxerConfigs(const DemuxerConfigs& configs) = 0;
230
172 // Return the index to |received_data_| that is not currently being decoded. 231 // Return the index to |received_data_| that is not currently being decoded.
173 size_t inactive_demuxer_data_index() const { 232 size_t inactive_demuxer_data_index() const {
174 return 1 - current_demuxer_data_index_; 233 return 1 - current_demuxer_data_index_;
175 } 234 }
176 235
177 // The UI message loop where callbacks should be dispatched. 236 // The UI message loop where callbacks should be dispatched.
178 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 237 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
179 238
180 // The task runner that decoder job runs on. 239 // The task runner that decoder job runs on.
181 scoped_refptr<base::SingleThreadTaskRunner> decoder_task_runner_; 240 scoped_refptr<base::SingleThreadTaskRunner> decoder_task_runner_;
182 241
183 // The media codec bridge used for decoding. Owned by derived class.
184 // NOTE: This MUST NOT be accessed in the destructor.
185 MediaCodecBridge* media_codec_bridge_;
186
187 // Whether the decoder needs to be flushed. 242 // Whether the decoder needs to be flushed.
188 bool needs_flush_; 243 bool needs_flush_;
189 244
190 // Whether input EOS is encountered. 245 // Whether input EOS is encountered.
191 // TODO(wolenetz/qinmin): Protect with a lock. See http://crbug.com/320043. 246 // TODO(wolenetz/qinmin): Protect with a lock. See http://crbug.com/320043.
192 bool input_eos_encountered_; 247 bool input_eos_encountered_;
193 248
194 // Whether output EOS is encountered. 249 // Whether output EOS is encountered.
195 bool output_eos_encountered_; 250 bool output_eos_encountered_;
196 251
(...skipping 12 matching lines...) Expand all
209 // Indicates prerolling state. If true, this job has not yet decoded output 264 // Indicates prerolling state. If true, this job has not yet decoded output
210 // that it will render, since the most recent of job construction or 265 // that it will render, since the most recent of job construction or
211 // BeginPrerolling(). If false, |preroll_timestamp_| has been reached. 266 // BeginPrerolling(). If false, |preroll_timestamp_| has been reached.
212 // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_| 267 // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_|
213 // is not very accurate. 268 // is not very accurate.
214 bool prerolling_; 269 bool prerolling_;
215 270
216 // Callback used to request more data. 271 // Callback used to request more data.
217 base::Closure request_data_cb_; 272 base::Closure request_data_cb_;
218 273
274 // Callback to notify the caller config has changed.
275 base::Closure on_demuxer_config_changed_cb_;
276
219 // Callback to run when new data has been received. 277 // Callback to run when new data has been received.
220 base::Closure on_data_received_cb_; 278 base::Closure on_data_received_cb_;
221 279
222 // Callback to run when the current Decode() operation completes. 280 // Callback to run when the current Decode() operation completes.
223 DecoderCallback decode_cb_; 281 DecoderCallback decode_cb_;
224 282
225 // Data received over IPC from last RequestData() operation. 283 // Data received over IPC from last RequestData() operation.
226 // We keep 2 chunks at the same time to reduce the IPC latency between chunks. 284 // We keep 2 chunks at the same time to reduce the IPC latency between chunks.
227 // If data inside the current chunk are all decoded, we will request a new 285 // If data inside the current chunk are all decoded, we will request a new
228 // chunk from the demuxer and swap the current chunk with the other one. 286 // chunk from the demuxer and swap the current chunk with the other one.
229 // New data will always be stored in the other chunk since the current 287 // New data will always be stored in the other chunk since the current
230 // one may be still in use. 288 // one may be still in use.
231 DemuxerData received_data_[2]; 289 DemuxerData received_data_[2];
232 290
233 // Index to the current data chunk that is being decoded. 291 // Index to the current data chunk that is being decoded.
234 size_t current_demuxer_data_index_; 292 size_t current_demuxer_data_index_;
235 293
236 // Index to the access unit inside each data chunk that is being decoded. 294 // Index to the access unit inside each data chunk that is being decoded.
237 size_t access_unit_index_[2]; 295 size_t access_unit_index_[2];
238 296
239 // The index of input buffer that can be used by QueueInputBuffer(). 297 // The index of input buffer that can be used by QueueInputBuffer().
240 // If the index is uninitialized or invalid, it must be -1. 298 // If the index is uninitialized or invalid, it must be -1.
241 int input_buf_index_; 299 int input_buf_index_;
242 300
301 // Indicates whether content is encrypted.
302 bool is_content_encrypted_;
303
304 // Indicates the decoder job should stop after decoding the current access
305 // unit.
243 bool stop_decode_pending_; 306 bool stop_decode_pending_;
244 307
245 // Indicates that this object should be destroyed once the current 308 // Indicates that this object should be destroyed once the current
246 // Decode() has completed. This gets set when Release() gets called 309 // Decode() has completed. This gets set when Release() gets called
247 // while there is a decode in progress. 310 // while there is a decode in progress.
248 bool destroy_pending_; 311 bool destroy_pending_;
249 312
250 // Indicates whether the decoder is in the middle of requesting new data. 313 // Indicates whether the decoder is in the middle of requesting new data.
251 bool is_requesting_demuxer_data_; 314 bool is_requesting_demuxer_data_;
252 315
253 // Indicates whether the incoming data should be ignored. 316 // Indicates whether the incoming data should be ignored.
254 bool is_incoming_data_invalid_; 317 bool is_incoming_data_invalid_;
255 318
256 // Weak pointer passed to media decoder jobs for callbacks. It is bounded to 319 // Indicates that |media_codec_bridge_| should be released once the current
257 // the decoder thread. 320 // Decode() has completed. This gets set when ReleaseDecoderResources() gets
258 // NOTE: Weak pointers must be invalidated before all other member variables. 321 // called while there is a decode in progress.
259 base::WeakPtrFactory<MediaDecoderJob> weak_factory_; 322 bool release_resources_pending_;
323
324 // Pointer to a DRM object that will be used for encrypted streams.
325 MediaDrmBridge* drm_bridge_;
326
327 // Indicates whether |media_codec_bridge_| is in the middle of being drained
328 // due to a config change.
329 bool drain_decoder_;
260 330
261 DISALLOW_IMPLICIT_CONSTRUCTORS(MediaDecoderJob); 331 DISALLOW_IMPLICIT_CONSTRUCTORS(MediaDecoderJob);
262 }; 332 };
263 333
264 } // namespace media 334 } // namespace media
265 335
266 #endif // MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_ 336 #endif // MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698