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

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

Issue 1176993005: Audio and video decoders for MediaCodecPlayer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Min's comments Created 5 years, 6 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 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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698