2 * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
4 * Copyright (C) 2013, Collabora Ltd.
5 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation
10 * version 2.1 of the License.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <gst/video/video.h>
35 #ifdef GST_OMX_STRUCT_PACKING
36 # if GST_OMX_STRUCT_PACKING == 1
38 # elif GST_OMX_STRUCT_PACKING == 2
40 # elif GST_OMX_STRUCT_PACKING == 4
42 # elif GST_OMX_STRUCT_PACKING == 8
45 # error "Unsupported struct packing value"
49 /* If the component may signal EOS before it has finished pushing
50 * out all of its buffers. Happens with egl_render on the rpi.
52 #define GST_OMX_HACK_SIGNALS_PREMATURE_EOS G_GUINT64_CONSTANT (0x0000000000000400)
55 #include <OMX_Component.h>
57 #ifdef TIZEN_FEATURE_OMX
59 #include <tbm_surface.h>
60 #include <tbm_surface_internal.h>
61 #include <gst/allocators/gsttizenmemory.h>
64 #ifdef USE_OMX_TARGET_RPI
65 #include <OMX_Broadcom.h>
69 #include <OMX_VideoExt.h>
73 #include <OMX_IndexExt.h>
76 #ifdef HAVE_COMPONENT_EXT
77 #include <OMX_ComponentExt.h>
81 #include <OMX_CoreExt.h>
85 #include <OMX_AudioExt.h>
88 #ifdef HAVE_IV_COMMON_EXT
89 #include <OMX_IVCommonExt.h>
93 #include <OMX_ImageExt.h>
97 #include <OMX_OtherExt.h>
100 #ifdef GST_OMX_STRUCT_PACKING
106 #define GST_OMX_INIT_STRUCT(st) G_STMT_START { \
107 memset ((st), 0, sizeof (*(st))); \
108 (st)->nSize = sizeof (*(st)); \
109 (st)->nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
110 (st)->nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
111 (st)->nVersion.s.nRevision = OMX_VERSION_REVISION; \
112 (st)->nVersion.s.nStep = OMX_VERSION_STEP; \
116 #define GST_OMX_GET_TICKS(ticks) ((((guint64) (ticks).nHighPart) << 32) | ((ticks).nLowPart))
117 #define GST_OMX_SET_TICKS(ticks, i) G_STMT_START { \
118 ticks.nLowPart = ((guint64) (i)) & 0xffffffff; \
119 ticks.nHighPart = ((guint64) (i)) >> 32; \
122 #define GST_OMX_GET_TICKS(ticks) (ticks)
123 #define GST_OMX_SET_TICKS(ticks, i) G_STMT_START { \
128 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
129 #define OMX_INIT_PARAM(param) G_STMT_START { \
130 memset (&(param), 0, sizeof ((param))); \
131 (param).nSize = sizeof (param); \
132 (param).nVersion.s.nVersionMajor = 1; \
133 (param).nVersion.s.nVersionMinor = 1; \
137 /* If set on an element property means "use the OMX default value".
138 * If set on a default_* variable means that the default values hasn't been
139 * retrieved from OMX yet. */
140 #define GST_OMX_PROP_OMX_DEFAULT G_MAXUINT32
142 /* OMX_StateInvalid does not exist in 1.2.0 spec. The initial state is now
143 * StateLoaded. Problem is that gst-omx still needs an initial state different
144 * than StateLoaded. Otherwise gst_omx_component_set_state(StateLoaded) will
145 * early return because it will think it is already in StateLoaded. Also note
146 * that there is no call to gst_omx_component_set_state(StateInvalid) so this
147 * also shows that StateInvalid is used as a helper in gst-omx.
149 #if OMX_VERSION_MINOR == 2
150 #define OMX_StateInvalid OMX_StateReserved_0x00000000
153 /* Different hacks that are required to work around
154 * bugs in different OpenMAX implementations
156 /* In the EventSettingsChanged callback use nData2 instead of nData1 for
157 * the port index. Happens with Bellagio.
159 #define GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP G_GUINT64_CONSTANT (0x0000000000000001)
160 /* In the EventSettingsChanged callback assume that port index 0 really
161 * means port index 1. Happens with the Bellagio ffmpegdist video decoder.
163 #define GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1 G_GUINT64_CONSTANT (0x0000000000000002)
164 /* If the video framerate is not specified as fraction (Q.16) but as
165 * integer number. Happens with the Bellagio ffmpegdist video encoder.
167 #define GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER G_GUINT64_CONSTANT (0x0000000000000004)
168 /* If the SYNCFRAME flag on encoder output buffers is not used and we
169 * have to assume that all frames are sync frames.
170 * Happens with the Bellagio ffmpegdist video encoder.
172 #define GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED G_GUINT64_CONSTANT (0x0000000000000008)
173 /* If the component needs to be re-created if the caps change.
174 * Happens with Qualcomm's OpenMAX implementation.
176 #define GST_OMX_HACK_NO_COMPONENT_RECONFIGURE G_GUINT64_CONSTANT (0x0000000000000010)
178 /* If the component does not accept empty EOS buffers.
179 * Happens with Qualcomm's OpenMAX implementation.
181 #define GST_OMX_HACK_NO_EMPTY_EOS_BUFFER G_GUINT64_CONSTANT (0x0000000000000020)
183 /* If the component might not acknowledge a drain.
184 * Happens with TI's Ducati OpenMAX implementation.
186 #define GST_OMX_HACK_DRAIN_MAY_NOT_RETURN G_GUINT64_CONSTANT (0x0000000000000040)
188 /* If the component doesn't allow any component role to be set.
189 * Happens with Broadcom's OpenMAX implementation.
191 #define GST_OMX_HACK_NO_COMPONENT_ROLE G_GUINT64_CONSTANT (0x0000000000000080)
193 /* If the component doesn't allow disabling the outport while
194 * when setting the format until the output format is known.
196 #define GST_OMX_HACK_NO_DISABLE_OUTPORT G_GUINT64_CONSTANT (0x0000000000000100)
198 /* If the encoder requires input buffers that have a height
199 * which is a multiple of 16 pixels
201 #define GST_OMX_HACK_HEIGHT_MULTIPLE_16 G_GUINT64_CONSTANT (0x0000000000000200)
203 /* If we should pass the profile/level information from upstream to the
204 * OMX decoder. This is a violation of the OMX spec as
205 * OMX_IndexParamVideoProfileLevelCurrent is supposed to be r-o so
206 * do it as a platform specific hack.
208 #define GST_OMX_HACK_PASS_PROFILE_TO_DECODER G_GUINT64_CONSTANT (0x0000000000000800)
210 /* If we should pass the color format information from upstream to the
211 * OMX decoder input. This is a violation of the OMX spec as
212 * the eColorFormat field is supposed to only be used if eCompressionFormat is
213 * set to OMX_IMAGE_CodingUnused.
214 * Do this as a platform specific hack for OMX implementation which may use
215 * this information to pre-allocate internal buffers for example.
217 #define GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER G_GUINT64_CONSTANT (0x0000000000001000)
219 /* If set, automatically update nBufferCountActual to nBufferCountMin before
220 * allocating buffers. This can be used on OMX implementation decreasing
221 * nBufferCountMin depending of the format and so can reduce the number
222 * of allocated buffers.
224 #define GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL G_GUINT64_CONSTANT (0x0000000000002000)
226 typedef struct _GstOMXCore GstOMXCore;
227 typedef struct _GstOMXPort GstOMXPort;
228 typedef enum _GstOMXPortDirection GstOMXPortDirection;
229 typedef struct _GstOMXComponent GstOMXComponent;
230 typedef struct _GstOMXBuffer GstOMXBuffer;
231 typedef struct _GstOMXClassData GstOMXClassData;
232 typedef struct _GstOMXMessage GstOMXMessage;
235 typedef enum GOmxVendor GOmxVendor; /* check omx vender */
237 #ifdef TIZEN_FEATURE_OMX
239 #define MFC_INPUT_BUFFER_PLANE 1
240 #define MFC_OUTPUT_BUFFER_PLANE 2
241 #define MAX_BUFFER_PLANE 3
243 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
245 typedef struct _EnableGemBuffersParams EnableGemBuffersParams;
247 struct _EnableGemBuffersParams
250 OMX_VERSIONTYPE nVersion;
257 /* Everything good and the buffer is valid */
258 GST_OMX_ACQUIRE_BUFFER_OK = 0,
259 /* The port is flushing, exit ASAP */
260 GST_OMX_ACQUIRE_BUFFER_FLUSHING,
261 /* The port must be reconfigured */
262 GST_OMX_ACQUIRE_BUFFER_RECONFIGURE,
263 /* The port is EOS */
264 GST_OMX_ACQUIRE_BUFFER_EOS,
265 /* A fatal error happened */
266 GST_OMX_ACQUIRE_BUFFER_ERROR,
267 /* No buffer is currently available (used when calling gst_omx_port_acquire_buffer() in not waiting mode) */
268 GST_OMX_ACQUIRE_BUFFER_NO_AVAILABLE,
269 } GstOMXAcquireBufferReturn;
272 /* Handle to the OpenMAX IL core shared library */
275 /* Current number of users, transitions from/to 0
276 * call init/deinit */
278 gint user_count; /* LOCK */
281 gboolean secure; /* trust zone */
283 /* OpenMAX core library functions, protected with LOCK */
284 OMX_ERRORTYPE (*init) (void);
285 OMX_ERRORTYPE (*deinit) (void);
286 OMX_ERRORTYPE (*get_handle) (OMX_HANDLETYPE * handle,
287 OMX_STRING name, OMX_PTR data, OMX_CALLBACKTYPE * callbacks);
288 OMX_ERRORTYPE (*free_handle) (OMX_HANDLETYPE handle);
289 OMX_ERRORTYPE (*setup_tunnel) (OMX_HANDLETYPE output, OMX_U32 outport, OMX_HANDLETYPE input, OMX_U32 inport);
293 GST_OMX_MESSAGE_STATE_SET,
294 GST_OMX_MESSAGE_FLUSH,
295 GST_OMX_MESSAGE_ERROR,
296 GST_OMX_MESSAGE_PORT_ENABLE,
297 GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED,
298 GST_OMX_MESSAGE_BUFFER_FLAG,
299 GST_OMX_MESSAGE_BUFFER_DONE,
303 GST_OMX_COMPONENT_TYPE_SINK,
304 GST_OMX_COMPONENT_TYPE_SOURCE,
305 GST_OMX_COMPONENT_TYPE_FILTER
306 } GstOmxComponentType;
308 /* How the port's buffers are allocated */
310 GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER,
311 GST_OMX_BUFFER_ALLOCATION_USE_BUFFER,
312 GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC, /* Only supported by OMX 1.2.0 */
313 } GstOMXBufferAllocation;
320 struct _GstOMXMessage {
321 GstOMXMessageType type;
339 } port_settings_changed;
345 OMX_HANDLETYPE component;
347 OMX_BUFFERHEADERTYPE *buffer;
354 GstOMXComponent *comp;
359 OMX_PARAM_PORTDEFINITIONTYPE port_def;
360 GPtrArray *buffers; /* Contains GstOMXBuffer* */
361 GQueue pending_buffers; /* Contains GstOMXBuffer* */
363 gboolean flushed; /* TRUE after OMX_CommandFlush was done */
364 gboolean enabled_pending; /* TRUE after OMX_Command{En,Dis}able */
365 gboolean disabled_pending; /* was done until it took effect */
366 gboolean eos; /* TRUE after a buffer with EOS flag was received */
367 GstOMXBufferAllocation allocation;
368 gboolean using_pool; /* TRUE if the buffers of this port are managed by a pool */
369 #ifdef TIZEN_FEATURE_OMX
371 gboolean flush_start;
374 /* Increased whenever the settings of these port change.
375 * If settings_cookie != configured_settings_cookie
376 * the port has to be reconfigured.
378 gint settings_cookie;
379 gint configured_settings_cookie;
382 struct _GstOMXComponent {
383 GstMiniObject mini_object;
387 gchar *name; /* for debugging mostly */
389 OMX_HANDLETYPE handle;
392 guint64 hacks; /* Flags, GST_OMX_HACK_* */
394 /* Added once, never changed. No locks necessary */
395 GPtrArray *ports; /* Contains GstOMXPort* */
396 gint n_in_ports, n_out_ports;
398 /* Locking order: lock -> messages_lock
400 * Never hold lock while waiting for messages_cond
401 * Always check that messages is empty before waiting */
404 GQueue messages; /* Queue of GstOMXMessages */
405 GMutex messages_lock;
409 /* OMX_StateInvalid if no pending state */
410 OMX_STATETYPE pending_state;
411 /* OMX_ErrorNone usually, if different nothing will work */
412 OMX_ERRORTYPE last_error;
414 GList *pending_reconfigure_outports;
417 struct _GstOMXBuffer {
419 OMX_BUFFERHEADERTYPE *omx_buf;
421 /* TRUE if the buffer is used by the port, i.e.
422 * between {Empty,Fill}ThisBuffer and the callback
426 /* Cookie of the settings when this buffer was allocated */
427 gint settings_cookie;
429 /* TRUE if this is an EGLImage */
432 /* Used in dynamic buffer mode to keep track of the mapped content while it's
433 * being processed by the OMX component. */
434 GstVideoFrame input_frame;
435 gboolean input_frame_mapped; /* TRUE if input_frame is valid */
436 GstMemory *input_mem;
437 GstBuffer *input_buffer;
438 gboolean input_buffer_mapped;
440 #ifdef TIZEN_FEATURE_OMX
441 tbm_surface_h surface;
445 struct _GstOMXClassData {
446 const gchar *core_name;
447 const gchar *component_name;
448 const gchar *component_role;
450 const gchar *default_src_template_caps;
451 const gchar *default_sink_template_caps;
453 guint32 in_port_index, out_port_index;
454 #ifdef TIZEN_FEATURE_OMX
455 guint32 in_port_usebuffer, out_port_usebuffer;
460 GstOmxComponentType type;
463 GKeyFile * gst_omx_get_configuration (void);
465 const gchar * gst_omx_error_to_string (OMX_ERRORTYPE err);
466 const gchar * gst_omx_state_to_string (OMX_STATETYPE state);
467 const gchar * gst_omx_command_to_string (OMX_COMMANDTYPE cmd);
468 const gchar * gst_omx_buffer_flags_to_string (guint32 flags);
470 guint64 gst_omx_parse_hacks (gchar ** hacks);
472 GstOMXCore * gst_omx_core_acquire (const gchar * filename);
473 void gst_omx_core_release (GstOMXCore * core);
475 GType gst_omx_component_get_type (void);
477 GstOMXComponent * gst_omx_component_new (GstObject * parent, const gchar *core_name, const gchar *component_name, const gchar * component_role, guint64 hacks);
478 GstOMXComponent * gst_omx_component_ref (GstOMXComponent * comp);
479 void gst_omx_component_unref (GstOMXComponent * comp);
481 OMX_ERRORTYPE gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state);
482 OMX_STATETYPE gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout);
484 OMX_ERRORTYPE gst_omx_component_get_last_error (GstOMXComponent * comp);
485 const gchar * gst_omx_component_get_last_error_string (GstOMXComponent * comp);
487 GstOMXPort * gst_omx_component_add_port (GstOMXComponent * comp, guint32 index);
488 GstOMXPort * gst_omx_component_get_port (GstOMXComponent * comp, guint32 index);
490 OMX_ERRORTYPE gst_omx_component_get_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer param);
491 OMX_ERRORTYPE gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer param);
493 OMX_ERRORTYPE gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config);
494 OMX_ERRORTYPE gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config);
496 OMX_ERRORTYPE gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2);
497 OMX_ERRORTYPE gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2);
500 OMX_ERRORTYPE gst_omx_port_get_port_definition (GstOMXPort * port, OMX_PARAM_PORTDEFINITIONTYPE * port_def);
501 OMX_ERRORTYPE gst_omx_port_update_port_definition (GstOMXPort *port, OMX_PARAM_PORTDEFINITIONTYPE *port_definition);
503 GstOMXAcquireBufferReturn gst_omx_port_acquire_buffer (GstOMXPort *port, GstOMXBuffer **buf, GstOMXWait wait);
504 OMX_ERRORTYPE gst_omx_port_release_buffer (GstOMXPort *port, GstOMXBuffer *buf);
506 OMX_ERRORTYPE gst_omx_port_set_flushing (GstOMXPort *port, GstClockTime timeout, gboolean flush);
507 gboolean gst_omx_port_is_flushing (GstOMXPort *port);
509 OMX_ERRORTYPE gst_omx_port_allocate_buffers (GstOMXPort *port);
510 #ifdef TIZEN_FEATURE_OMX
511 OMX_ERRORTYPE gst_omx_port_tbm_allocate_dec_buffers (GstOMXPort * port);
512 OMX_ERRORTYPE gst_omx_port_tbm_allocate_enc_buffers (GstOMXPort * port);
513 OMX_ERRORTYPE gst_omx_component_get_extension_index (GstOMXComponent * comp, OMX_STRING name, gpointer index);
514 void gst_omx_port_flush_start (GstOMXPort * port, gboolean flush);
516 OMX_ERRORTYPE gst_omx_port_use_buffers (GstOMXPort *port, const GList *buffers);
517 OMX_ERRORTYPE gst_omx_port_use_eglimages (GstOMXPort *port, const GList *images);
518 OMX_ERRORTYPE gst_omx_port_deallocate_buffers (GstOMXPort *port);
519 OMX_ERRORTYPE gst_omx_port_populate (GstOMXPort *port);
520 OMX_ERRORTYPE gst_omx_port_wait_buffers_released (GstOMXPort * port, GstClockTime timeout);
521 void gst_omx_port_requeue_buffer (GstOMXPort * port, GstOMXBuffer * buf);
523 OMX_ERRORTYPE gst_omx_port_mark_reconfigured (GstOMXPort * port);
525 OMX_ERRORTYPE gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled);
526 OMX_ERRORTYPE gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout);
527 gboolean gst_omx_port_is_enabled (GstOMXPort * port);
528 gboolean gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra);
529 gboolean gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb);
531 gboolean gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf);
532 gboolean gst_omx_port_set_subframe (GstOMXPort * port, gboolean enabled);
533 gboolean gst_omx_port_get_subframe (GstOMXPort * port);
535 /* OMX 1.2.0 dynamic allocation mode */
536 gboolean gst_omx_is_dynamic_allocation_supported (void);
537 OMX_ERRORTYPE gst_omx_port_use_dynamic_buffers (GstOMXPort * port);
538 gboolean gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input, GstVideoInfo * info);
539 gboolean gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem);
540 gboolean gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input);
541 gboolean gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input);
543 void gst_omx_set_default_role (GstOMXClassData *class_data, const gchar *default_role);
545 /* refered by plugin_init */
546 GST_DEBUG_CATEGORY_EXTERN (gst_omx_video_debug_category);
550 #endif /* __GST_OMX_H__ */