OLD | NEW |
| (Empty) |
1 // Copyright 2015 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_CODEC_DECODER_H_ | |
6 #define MEDIA_BASE_ANDROID_MEDIA_CODEC_DECODER_H_ | |
7 | |
8 #include <stddef.h> | |
9 | |
10 #include <memory> | |
11 | |
12 #include "base/android/scoped_java_ref.h" | |
13 #include "base/callback.h" | |
14 #include "base/macros.h" | |
15 #include "base/memory/ref_counted.h" | |
16 #include "base/single_thread_task_runner.h" | |
17 #include "base/synchronization/lock.h" | |
18 #include "base/threading/thread.h" | |
19 #include "base/time/time.h" | |
20 #include "media/base/android/access_unit_queue.h" | |
21 #include "media/base/android/demuxer_stream_player_params.h" | |
22 | |
23 namespace media { | |
24 | |
25 struct FrameStatistics; | |
26 class MediaCodecBridge; | |
27 | |
28 // The decoder for MediaCodecPlayer. | |
29 // This class accepts the incoming data into AccessUnitQueue and works with | |
30 // MediaCodecBridge for decoding and rendering the frames. The MediaCodecPlayer | |
31 // has two decoder objects: audio and video. | |
32 // | |
33 // The decoder works on two threads. The data from demuxer comes on Media | |
34 // thread. The commands from MediaCodecPlayer, such as Prefetch, Start, | |
35 // RequestToStop also come on the Media thread. The operations with MediaCodec | |
36 // buffers and rendering happen on a separate thread called Decoder thread. | |
37 // This class creates, starts and stops it as necessary. | |
38 // | |
39 // Decoder's internal state machine goes through the following states: | |
40 // | |
41 // [ Stopped ] <------------------- (any state except Error) | |
42 // | | | | |
43 // | Prefetch |--- internal ------| | |
44 // v | transition v | |
45 // [ Prefetching ] | [ Error ] | |
46 // | | | |
47 // | internal transition | | |
48 // v | Error recovery: | |
49 // [ Prefetched ] | | |
50 // | | (any state including Error) | |
51 // | Configure and Start | | | |
52 // v | | ReleaseDecoderResources | |
53 // [ Running ] | v | |
54 // | | [ InEmergencyStop ] | |
55 // | RequestToStop | | | |
56 // v | |(decoder thread stopped) | |
57 // [ Stopping ] ------------------- v | |
58 // [ Stopped ] | |
59 // | |
60 // [ Stopped ] -------------------- | |
61 // ^ | | |
62 // | Flush | | |
63 // --------------------------- | |
64 | |
65 // (any state except Error) | |
66 // | | |
67 // | SyncStop | |
68 // v | |
69 // [ InEmergencyStop ] | |
70 // | | |
71 // |(decoder thread stopped) | |
72 // v | |
73 // [ Stopped ] | |
74 | |
75 // Here is the workflow that is expected to be maintained by a caller, which is | |
76 // MediaCodecPlayer currently. | |
77 // | |
78 // [ Stopped ] | |
79 // | | |
80 // | Prefetch | |
81 // v | |
82 // [ Prefetching ] | |
83 // | | |
84 // | (Enough data received) | |
85 // v | |
86 // [ Prefetched ] | |
87 // | | |
88 // | <---------- SetDemuxerConfigs (*) | |
89 // | | |
90 // | <---------- SetVideoSurface (**) | |
91 // | | |
92 // | Configure --------------------------------------------+ | |
93 // | | | |
94 // v v | |
95 // ( Config Succeeded ) ( Key frame required ) | |
96 // | | | |
97 // | Start | | |
98 // v | | |
99 // [ Running ] ------------------------------+ | | |
100 // | | | | |
101 // | | | | |
102 // | RequestToStop | SyncStop | SyncStop | |
103 // | | | | |
104 // [ Stopping ] | | | |
105 // | | | | |
106 // | ( Last frame rendered ) | | | |
107 // | | | | |
108 // | | | | |
109 // v | | | |
110 // [ Stopped ] <-----------------------------+-----------------+ | |
111 // | |
112 // | |
113 // (*) Demuxer configs is a precondition to Configure(), but MediaCodecPlayer | |
114 // has stricter requirements and they are set before Prefetch(). | |
115 // | |
116 // (**) VideoSurface is a precondition to video decoder Configure(), can be set | |
117 // any time before Configure(). | |
118 | |
119 class MediaCodecDecoder { | |
120 public: | |
121 // The result of MediaCodec configuration, used by MediaCodecPlayer. | |
122 enum ConfigStatus { | |
123 kConfigFailure = 0, | |
124 kConfigOk, | |
125 kConfigKeyFrameRequired, | |
126 }; | |
127 | |
128 // The decoder reports current playback time to the MediaCodecPlayer. | |
129 // For audio, the parameters designate the beginning and end of a time | |
130 // interval. The beginning is the estimated time that is playing right now. | |
131 // The end is the playback time of the last buffered data. During normal | |
132 // playback the subsequent intervals overlap. | |
133 // For video both values are PTS of the corresponding frame, i.e. the interval | |
134 // has zero width. | |
135 // The third parameter means "postpone", it is set to true if the actual | |
136 // rendering will start in a later point in time. This only happens with | |
137 // audio after preroll. The MediaCodecPlayer might decide to update the | |
138 // current time but not pass it to the upper layer. | |
139 typedef base::Callback<void(base::TimeDelta, base::TimeDelta, bool)> | |
140 SetTimeCallback; | |
141 | |
142 // MediaCodecDecoder constructor. | |
143 // Parameters: | |
144 // decoder_thread_name: | |
145 // The thread name to be passed to decoder thread constructor. | |
146 // media_task_runner: | |
147 // A task runner for the controlling thread. All public methods should be | |
148 // called on this thread, and callbacks are delivered on this thread. | |
149 // The MediaCodecPlayer uses a dedicated (Media) thread for this. | |
150 // frame_statistics: | |
151 // A pointer to FrameStatistics object which gathers playback quality | |
152 // related data. | |
153 // external_request_data_cb: | |
154 // Called periodically as the amount of internally stored data decreases. | |
155 // The receiver should call OnDemuxerDataAvailable() with more data. | |
156 // starvation_cb: | |
157 // Called when starvation is detected. The decoder state does not change. | |
158 // The player is supposed to stop and then prefetch the decoder. | |
159 // decoder_drained_cb: | |
160 // Called when decoder is drained for reconfiguration. | |
161 // stop_done_cb: | |
162 // Called when async stop request is completed. | |
163 // waiting_for_decryption_key_cb: | |
164 // Will be executed whenever the key needed to decrypt the stream is not | |
165 // available. | |
166 // error_cb: | |
167 // Called when a MediaCodec error occurred. If this happens, a player has | |
168 // to either call ReleaseDecoderResources() or destroy the decoder object. | |
169 MediaCodecDecoder( | |
170 const char* decoder_thread_name, | |
171 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | |
172 FrameStatistics* frame_statistics, | |
173 const base::Closure& external_request_data_cb, | |
174 const base::Closure& starvation_cb, | |
175 const base::Closure& decoder_drained_cb, | |
176 const base::Closure& stop_done_cb, | |
177 const base::Closure& waiting_for_decryption_key_cb, | |
178 const base::Closure& error_cb); | |
179 | |
180 virtual ~MediaCodecDecoder(); | |
181 | |
182 virtual const char* class_name() const; | |
183 | |
184 // MediaCodecDecoder exists through the whole lifetime of the player | |
185 // to support dynamic addition and removal of the streams. | |
186 // This method returns true if the current stream (audio or video) | |
187 // is currently active. | |
188 virtual bool HasStream() const = 0; | |
189 | |
190 // Stores configuration for the use of upcoming Configure() | |
191 virtual void SetDemuxerConfigs(const DemuxerConfigs& configs) = 0; | |
192 | |
193 // Returns true if the DemuxerConfigs announce that content is encrypted and | |
194 // that MediaCrypto is required for configuration. | |
195 virtual bool IsContentEncrypted() const = 0; | |
196 | |
197 // Stops decoder thread, releases the MediaCodecBridge and other resources. | |
198 virtual void ReleaseDecoderResources() = 0; | |
199 | |
200 // Flushes the MediaCodec, after that resets the AccessUnitQueue and blocks | |
201 // the input. Decoder thread should not be running. | |
202 virtual void Flush(); | |
203 | |
204 // Releases MediaCodecBridge and any related buffers or references. | |
205 virtual void ReleaseMediaCodec(); | |
206 | |
207 // Returns corresponding conditions. | |
208 bool IsPrefetchingOrPlaying() const; | |
209 bool IsStopped() const; | |
210 bool IsCompleted() const; | |
211 bool NotCompletedAndNeedsPreroll() const; | |
212 | |
213 // Forces reconfiguraton on the next Configure(). | |
214 void SetNeedsReconfigure(); | |
215 | |
216 // Sets preroll timestamp and requests preroll. | |
217 void SetPrerollTimestamp(base::TimeDelta preroll_ts); | |
218 | |
219 // Starts prefetching: accumulates enough data in AccessUnitQueue. | |
220 // Decoder thread is not running. | |
221 void Prefetch(const base::Closure& prefetch_done_cb); | |
222 | |
223 // Configures MediaCodec. | |
224 ConfigStatus Configure(jobject media_crypto); | |
225 | |
226 // Starts the decoder for prerolling. This method starts the decoder thread. | |
227 bool Preroll(const base::Closure& preroll_done_cb); | |
228 | |
229 // Starts the decoder after preroll is not needed, starting decoder thread | |
230 // if it has not started yet. | |
231 bool Start(base::TimeDelta start_timestamp); | |
232 | |
233 // Stops the playback process synchronously. This method stops the decoder | |
234 // thread synchronously, and then releases all MediaCodec buffers. | |
235 void SyncStop(); | |
236 | |
237 // Requests to stop the playback and returns. | |
238 // Decoder will stop asynchronously after all the dequeued output buffers | |
239 // are rendered. | |
240 void RequestToStop(); | |
241 | |
242 // Notification posted when asynchronous stop is done or playback completed. | |
243 void OnLastFrameRendered(bool eos_encountered); | |
244 | |
245 // Notification posted when last prerolled frame has been returned to codec. | |
246 void OnPrerollDone(); | |
247 | |
248 // Puts the incoming data into AccessUnitQueue. | |
249 void OnDemuxerDataAvailable(const DemuxerData& data); | |
250 | |
251 // For testing only. | |
252 | |
253 // Returns true if the decoder is in kPrerolling state. | |
254 bool IsPrerollingForTests() const; | |
255 | |
256 // Drains decoder and reconfigures for each |kConfigChanged|. | |
257 void SetAlwaysReconfigureForTests(); | |
258 | |
259 // Sets the notification to be called when MediaCodec is created. | |
260 void SetCodecCreatedCallbackForTests(base::Closure cb); | |
261 | |
262 protected: | |
263 enum RenderMode { | |
264 kRenderSkip = 0, | |
265 kRenderAfterPreroll, | |
266 kRenderNow, | |
267 }; | |
268 | |
269 // Returns true if the new DemuxerConfigs requires MediaCodec | |
270 // reconfiguration. | |
271 virtual bool IsCodecReconfigureNeeded(const DemuxerConfigs& next) const = 0; | |
272 | |
273 // Does the part of MediaCodecBridge configuration that is specific | |
274 // to audio or video. | |
275 virtual ConfigStatus ConfigureInternal(jobject media_crypto) = 0; | |
276 | |
277 // Associates PTS with device time so we can calculate delays. | |
278 // We use delays for video decoder only. | |
279 virtual void AssociateCurrentTimeWithPTS(base::TimeDelta current_time) {} | |
280 | |
281 // Invalidate delay calculation. We use delays for video decoder only. | |
282 virtual void DissociatePTSFromTime() {} | |
283 | |
284 // Processes the change of the output format, varies by stream. | |
285 // Returns true if this processing succeeded. | |
286 virtual bool OnOutputFormatChanged() = 0; | |
287 | |
288 // Renders the decoded frame and releases output buffer, or posts a delayed | |
289 // task to do it at a later time. Returnes false if an error occurred. | |
290 virtual bool Render(int buffer_index, | |
291 size_t offset, | |
292 size_t size, | |
293 RenderMode render_mode, | |
294 base::TimeDelta pts, | |
295 bool eos_encountered) = 0; | |
296 | |
297 // Returns the number of delayed task (we might have them for video). | |
298 virtual int NumDelayedRenderTasks() const; | |
299 | |
300 // Releases output buffers that are dequeued and not released yet (video). | |
301 virtual void ReleaseDelayedBuffers() {} | |
302 | |
303 #ifndef NDEBUG | |
304 // For video, checks that access unit is the key frame or stand-alone EOS. | |
305 virtual void VerifyUnitIsKeyFrame(const AccessUnit* unit) const {} | |
306 #endif | |
307 | |
308 // Helper methods. | |
309 | |
310 // Synchroniously stop decoder thread. | |
311 void DoEmergencyStop(); | |
312 | |
313 // Returns true if we are in the process of sync stop. | |
314 bool InEmergencyStop() const { return GetState() == kInEmergencyStop; } | |
315 | |
316 // Notifies the decoder if the frame is the last one. | |
317 void CheckLastFrame(bool eos_encountered, bool has_delayed_tasks); | |
318 | |
319 const char* AsString(RenderMode render_mode); | |
320 | |
321 // Protected data. | |
322 | |
323 // We call MediaCodecBridge on this thread for both input and output buffers. | |
324 base::Thread decoder_thread_; | |
325 | |
326 // Object for posting tasks on Media thread. | |
327 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | |
328 | |
329 // Statistics for UMA. | |
330 FrameStatistics* frame_statistics_; | |
331 | |
332 // Controls Android MediaCodec | |
333 std::unique_ptr<MediaCodecBridge> media_codec_bridge_; | |
334 | |
335 // The queue of access units. | |
336 AccessUnitQueue au_queue_; | |
337 | |
338 // Flag forces reconfiguration even if |media_codec_bridge_| exists. Currently | |
339 // is set by video decoder when the video surface changes. | |
340 bool needs_reconfigure_; | |
341 | |
342 // Flag forces to drain decoder in the process of dynamic reconfiguration. | |
343 bool drain_decoder_; | |
344 | |
345 // For tests only. Forces to always reconfigure for |kConfigChanged| unit. | |
346 bool always_reconfigure_for_tests_; | |
347 | |
348 // For tests only. Callback to be callned when MediaCodec is created. | |
349 base::Closure codec_created_for_tests_cb_; | |
350 | |
351 private: | |
352 enum DecoderState { | |
353 kStopped = 0, | |
354 kPrefetching, | |
355 kPrefetched, | |
356 kPrerolling, | |
357 kPrerolled, | |
358 kRunning, | |
359 kStopping, | |
360 kInEmergencyStop, | |
361 kError, | |
362 }; | |
363 | |
364 // Helper method that processes an error from MediaCodec. | |
365 void OnCodecError(); | |
366 | |
367 // Requests data. Ensures there is no more than one request at a time. | |
368 void RequestData(); | |
369 | |
370 // Prefetching callback that is posted to Media thread | |
371 // in the kPrefetching state. | |
372 void PrefetchNextChunk(); | |
373 | |
374 // The callback to do actual playback. Posted to Decoder thread | |
375 // in the kRunning state. | |
376 void ProcessNextFrame(); | |
377 | |
378 // Helper method for ProcessNextFrame. | |
379 // Pushes one input buffer to the MediaCodec if the codec can accept it. | |
380 // Returns false if there was MediaCodec error. | |
381 bool EnqueueInputBuffer(); | |
382 | |
383 // Helper method for EnqueueInputBuffer. | |
384 // Gets the next data frame from the queue, requesting more data and saving | |
385 // configuration changes on the way. Sets |drain_decoder| to true of any of | |
386 // the configuration changes requires draining the decoder. Returns the Info | |
387 // pointing to the current data unit ot empty Info if it got past the end of | |
388 // the queue. | |
389 AccessUnitQueue::Info AdvanceAccessUnitQueue(bool* drain_decoder); | |
390 | |
391 // Helper method for ProcessNextFrame. | |
392 // Pulls all currently available output frames and renders them. | |
393 // Returns true if we need to continue decoding process, i.e post next | |
394 // ProcessNextFrame method, and false if we need to stop decoding. | |
395 bool DepleteOutputBufferQueue(); | |
396 | |
397 DecoderState GetState() const; | |
398 void SetState(DecoderState state); | |
399 const char* AsString(DecoderState state); | |
400 | |
401 // Private Data. | |
402 | |
403 // External data request callback that is passed to decoder. | |
404 base::Closure external_request_data_cb_; | |
405 | |
406 // These notifications are called on corresponding conditions. | |
407 base::Closure prefetch_done_cb_; | |
408 base::Closure starvation_cb_; | |
409 base::Closure preroll_done_cb_; | |
410 base::Closure decoder_drained_cb_; | |
411 base::Closure stop_done_cb_; | |
412 base::Closure waiting_for_decryption_key_cb_; | |
413 base::Closure error_cb_; | |
414 | |
415 // Data request callback that is posted by decoder internally. | |
416 base::Closure request_data_cb_; | |
417 | |
418 // Callback used to post OnCodecError method. | |
419 base::Closure internal_error_cb_; | |
420 | |
421 // Callback for posting OnPrerollDone method. | |
422 base::Closure internal_preroll_done_cb_; | |
423 | |
424 // Internal state. | |
425 DecoderState state_; | |
426 mutable base::Lock state_lock_; | |
427 | |
428 // Preroll timestamp is set if we need preroll and cleared after we done it. | |
429 base::TimeDelta preroll_timestamp_; | |
430 | |
431 // Index of the dequeued and filled buffer that we keep trying to enqueue. | |
432 // Such buffer appears in MEDIA_CODEC_NO_KEY processing. | |
433 int pending_input_buf_index_; | |
434 | |
435 // Set to true when MediaCodec internal buffers are filled up. | |
436 bool is_prepared_; | |
437 | |
438 // Flag is set when the EOS is enqueued into MediaCodec. Reset by Flush. | |
439 bool eos_enqueued_; | |
440 | |
441 // Flag is set when NO_KEY error is received from QueueSecureInputBuffer. | |
442 // Reset after we stop. | |
443 bool missing_key_reported_; | |
444 | |
445 // Flag is set when the EOS is received in MediaCodec output. Reset by Flush. | |
446 bool completed_; | |
447 | |
448 // Flag to ensure we post last frame notification once. | |
449 bool last_frame_posted_; | |
450 | |
451 // Indicates whether the data request is in progress. | |
452 bool is_data_request_in_progress_; | |
453 | |
454 // Indicates whether the incoming data should be ignored. | |
455 bool is_incoming_data_invalid_; | |
456 | |
457 #ifndef NDEBUG | |
458 // When set, we check that the following video frame is the key frame. | |
459 bool verify_next_frame_is_key_; | |
460 #endif | |
461 | |
462 // NOTE: Weak pointers must be invalidated before all other member variables. | |
463 base::WeakPtrFactory<MediaCodecDecoder> weak_factory_; | |
464 | |
465 DISALLOW_COPY_AND_ASSIGN(MediaCodecDecoder); | |
466 }; | |
467 | |
468 } // namespace media | |
469 | |
470 #endif // MEDIA_BASE_ANDROID_MEDIA_CODEC_DECODER_H_ | |
OLD | NEW |