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

Side by Side Diff: media/omx/omx_codec.h

Issue 2255005: move from omx_codec to new omx_video_decode_engine... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: remove omx_code, update omx_test to use omx engine Created 10 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
« no previous file with comments | « media/media.gyp ('k') | media/omx/omx_codec.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 // TODO(ajwong): Generalize this class (fix comments, API, and extract
6 // implemntation) so that it can be used for encoding & decoding of both
7 // Video and Audio.
8 //
9 // An object that works with an OpenMAX component for video decoding.
10 // Operations on this object are all asynchronous and this object
11 // requires a message loop that it works on.
12 //
13 // OWNERSHIP
14 //
15 // The OmxCodec works with external objects
16 // OmxConfigurator
17 // This object is given to OmxCodec to perform port configuration.
18 // This object is provided and destroyed externally. Its references
19 // are given to OmxCodec and client application is responsible
20 // for cleaning them.
21 //
22 // INTERACTION WITH EXTERNAL OBJECTS
23 //
24 // ................ ............
25 // | Configurator | <------------- | OmxCodec |
26 // ................ ............
27 // Read / Feed -----------' '
28 // .-----------' v Buffer Allocation
29 // .......... ...............
30 // | Client | ------------------> | OutputSink |
31 // .......... Buffer Ready ...............
32 //
33 // THREADING
34 //
35 // OmxCodec is given a message loop to run on. There is a strong gurantee
36 // that all callbacks given to it will be executed on this message loop.
37 // Communicatations with OmxConfigurator and OmxOutputSink are also done
38 // on this thread.
39 //
40 // Public methods can be called on any thread.
41 //
42 // USAGES
43 //
44 // // Initialization.
45 // MessageLoop message_loop;
46 // OmxCodec* decoder = new OmxCodec(&message_loop);
47 //
48 // OmxConfigurator::MediaFormat input_format, output_format;
49 // input_format.codec = OmxCodec::kCodecH264;
50 // output_format.codec = OmxCodec::kCodecRaw;
51 // scoped_ptr<OmxConfigurator> configurator(
52 // new OmxDecoderConfigurator(input_format, output_format));
53 //
54 // decoder->Setup(configurator.get());
55 // decoder->SetErrorCallback(NewCallback(this, &Client::ErrorCallback));
56 // decoder->SetFormatCallback(NewCallback(this, &Client::FormatCallback));
57 //
58 // // Start is asynchronous. We don't need to wait for it to proceed.
59 // decoder->Start();
60 //
61 // // We can start giving buffer to the decoder right after start. It will
62 // // queue the input buffers and output requests and process them until
63 // // the decoder can actually process them.
64 // for (int i = 0; i < kInitialBuffers; ++i) {
65 // OmxInputBuffer* buffer = PrepareInitialInputBuffer();
66 // decoder->Feed(buffer, NewCallback(this, &Client::FeedCallback));
67 // }
68 //
69 // // We can also issue read requests to the decoder.
70 // decoder->Read(NewCallback(this, &Client::ReadCallback));
71 //
72 // // Make the following call to stop the decoder:
73 // decoder->Stop(NewCallback(this, &Client::StopCallback));
74 //
75 // A typical FeedCallback will look like:
76 // void Client::FeedCallback(OmxInputBuffer* buffer) {
77 // // We have read to the end so stop feeding.
78 // if (buffer->IsEndOfStream())
79 // return;
80 // PrepareInputBuffer(buffer);
81 // decoder->Feed(buffer, NewCallback(this, &Client::FeedCallback));
82 // }
83 //
84 // A typical ReadCallback will look like:
85 // void Client::ReadCallback(int buffer_id,
86 // OmxOutputSink::BufferUsedCallback* callback) {
87 // // Detect end-of-stream state.
88 // if (buffer_id == OmxCodec::kEosBuffer)
89 // return;
90 //
91 // // Issue a new read immediately.
92 // decoder->Read(NewCallback(this, &Client::ReadCallback));
93 //
94 // // Pass the buffer to OmxOutputSink.
95 // output_sink->BufferReady(buffer_id, callback);
96 // }
97 //
98 // EXTERNAL STATES
99 //
100 // Client of this class will only see four states from the decoder:
101 // .........
102 // | Error |
103 // .........
104 // ^
105 // `-.
106 // ......... ......... ........
107 // | Empty | -> | Start | -> | Stop |
108 // ......... ......... ........
109 //
110 // How to operate this object in these four states can be described by
111 // usage above.
112 //
113 // INTERNAL STATES
114 //
115 // There are multiple internal states to keep track of state transitions
116 // of the OpenMAX component. The state transitions and the task during
117 // the transition can be summerized by the following state diagram:
118 //
119 // ......... -> .......... -> ........ -> .............
120 // | Empty | | Loaded | | Idle | | Executing |
121 // ......... <- .......... <- ........ <- .............
122 // ^ `
123 // ` v
124 // ......... ............. ..............
125 // | Error | | Port Enable | | Port Disable |
126 // ......... ............. ..............
127 //
128 // We need to perform specific tasks in order to transition from one state
129 // to another. When an error is received, this object will transition to
130 // the error state.
131
132 #ifndef MEDIA_OMX_OMX_CODEC_H_
133 #define MEDIA_OMX_OMX_CODEC_H_
134
135 #include <queue>
136 #include <vector>
137
138 #include "base/callback.h"
139 #include "base/scoped_ptr.h"
140 #include "media/omx/omx_configurator.h"
141 #include "third_party/openmax/il/OMX_Component.h"
142 #include "third_party/openmax/il/OMX_Core.h"
143 #include "third_party/openmax/il/OMX_Video.h"
144
145 class MessageLoop;
146
147 namespace media {
148
149 class Buffer;
150
151 class OmxCodec : public base::RefCountedThreadSafe<OmxCodec> {
152 public:
153 // TODO(jiesun): remove callback parameters.
154 typedef Callback2<
155 const OmxConfigurator::MediaFormat&,
156 const OmxConfigurator::MediaFormat&>::Type FormatCallback;
157 typedef Callback1<scoped_refptr<Buffer> >::Type FeedDoneCallback;
158 typedef Callback1<OMX_BUFFERHEADERTYPE*>::Type FillDoneCallback;
159 typedef Callback0::Type Callback;
160
161 // Initialize an OmxCodec object that runs on |message_loop|. It is
162 // guaranteed that callbacks are executed on this message loop.
163 explicit OmxCodec(MessageLoop* message_loop);
164 virtual ~OmxCodec();
165
166 // Setup OmxCodec using |configurator|. |configurator| and |output_sink|
167 // are not owned by this class and should be cleaned up externally.
168 void Setup(OmxConfigurator* configurator,
169 FeedDoneCallback* feed_done_callback,
170 FillDoneCallback* fill_done_callback);
171
172 // Set the error callback. In case of error the callback will be called.
173 void SetErrorCallback(Callback* callback);
174
175 // Set the format change callback. In case of input stream changes.
176 void SetFormatCallback(FormatCallback* callback);
177
178 // Start the decoder, this will start the initialization asynchronously.
179 // Client can start feeding to and reading from the decoder.
180 void Start();
181
182 // Stop the decoder. When the decoder is fully stopped, |callback|
183 // is called.
184 void Stop(Callback* callback);
185
186 // Feed the decoder with |buffer|. When the decoder has consumed the
187 // buffer |feed_done_callback_| is called with |buffer|.
188 void Feed(scoped_refptr<Buffer> buffer);
189
190 // Flush the decoder and reset its end-of-stream state.
191 void Flush(Callback* callback);
192
193 // Subclass can provide a different value.
194 virtual int current_omx_spec_version() const { return 0x00000101; }
195
196 static const int kEosBuffer = -1;
197
198 private:
199 enum State {
200 kEmpty,
201 kLoaded,
202 kIdle,
203 kExecuting,
204 kPortSettingEnable,
205 kPortSettingDisable,
206 kError,
207 };
208
209 // Getter and setter for the state.
210 State GetState() const;
211 void SetState(State state);
212 State GetNextState() const;
213 void SetNextState(State state);
214
215 // Methods to be executed in |message_loop_|, they correspond to the
216 // public methods.
217 void StartTask();
218 void StopTask(Callback* callback);
219 void FeedTask(scoped_refptr<Buffer> buffer);
220
221 // Helper method to perform tasks when this object is stopped.
222 void DoneStop();
223
224 // Helper method to call |error_callback_| after transition to error
225 // state is done.
226 void ReportError();
227
228 // Helper method to call |format_callback_| after a format change.
229 // used when decoder output port had done with port reconfigure and
230 // return to enabled state.
231 void ReportFormatChange(
232 const OmxConfigurator::MediaFormat& input_format,
233 const OmxConfigurator::MediaFormat& output_format);
234
235 // Helper method to configure port format at LOADED state.
236 bool ConfigureIOPorts();
237
238 // Methods and free input and output buffers.
239 bool AllocateInputBuffers();
240 bool AllocateOutputBuffers();
241 void FreeInputBuffers();
242 void FreeOutputBuffers();
243 void FreeInputQueue();
244
245 // Transition methods define the specific tasks needs to be done
246 // in order transition to the next state.
247 void Transition_EmptyToLoaded();
248 void Transition_LoadedToIdle();
249 void Transition_IdleToExecuting();
250 void Transition_ExecutingToDisable();
251 void Transition_DisableToEnable();
252 void Transition_DisableToIdle();
253 void Transition_EnableToExecuting();
254 void Transition_EnableToIdle();
255 void Transition_ExecutingToIdle();
256 void Transition_IdleToLoaded();
257 void Transition_LoadedToEmpty();
258 void Transition_Error();
259
260 // State transition routines. They control which task to perform based
261 // on the current state and the next state.
262 void PostStateTransitionTask(State state);
263 void StateTransitionTask(State state);
264
265 // This method does an automatic state transition after the last
266 // state transition was completed. For example, after the decoder
267 // has transitioned from kEmpty to kLoaded, this method will order
268 // transition from kLoaded to kIdle.
269 void PostDoneStateTransitionTask();
270 void DoneStateTransitionTask();
271
272 // Determine whether we can issue fill buffer or empty buffer
273 // to the decoder based on the current state and next state.
274 bool CanFillBuffer();
275 bool CanEmptyBuffer();
276
277 // Determine whether we can use |input_queue_| and |output_queue_|
278 // based on the current state.
279 bool CanAcceptInput();
280 bool CanAcceptOutput();
281
282 // Methods to handle incoming (encoded) buffers.
283 void EmptyBufferCompleteTask(OMX_BUFFERHEADERTYPE* buffer);
284 void EmptyBufferTask();
285
286 // Methods to handle outgoing (decoded) buffers.
287 void FillBufferCompleteTask(OMX_BUFFERHEADERTYPE* buffer);
288
289 // Take on decoded buffer to fulfill one read request.
290 void FulfillOneRead();
291
292 // Callback method to be called from a buffer output sink.
293 // BufferUsedTask() is the corresponding task that runs on
294 // |message_loop_|.
295 void BufferUsedCallback(int buffer_id);
296 void BufferUsedTask(int buffer_id);
297
298 // Methods that do initial reads to kick start the decoding process.
299 void InitialFillBuffer();
300 void InitialEmptyBuffer();
301
302 // Member functions to handle events from the OMX component. They
303 // are called on the thread that the OMX component runs on, thus
304 // it is not safe to perform any operations on them. They simply
305 // post a task on |message_loop_| to do the actual work.
306 void EventHandlerInternal(OMX_HANDLETYPE component,
307 OMX_EVENTTYPE event,
308 OMX_U32 data1, OMX_U32 data2,
309 OMX_PTR event_data);
310
311 void EmptyBufferCallbackInternal(OMX_HANDLETYPE component,
312 OMX_BUFFERHEADERTYPE* buffer);
313
314 void FillBufferCallbackInternal(OMX_HANDLETYPE component,
315 OMX_BUFFERHEADERTYPE* buffer);
316
317 // The following three methods are static callback methods
318 // for the OMX component. When these callbacks are received, the
319 // call is delegated to the three internal methods above.
320 static OMX_ERRORTYPE EventHandler(OMX_HANDLETYPE component,
321 OMX_PTR priv_data,
322 OMX_EVENTTYPE event,
323 OMX_U32 data1, OMX_U32 data2,
324 OMX_PTR event_data);
325
326 static OMX_ERRORTYPE EmptyBufferCallback(OMX_HANDLETYPE component,
327 OMX_PTR priv_data,
328 OMX_BUFFERHEADERTYPE* buffer);
329
330 static OMX_ERRORTYPE FillBufferCallback(OMX_HANDLETYPE component,
331 OMX_PTR priv_data,
332 OMX_BUFFERHEADERTYPE* buffer);
333
334 std::vector<OMX_BUFFERHEADERTYPE*> input_buffers_;
335 int input_buffer_count_;
336 int input_buffer_size_;
337 int input_port_;
338 bool input_eos_;
339
340 std::vector<OMX_BUFFERHEADERTYPE*> output_buffers_;
341 int output_buffer_count_;
342 int output_buffer_size_;
343 int output_port_;
344 bool output_eos_;
345
346 // |state_| records the current state. During state transition
347 // |next_state_| is the next state that this machine will transition
348 // to. After a state transition is completed and the state becomes
349 // stable then |next_state_| equals |state_|. Inequality can be
350 // used to detect a state transition.
351 // These two members are read and written only on |message_loop_|.
352 State state_;
353 State next_state_;
354
355 OMX_COMPONENTTYPE* component_handle_;
356 OmxConfigurator* configurator_;
357 MessageLoop* message_loop_;
358
359 scoped_ptr<FormatCallback> format_callback_;
360 scoped_ptr<Callback> stop_callback_;
361 scoped_ptr<Callback> error_callback_;
362 scoped_ptr<FeedDoneCallback> feed_done_callback_;
363 scoped_ptr<FillDoneCallback> fill_done_callback_;
364
365 // Input queue for encoded data.
366 // The input buffers will be sent to OMX component via OMX_EmptyThisBuffer()
367 std::queue<scoped_refptr<Buffer> > pending_input_queue_;
368
369 // Input queue for encoded data.
370 // Those buffers have been sent to OMX component, but not returned
371 // by EmptyBufferDone callback. Once returned from OMX component, they
372 // will be returned to owner.
373 std::queue<scoped_refptr<Buffer> > processing_input_queue_;
374
375 // Available input OpenMAX buffers that we can use to issue
376 // OMX_EmptyThisBuffer() call.
377 std::queue<OMX_BUFFERHEADERTYPE*> available_input_buffers_;
378
379 // A queue of buffers that carries decoded video frames. They are
380 // ready to return to client.
381 // TOOD(hclam): extract it to a separate class.
382 std::queue<int> output_buffers_ready_;
383
384 private:
385 DISALLOW_COPY_AND_ASSIGN(OmxCodec);
386 };
387
388 } // namespace media
389
390 #endif // MEDIA_OMX_OMX_CODEC_H_
OLDNEW
« no previous file with comments | « media/media.gyp ('k') | media/omx/omx_codec.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698