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

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

Issue 2283493003: Delete browser MSE implementation. (Closed)
Patch Set: Actually delete MSP. Cleanse references. Remove AudioTrack usage. Created 4 years, 2 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
OLDNEW
(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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698