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 "base/android/scoped_java_ref.h" | |
9 #include "base/callback.h" | |
10 #include "base/macros.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/single_thread_task_runner.h" | |
14 #include "base/synchronization/lock.h" | |
15 #include "base/threading/thread.h" | |
16 #include "base/time/time.h" | |
17 #include "media/base/android/access_unit_queue.h" | |
18 #include "media/base/android/demuxer_stream_player_params.h" | |
19 | |
20 namespace media { | |
21 | |
22 class MediaCodecBridge; | |
23 | |
24 // The decoder for MediaCodecPlayer. | |
25 // This class accepts the incoming data into AccessUnitQueue and works with | |
26 // MediaCodecBridge for decoding and rendering the frames. The MediaCodecPlayer | |
27 // has two decoder objects: audio and video. | |
28 // | |
29 // The decoder works on two threads. The data from demuxer comes on Media | |
30 // thread. The commands from MediaCodecPlayer, such as Prefetch, Start, | |
31 // RequestToStop also come on the Media thread. The operations with MediaCodec | |
32 // buffers and rendering happen on a separate thread called Decoder thread. | |
33 // This class creates, starts and stops it as necessary. | |
34 // | |
35 // Decoder's internal state machine goes through the following states: | |
wolenetz
2015/06/19 22:46:42
nit: what transition(s) may Flush() occur on? Or d
Tima Vaisburd
2015/06/20 02:32:31
Flush is only allowed in the Stopped state.
wolenetz
2015/06/22 21:41:21
Acknowledged.
| |
36 // | |
37 // [ Stopped ] <------------------- (any state) | |
38 // | | | | |
39 // | Prefetch |--- internal ------| | |
wolenetz
2015/06/19 22:46:42
nit: I'm not sure from this diagram (though, thank
wolenetz
2015/06/22 21:41:21
Acknowledged.
| |
40 // v | transition v | |
41 // [ Prefetching ] | [ Error ] | |
42 // | | | | |
43 // | internal transition | | ReleaseDecoderResources | |
44 // v | v | |
45 // [ Prefetched ] | [ Stopped ] | |
wolenetz
2015/06/19 22:46:42
nit: it appears the error->stopped->prefetching pa
Tima Vaisburd
2015/06/20 02:32:31
Yes, after ReleaseDecoderResources on the next cyc
Tima Vaisburd
2015/06/20 02:32:31
Yes, ReleaseDecoderResources is a path to recovery
wolenetz
2015/06/22 21:41:21
Acknowledged.
| |
46 // | | | |
47 // | Start | | |
48 // v | | |
49 // [ Running ] | | |
50 // | | | |
51 // | RequestToStop | | |
52 // v | | |
53 // [ Stopping ] ------------------- | |
54 | |
55 class MediaCodecDecoder { | |
56 public: | |
57 // The result of MediaCodec configuration, used by MediaCodecPlayer. | |
58 enum ConfigStatus { | |
59 CONFIG_FAILURE = 0, | |
60 CONFIG_OK, | |
61 CONFIG_KEY_FRAME_REQUIRED, | |
62 }; | |
63 | |
64 // The decoder reports current playback time to the MediaCodecPlayer. | |
wolenetz
2015/06/19 22:46:42
please document the two TimeDelta parameters
Tima Vaisburd
2015/06/20 02:32:31
Done.
| |
65 typedef base::Callback<void(base::TimeDelta, base::TimeDelta)> | |
66 SetTimeCallback; | |
67 | |
68 // MediaCodecDecoder constructor. | |
69 // Parameters: | |
70 // media_task_runner: | |
71 // A task runner for the controlling thread. All public methods should be | |
72 // called on this thread, and callbacks are delivered on this thread. | |
73 // The MediaCodecPlayer uses a dedicated (Media) thread for this. | |
74 // request_data_cb: | |
75 // Called periodically as the amount of internally stored data decreased. | |
76 // The receiver should call OnDemuxerDataAvailable() with more data. | |
77 // starvation_cb: | |
78 // Called when starvation is detected. The decoder state does not change. | |
79 // The player is supposed to stop and then prefetch the decoder. | |
80 // stop_done_cb: | |
81 // Called when async stop request is completed. | |
82 // error_cb: | |
83 // Called when an unrecoverable MediaCodec error occurred. If this happen, | |
wolenetz
2015/06/19 22:46:42
nit: s/happen/happens/
Tima Vaisburd
2015/06/20 02:32:31
Done.
| |
84 // a player has to either call ReleaseDecoderResources() or destroy the | |
85 // decoder object. | |
wolenetz
2015/06/19 22:46:42
nit: (see diagram comment): is error truly unrecov
Tima Vaisburd
2015/06/20 02:32:30
Removed word "unrecoverable".
| |
86 // decoder_thread_name: | |
87 // The thread name to be passed to decoder thread constructor. | |
88 MediaCodecDecoder( | |
89 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | |
90 const base::Closure& request_data_cb, | |
91 const base::Closure& starvation_cb, | |
92 const base::Closure& stop_done_cb, | |
93 const base::Closure& error_cb, | |
94 const char* decoder_thread_name); | |
95 virtual ~MediaCodecDecoder(); | |
96 | |
97 virtual const char* class_name() const { return "Decoder"; } | |
98 | |
99 // MediaCodecDecoder exists through the whole lifetime of the player | |
100 // to support dynamic addition and removal of the streams. | |
101 // This method returns true if the current stream (audio or video) | |
102 // is currently active. | |
103 virtual bool HasStream() const = 0; | |
104 | |
105 // Stores configuration for the use of upcoming Configure() | |
106 virtual void SetDemuxerConfigs(const DemuxerConfigs& configs) = 0; | |
107 | |
108 // Stops decoder thread, releases the MediaCodecBridge and other resources. | |
109 virtual void ReleaseDecoderResources(); | |
110 | |
111 // Flushes the MediaCodec and resets the AccessUnitQueue. | |
112 // Decoder thread should not be running. | |
113 virtual void Flush(); | |
114 | |
115 // Releases MediaCodecBridge. | |
116 void ReleaseMediaCodec(); | |
117 | |
118 // Returns corresponding conditions. | |
119 bool IsPrefetchingOrPlaying() const; | |
120 bool IsStopped() const; | |
121 bool IsCompleted() const; | |
122 | |
123 base::android::ScopedJavaLocalRef<jobject> GetMediaCrypto(); | |
124 | |
125 // Starts prefetching: accumulates enough data in AccessUnitQueue. | |
126 // Decoder thread is not running. | |
127 void Prefetch(const base::Closure& prefetch_done_cb); | |
128 | |
129 // Configures MediaCodec. | |
130 ConfigStatus Configure(); | |
131 | |
132 // Starts the decoder thread and resumes the playback. | |
133 bool Start(base::TimeDelta current_time); | |
134 | |
135 // Stops the playback process synchronously. This method stops the decoder | |
136 // thread synchronously, and then releases all MediaCodec buffers. | |
137 void SyncStop(); | |
138 | |
139 // Requests to stop the playback and returns. | |
140 // Decoder will stop asynchronously after all the dequeued output buffers | |
141 // are rendered. | |
142 void RequestToStop(); | |
143 | |
144 // Notification posted when asynchronous stop is done or playback completed. | |
145 void OnLastFrameRendered(bool completed); | |
146 | |
147 // Puts the incoming data into AccessUnitQueue. | |
148 void OnDemuxerDataAvailable(const DemuxerData& data); | |
149 | |
150 protected: | |
151 // Returns true if the new DemuxerConfigs requires MediaCodec | |
152 // reconfiguration. | |
153 virtual bool IsCodecReconfigureNeeded(const DemuxerConfigs& curr, | |
154 const DemuxerConfigs& next) const = 0; | |
155 | |
156 // Does the part of MediaCodecBridge configuration that is specific | |
157 // to audio or video. | |
158 virtual ConfigStatus ConfigureInternal() = 0; | |
159 | |
160 // Associates PTS with device time so we can calculate delays. | |
161 // We use delays for video decoder only. | |
162 virtual void SynchronizePTSWithTime(base::TimeDelta current_time) {} | |
163 | |
164 // Processes the change of the output format, varies by stream. | |
165 virtual void OnOutputFormatChanged() = 0; | |
166 | |
167 // Renders the decoded frame and releases output buffer, or posts | |
168 // a delayed task to do it at a later time, | |
169 virtual void Render(int buffer_index, | |
170 size_t size, | |
171 bool render_output, | |
172 base::TimeDelta pts, | |
173 bool eos_encountered) = 0; | |
174 | |
175 // Returns the number of delayed task (we might have them for video). | |
176 virtual int NumDelayedRenderTasks() const { return 0; } | |
177 | |
178 // Releases output buffers that are dequeued and not released yet | |
179 // because their rendering is delayed (video). | |
180 virtual void ReleaseDelayedBuffers() {} | |
181 | |
182 // Helper methods. | |
183 | |
184 // Notifies the decoder if the frame is the last one. | |
185 void CheckLastFrame(bool eos_encountered, bool has_delayed_tasks); | |
186 | |
187 // Protected data. | |
188 | |
189 // Object for posting tasks on Media thread. | |
190 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | |
191 | |
192 // Controls Android MediaCodec | |
193 scoped_ptr<MediaCodecBridge> media_codec_bridge_; | |
194 | |
195 // We call MediaCodecBridge on this thread for both | |
196 // input and output buffers. | |
197 base::Thread decoder_thread_; | |
198 | |
199 // The queue of access units. | |
200 AccessUnitQueue au_queue_; | |
201 | |
202 private: | |
203 enum DecoderState { | |
204 kStopped = 0, | |
205 kPrefetching, | |
206 kPrefetched, | |
207 kRunning, | |
208 kStopping, | |
209 kError, | |
210 }; | |
211 | |
212 // Helper method that processes an error from MediaCodec. | |
213 void OnCodecError(); | |
214 | |
215 // Prefetching callback that is posted to Media thread | |
216 // in the kPrefetching state. | |
217 void PrefetchNextChunk(); | |
218 | |
219 // The callback to do actual playback. Posted to Decoder thread | |
220 // in the kRunning state. | |
221 void ProcessNextFrame(); | |
222 | |
223 // Helper method for ProcessNextFrame. | |
224 // Pushes one input buffer to the MediaCodec if the codec can accept it. | |
225 // Returns false if there was MediaCodec error. | |
226 bool EnqueueInputBuffer(); | |
227 | |
228 // Helper method for ProcessNextFrame. | |
229 // Pulls all currently available output frames and renders them. | |
230 // Returns false if there was MediaCodec error. | |
231 bool DepleteOutputBufferQueue(bool* eos_encountered); | |
232 | |
233 DecoderState GetState() const; | |
234 void SetState(DecoderState state); | |
235 const char* AsString(DecoderState state); | |
236 | |
237 // Private Data. | |
238 | |
239 // Callback used to request more data. | |
240 base::Closure request_data_cb_; | |
241 | |
242 // These notifications are called on corresponding conditions. | |
243 base::Closure prefetch_done_cb_; | |
244 base::Closure starvation_cb_; | |
245 base::Closure stop_done_cb_; | |
246 base::Closure error_cb_; | |
247 | |
248 // Callback used to post OnCodecError method. | |
249 base::Closure internal_error_cb_; | |
250 | |
251 // Internal state. | |
252 DecoderState state_; | |
253 mutable base::Lock state_lock_; | |
254 | |
255 // Flag is set when the EOS is enqueued into MediaCodec. | |
wolenetz
2015/06/19 22:46:42
Is EOS reset by Flush or some other operation? e.g
Tima Vaisburd
2015/06/20 02:32:31
Added "Reset by Flush" in the comment.
| |
256 bool eos_enqueued_; | |
257 | |
258 // Flag is set when the EOS is received in MediaCodec output. | |
wolenetz
2015/06/19 22:46:42
ditto: when might this flag be reset?
Tima Vaisburd
2015/06/20 02:32:31
Same thing, added "Reset by Flush" in the comment.
| |
259 bool completed_; | |
260 | |
261 // Flag to ensure we post last frame notification once. | |
262 bool last_frame_posted_; | |
263 | |
264 base::WeakPtr<MediaCodecDecoder> weak_this_; | |
wolenetz
2015/06/19 22:46:42
I'm confused: do we really need both weak_this_ an
Tima Vaisburd
2015/06/20 02:32:31
I copied this pattern from MedisSourcePlayer. I th
Tima Vaisburd
2015/06/21 22:35:20
Removed weak_this_ in favor of GetWeakPtr().
wolenetz
2015/06/22 21:41:21
Acknowledged.
| |
265 // NOTE: Weak pointers must be invalidated before all other member variables. | |
266 base::WeakPtrFactory<MediaCodecDecoder> weak_factory_; | |
267 | |
268 DISALLOW_COPY_AND_ASSIGN(MediaCodecDecoder); | |
269 }; | |
270 | |
271 } // namespace media | |
272 | |
273 #endif // MEDIA_BASE_ANDROID_MEDIA_CODEC_DECODER_H_ | |
OLD | NEW |