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/allocators/gstdmabuf.h>
32 #include "gstomxmjpegdec.h"
33 #include "gstomxmpeg2videodec.h"
34 #include "gstomxmpeg4videodec.h"
35 #include "gstomxh264dec.h"
36 #include "gstomxh263dec.h"
37 #include "gstomxh265dec.h"
38 #include "gstomxvp8dec.h"
39 #include "gstomxtheoradec.h"
40 #include "gstomxwmvdec.h"
41 #include "gstomxmpeg4videoenc.h"
42 #include "gstomxh264enc.h"
43 #include "gstomxh263enc.h"
44 #include "gstomxh265enc.h"
45 #include "gstomxaacdec.h"
46 #include "gstomxmp3dec.h"
47 #include "gstomxmp3enc.h"
48 #include "gstomxaacenc.h"
49 #include "gstomxamrdec.h"
50 #include "gstomxanalogaudiosink.h"
51 #include "gstomxhdmiaudiosink.h"
53 GST_DEBUG_CATEGORY (gstomx_debug);
54 #define GST_CAT_DEFAULT gstomx_debug
56 GST_DEBUG_CATEGORY_STATIC (OMX_API_TRACE);
58 /* Macros used to log result of OMX calls. Use the requested debug level if the
59 * operation succeeded and GST_LEVEL_ERROR if not.
60 * Don't consider OMX_ErrorNoMore as an error as it means we're done iterating. */
61 #define DEBUG_IF_OK(obj,err,...) \
62 GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (err == OMX_ErrorNone || err == OMX_ErrorNoMore) ? GST_LEVEL_DEBUG : GST_LEVEL_ERROR, obj, __VA_ARGS__)
63 #define INFO_IF_OK(obj,err,...) \
64 GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (err == OMX_ErrorNone || err == OMX_ErrorNoMore) ? GST_LEVEL_INFO : GST_LEVEL_ERROR, obj, __VA_ARGS__)
66 G_LOCK_DEFINE_STATIC (core_handles);
67 static GHashTable *core_handles;
69 /* Cache used by gst_omx_buffer_flags_to_string() */
70 G_LOCK_DEFINE_STATIC (buffer_flags_str);
71 static GHashTable *buffer_flags_str;
74 gst_omx_core_acquire (const gchar * filename)
78 G_LOCK (core_handles);
81 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
83 core = g_hash_table_lookup (core_handles, filename);
85 core = g_slice_new0 (GstOMXCore);
86 g_mutex_init (&core->lock);
88 g_hash_table_insert (core_handles, g_strdup (filename), core);
90 /* Hack for the Broadcom OpenMAX IL implementation */
91 #ifdef USE_OMX_TARGET_RPI
94 if (g_str_has_suffix (filename, "vc/lib/libopenmaxil.so")) {
96 gchar *bcm_host_filename;
98 GModule *bcm_host_module;
99 void (*bcm_host_init) (void);
101 bcm_host_path = g_path_get_dirname (filename);
103 g_build_filename (bcm_host_path, "libbcm_host.so", NULL);
106 g_module_open (bcm_host_filename,
107 G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
109 g_free (bcm_host_filename);
110 g_free (bcm_host_path);
112 if (!bcm_host_module) {
113 /* Retry without an absolute path */
115 g_module_open ("libbcm_host.so",
116 G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
117 if (!bcm_host_module) {
118 GST_ERROR ("Failed to load libbcm_host.so");
123 if (!g_module_symbol (bcm_host_module, "bcm_host_init",
124 (gpointer *) & bcm_host_init)) {
125 GST_ERROR ("Failed to load symbol 'bcm_host_init' from libbcm_host.so");
133 g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
137 if (!g_module_symbol (core->module, "OMX_Init", (gpointer *) & core->init))
139 if (!g_module_symbol (core->module, "OMX_Deinit",
140 (gpointer *) & core->deinit))
142 if (!g_module_symbol (core->module, "OMX_GetHandle",
143 (gpointer *) & core->get_handle))
145 if (!g_module_symbol (core->module, "OMX_FreeHandle",
146 (gpointer *) & core->free_handle))
148 if (!g_module_symbol (core->module, "OMX_SetupTunnel",
149 (gpointer *) & core->setup_tunnel))
152 GST_DEBUG ("Successfully loaded core '%s'", filename);
155 g_mutex_lock (&core->lock);
157 if (core->user_count == 1) {
161 if (err != OMX_ErrorNone) {
162 GST_ERROR ("Failed to initialize core '%s': 0x%08x", filename, err);
163 g_mutex_unlock (&core->lock);
167 GST_DEBUG ("Successfully initialized core '%s'", filename);
170 g_mutex_unlock (&core->lock);
171 G_UNLOCK (core_handles);
177 GST_ERROR ("Failed to load module '%s': %s", filename, g_module_error ());
182 GST_ERROR ("Failed to locate required OpenMAX symbol in '%s': %s", filename,
184 g_module_close (core->module);
190 g_hash_table_remove (core_handles, filename);
191 g_mutex_clear (&core->lock);
192 g_slice_free (GstOMXCore, core);
194 G_UNLOCK (core_handles);
201 gst_omx_core_release (GstOMXCore * core)
203 g_return_if_fail (core != NULL);
205 G_LOCK (core_handles);
207 g_mutex_lock (&core->lock);
209 GST_DEBUG ("Releasing core %p", core);
212 if (core->user_count == 0) {
213 GST_DEBUG ("Deinit core %p", core);
216 G_LOCK (buffer_flags_str);
217 g_clear_pointer (&buffer_flags_str, g_hash_table_unref);
218 G_UNLOCK (buffer_flags_str);
221 g_mutex_unlock (&core->lock);
223 G_UNLOCK (core_handles);
226 /* NOTE: comp->messages_lock will be used */
228 gst_omx_component_flush_messages (GstOMXComponent * comp)
232 g_mutex_lock (&comp->messages_lock);
233 while ((msg = g_queue_pop_head (&comp->messages))) {
234 g_slice_free (GstOMXMessage, msg);
236 g_mutex_unlock (&comp->messages_lock);
240 gst_omx_buffer_reset (GstOMXBuffer * buf)
242 buf->omx_buf->nFlags = 0;
243 buf->omx_buf->nOffset = 0;
244 buf->omx_buf->nFilledLen = 0;
245 GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
248 static void gst_omx_buffer_unmap (GstOMXBuffer * buffer);
250 /* NOTE: Call with comp->lock, comp->messages_lock will be used */
252 gst_omx_component_handle_messages (GstOMXComponent * comp)
256 g_mutex_lock (&comp->messages_lock);
257 while ((msg = g_queue_pop_head (&comp->messages))) {
258 g_mutex_unlock (&comp->messages_lock);
261 case GST_OMX_MESSAGE_STATE_SET:{
262 GST_INFO_OBJECT (comp->parent, "%s state change to %s finished",
263 comp->name, gst_omx_state_to_string (msg->content.state_set.state));
264 comp->state = msg->content.state_set.state;
265 if (comp->state == comp->pending_state)
266 comp->pending_state = OMX_StateInvalid;
269 case GST_OMX_MESSAGE_FLUSH:{
270 GstOMXPort *port = NULL;
271 OMX_U32 index = msg->content.flush.port;
273 port = gst_omx_component_get_port (comp, index);
277 GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
280 if (port->flushing) {
281 port->flushed = TRUE;
283 GST_ERROR_OBJECT (comp->parent, "%s port %u was not flushing",
284 comp->name, port->index);
289 case GST_OMX_MESSAGE_ERROR:{
290 OMX_ERRORTYPE error = msg->content.error.error;
292 if (error == OMX_ErrorNone)
295 GST_ERROR_OBJECT (comp->parent, "%s got error: %s (0x%08x)", comp->name,
296 gst_omx_error_to_string (error), error);
298 /* We only set the first error ever from which
299 * we can't recover anymore.
301 if (comp->last_error == OMX_ErrorNone)
302 comp->last_error = error;
303 g_cond_broadcast (&comp->messages_cond);
307 case GST_OMX_MESSAGE_PORT_ENABLE:{
308 GstOMXPort *port = NULL;
309 OMX_U32 index = msg->content.port_enable.port;
310 OMX_BOOL enable = msg->content.port_enable.enable;
312 port = gst_omx_component_get_port (comp, index);
316 GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
317 port->index, (enable ? "enabled" : "disabled"));
320 port->enabled_pending = FALSE;
322 port->disabled_pending = FALSE;
325 case GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED:{
327 OMX_U32 index = msg->content.port_settings_changed.port;
328 GList *outports = NULL, *l, *k;
330 GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port %u)",
331 comp->name, (guint) index);
333 /* FIXME: This probably can be done better */
335 /* Now update the ports' states */
336 n = (comp->ports ? comp->ports->len : 0);
337 for (i = 0; i < n; i++) {
338 GstOMXPort *port = g_ptr_array_index (comp->ports, i);
340 if (index == OMX_ALL || index == port->index) {
341 port->settings_cookie++;
342 gst_omx_port_update_port_definition (port, NULL);
343 if (port->port_def.eDir == OMX_DirOutput && !port->tunneled)
344 outports = g_list_prepend (outports, port);
348 for (k = outports; k; k = k->next) {
349 gboolean found = FALSE;
351 for (l = comp->pending_reconfigure_outports; l; l = l->next) {
352 if (l->data == k->data) {
359 comp->pending_reconfigure_outports =
360 g_list_prepend (comp->pending_reconfigure_outports, k->data);
363 g_list_free (outports);
367 case GST_OMX_MESSAGE_BUFFER_FLAG:{
368 GstOMXPort *port = NULL;
369 OMX_U32 index = msg->content.buffer_flag.port;
370 OMX_U32 flags = msg->content.buffer_flag.flags;
372 port = gst_omx_component_get_port (comp, index);
376 GST_DEBUG_OBJECT (comp->parent,
377 "%s port %u got buffer flags 0x%08x (%s)", comp->name, port->index,
378 (guint) flags, gst_omx_buffer_flags_to_string (flags));
379 if ((flags & OMX_BUFFERFLAG_EOS)
380 && port->port_def.eDir == OMX_DirOutput && !port->eos) {
381 GST_DEBUG_OBJECT (comp->parent, "%s port %u is EOS", comp->name,
388 case GST_OMX_MESSAGE_BUFFER_DONE:{
389 GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate;
396 if (msg->content.buffer_done.empty) {
397 /* Input buffer is empty again and can be used to contain new input */
398 GST_LOG_OBJECT (port->comp->parent,
399 "%s port %u emptied buffer %p (%p)", port->comp->name,
400 port->index, buf, buf->omx_buf->pBuffer);
402 /* Reset all flags, some implementations don't
403 * reset them themselves and the flags are not
404 * valid anymore after the buffer was consumed
406 gst_omx_buffer_reset (buf);
408 /* Release and unmap the parent buffer, if any */
409 gst_omx_buffer_unmap (buf);
411 /* Output buffer contains output now or
412 * the port was flushed */
413 GST_LOG_OBJECT (port->comp->parent,
414 "%s port %u filled buffer %p (%p)", port->comp->name, port->index,
415 buf, buf->omx_buf->pBuffer);
417 if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS)
418 && port->port_def.eDir == OMX_DirOutput && !port->eos) {
419 GST_DEBUG_OBJECT (comp->parent, "%s port %u is EOS", comp->name,
425 /* If an input port is managed by a pool, the buffer will be ready to be
426 * filled again once it's been released to the pool. */
427 if (port->port_def.eDir == OMX_DirOutput || !port->using_pool) {
428 g_queue_push_tail (&port->pending_buffers, buf);
434 g_assert_not_reached ();
439 g_slice_free (GstOMXMessage, msg);
441 g_mutex_lock (&comp->messages_lock);
444 g_mutex_unlock (&comp->messages_lock);
447 /* NOTE: comp->messages_lock will be used */
449 gst_omx_component_send_message (GstOMXComponent * comp, GstOMXMessage * msg)
451 g_mutex_lock (&comp->messages_lock);
453 g_queue_push_tail (&comp->messages, msg);
454 g_cond_broadcast (&comp->messages_cond);
455 g_mutex_unlock (&comp->messages_lock);
458 /* NOTE: Call with comp->lock, comp->messages_lock will be used */
460 gst_omx_component_wait_message (GstOMXComponent * comp, GstClockTime timeout)
463 gint64 wait_until = -1;
465 if (timeout != GST_CLOCK_TIME_NONE) {
466 gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
471 wait_until = g_get_monotonic_time () + add;
472 GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
475 GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
478 g_mutex_lock (&comp->messages_lock);
479 g_mutex_unlock (&comp->lock);
481 if (!g_queue_is_empty (&comp->messages)) {
483 } else if (timeout == GST_CLOCK_TIME_NONE) {
484 g_cond_wait (&comp->messages_cond, &comp->messages_lock);
488 g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
492 g_mutex_unlock (&comp->messages_lock);
493 g_mutex_lock (&comp->lock);
499 omx_event_type_to_str (OMX_EVENTTYPE event)
502 case OMX_EventCmdComplete:
503 return "EventCmdComplete";
508 case OMX_EventPortSettingsChanged:
509 return "EventPortSettingsChanged";
510 case OMX_EventBufferFlag:
511 return "EventBufferFlag";
512 case OMX_EventResourcesAcquired:
513 return "EventResourcesAcquired";
514 case OMX_EventComponentResumed:
515 return "EventComponentResumed";
516 case OMX_EventDynamicResourcesAvailable:
517 return "EventDynamicResourcesAvailable";
518 case OMX_EventPortFormatDetected:
519 return "EventPortFormatDetected";
520 #ifdef OMX_EventIndexSettingChanged
521 case OMX_EventIndexSettingChanged:
522 return "EventIndexSettingChanged";
524 #ifdef OMX_EventPortNeedsDisable
525 case OMX_EventPortNeedsDisable:
526 return "EventPortNeedsDisable";
528 #ifdef OMX_EventPortNeedsFlush
529 case OMX_EventPortNeedsFlush:
530 return "EventPortNeedsFlush";
532 case OMX_EventKhronosExtensions:
533 case OMX_EventVendorStartUnused:
542 /* See "Table 3-11: Event Parameter Usage" */
543 static GstStructure *
544 omx_event_to_debug_struct (OMX_EVENTTYPE event,
545 guint32 data1, guint32 data2, gpointer event_data)
549 name = omx_event_type_to_str (event);
551 case OMX_EventCmdComplete:
553 const gchar *cmd = gst_omx_command_to_string (data1);
559 case OMX_CommandStateSet:
560 return gst_structure_new (name,
561 "command", G_TYPE_STRING, cmd,
562 "state-reached", G_TYPE_STRING, gst_omx_state_to_string (data2),
564 case OMX_CommandFlush:
565 case OMX_CommandPortDisable:
566 case OMX_CommandPortEnable:
567 case OMX_CommandMarkBuffer:
568 return gst_structure_new (name,
569 "command", G_TYPE_STRING, cmd, "port", G_TYPE_UINT, data2,
570 "error", G_TYPE_STRING,
571 gst_omx_error_to_string (GPOINTER_TO_UINT (event_data)), NULL);
572 case OMX_CommandKhronosExtensions:
573 case OMX_CommandVendorStartUnused:
580 return gst_structure_new (name, "error", G_TYPE_STRING,
581 gst_omx_error_to_string (data1), "extra-info", G_TYPE_STRING,
582 gst_omx_error_to_string (data2), NULL);
584 case OMX_EventComponentResumed:
585 case OMX_EventResourcesAcquired:
586 case OMX_EventDynamicResourcesAvailable:
587 case OMX_EventPortFormatDetected:
588 return gst_structure_new_empty (name);
589 case OMX_EventPortSettingsChanged:
590 #ifdef OMX_EventIndexSettingChanged
591 case OMX_EventIndexSettingChanged:
593 #ifdef OMX_EventPortNeedsDisable
594 case OMX_EventPortNeedsDisable:
596 #ifdef OMX_EventPortNeedsFlush
597 case OMX_EventPortNeedsFlush:
599 return gst_structure_new (name, "port", G_TYPE_UINT,
600 data1, "param-config", G_TYPE_UINT, data2, NULL);
601 case OMX_EventBufferFlag:
602 return gst_structure_new (name, "port", G_TYPE_UINT,
603 data1, "flags", G_TYPE_STRING, gst_omx_buffer_flags_to_string (data2),
605 case OMX_EventKhronosExtensions:
606 case OMX_EventVendorStartUnused:
616 log_omx_api_trace_event (GstOMXComponent * comp, OMX_EVENTTYPE event,
617 guint32 data1, guint32 data2, gpointer event_data)
619 #ifndef GST_DISABLE_GST_DEBUG
622 /* Don't bother creating useless structs if not needed */
623 if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_DEBUG)
626 s = omx_event_to_debug_struct (event, data1, data2, event_data);
628 GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
629 "invalid event 0x%08x Data1 %u Data2 %u EventData %p", event, data1,
634 GST_CAT_DEBUG_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
636 gst_structure_free (s);
637 #endif /* GST_DISABLE_GST_DEBUG */
641 EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
642 OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData)
644 GstOMXComponent *comp = (GstOMXComponent *) pAppData;
646 log_omx_api_trace_event (comp, eEvent, nData1, nData2, pEventData);
649 case OMX_EventCmdComplete:
651 OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) nData1;
653 GST_DEBUG_OBJECT (comp->parent, "%s %s command complete (%d)",
654 comp->name, gst_omx_command_to_string (cmd), cmd);
657 case OMX_CommandStateSet:{
658 GstOMXMessage *msg = g_slice_new (GstOMXMessage);
660 msg->type = GST_OMX_MESSAGE_STATE_SET;
661 msg->content.state_set.state = nData2;
663 GST_DEBUG_OBJECT (comp->parent, "%s state change to %s finished",
665 gst_omx_state_to_string (msg->content.state_set.state));
667 gst_omx_component_send_message (comp, msg);
670 case OMX_CommandFlush:{
671 GstOMXMessage *msg = g_slice_new (GstOMXMessage);
673 msg->type = GST_OMX_MESSAGE_FLUSH;
674 msg->content.flush.port = nData2;
675 GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
676 (guint) msg->content.flush.port);
678 gst_omx_component_send_message (comp, msg);
681 case OMX_CommandPortEnable:
682 case OMX_CommandPortDisable:{
683 GstOMXMessage *msg = g_slice_new (GstOMXMessage);
685 msg->type = GST_OMX_MESSAGE_PORT_ENABLE;
686 msg->content.port_enable.port = nData2;
687 msg->content.port_enable.enable = (cmd == OMX_CommandPortEnable);
688 GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
689 (guint) msg->content.port_enable.port,
690 (msg->content.port_enable.enable ? "enabled" : "disabled"));
692 gst_omx_component_send_message (comp, msg);
703 OMX_ERRORTYPE error_type = nData1;
705 /* Yes, this really happens... */
706 if (error_type == OMX_ErrorNone)
709 /* Always ignore PortUnpopulated error. This error is informational
710 * at best but it is useful for debugging some strange scenarios.
712 if (error_type == OMX_ErrorPortUnpopulated) {
713 GST_DEBUG_OBJECT (comp->parent, "%s got error: %s (0x%08x)",
714 comp->name, gst_omx_error_to_string (error_type), error_type);
718 msg = g_slice_new (GstOMXMessage);
720 msg->type = GST_OMX_MESSAGE_ERROR;
721 msg->content.error.error = error_type;
722 GST_ERROR_OBJECT (comp->parent, "%s got error: %s (0x%08x)", comp->name,
723 gst_omx_error_to_string (msg->content.error.error),
724 msg->content.error.error);
726 gst_omx_component_send_message (comp, msg);
729 case OMX_EventPortSettingsChanged:
731 GstOMXMessage *msg = g_slice_new (GstOMXMessage);
735 GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP)) {
744 GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1))
748 msg->type = GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED;
749 msg->content.port_settings_changed.port = index;
750 GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port index: %u)",
751 comp->name, (guint) msg->content.port_settings_changed.port);
753 gst_omx_component_send_message (comp, msg);
756 case OMX_EventBufferFlag:{
759 msg = g_slice_new (GstOMXMessage);
761 msg->type = GST_OMX_MESSAGE_BUFFER_FLAG;
762 msg->content.buffer_flag.port = nData1;
763 msg->content.buffer_flag.flags = nData2;
764 GST_DEBUG_OBJECT (comp->parent, "%s port %u got buffer flags 0x%08x (%s)",
765 comp->name, (guint) msg->content.buffer_flag.port,
766 (guint) msg->content.buffer_flag.flags,
767 gst_omx_buffer_flags_to_string (msg->content.buffer_flag.flags));
769 gst_omx_component_send_message (comp, msg);
772 case OMX_EventPortFormatDetected:
774 GST_DEBUG_OBJECT (comp->parent, "%s unknown event 0x%08x", comp->name,
779 return OMX_ErrorNone;
783 gst_omx_buffer_unmap (GstOMXBuffer * buffer)
785 g_return_if_fail (buffer != NULL);
787 if (buffer->input_frame_mapped) {
788 g_assert (!buffer->input_mem);
789 g_assert (!buffer->input_buffer);
790 g_assert (!buffer->input_buffer_mapped);
791 gst_video_frame_unmap (&buffer->input_frame);
792 buffer->input_frame_mapped = FALSE;
793 } else if (buffer->input_mem) {
794 g_assert (!buffer->input_buffer);
795 g_assert (!buffer->input_buffer_mapped);
796 gst_memory_unmap (buffer->input_mem, &buffer->map);
797 g_clear_pointer (&buffer->input_mem, gst_memory_unref);
798 } else if (buffer->input_buffer) {
799 if (buffer->input_buffer_mapped)
800 gst_buffer_unmap (buffer->input_buffer, &buffer->map);
801 buffer->input_buffer_mapped = FALSE;
802 g_clear_pointer (&buffer->input_buffer, gst_buffer_unref);
807 log_omx_api_trace_buffer (GstOMXComponent * comp, const gchar * event,
810 #ifndef GST_DISABLE_GST_DEBUG
813 /* Don't bother creating useless structs if not needed */
814 if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_TRACE)
818 gchar *buf_str, *omx_buf_str, *pbuffer_str;
820 /* GST_PTR_FORMAT won't serialize G_TYPE_POINTER fields so stringify pointers */
821 buf_str = g_strdup_printf ("%p", buf);
822 omx_buf_str = g_strdup_printf ("%p", buf->omx_buf);
823 pbuffer_str = g_strdup_printf ("%p", buf->omx_buf->pBuffer);
826 s = gst_structure_new (event,
827 "GstOMXBuffer", G_TYPE_STRING, buf_str,
828 "OMX-buffer", G_TYPE_STRING, omx_buf_str,
829 "pBuffer", G_TYPE_STRING, pbuffer_str,
830 "TimeStamp", G_TYPE_UINT64, GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
831 "AllocLen", G_TYPE_UINT, buf->omx_buf->nAllocLen,
832 "FilledLen", G_TYPE_UINT, buf->omx_buf->nFilledLen,
833 "flags", G_TYPE_UINT, buf->omx_buf->nFlags,
834 "flags-str", G_TYPE_STRING, gst_omx_buffer_flags_to_string (buf->omx_buf->nFlags),
839 g_free (omx_buf_str);
840 g_free (pbuffer_str);
842 s = gst_structure_new_empty (event);
845 GST_CAT_TRACE_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
847 gst_structure_free (s);
848 #endif /* GST_DISABLE_GST_DEBUG */
852 EmptyBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
853 OMX_BUFFERHEADERTYPE * pBuffer)
856 GstOMXComponent *comp;
859 buf = pBuffer->pAppPrivate;
861 GST_ERROR ("Have unknown or deallocated buffer %p", pBuffer);
862 return OMX_ErrorNone;
865 g_assert (buf->omx_buf == pBuffer);
867 if (buf->port->tunneled) {
868 GST_ERROR ("EmptyBufferDone on tunneled port");
869 return OMX_ErrorBadParameter;
872 comp = buf->port->comp;
874 msg = g_slice_new (GstOMXMessage);
875 msg->type = GST_OMX_MESSAGE_BUFFER_DONE;
876 msg->content.buffer_done.component = hComponent;
877 msg->content.buffer_done.app_data = pAppData;
878 msg->content.buffer_done.buffer = pBuffer;
879 msg->content.buffer_done.empty = OMX_TRUE;
881 log_omx_api_trace_buffer (comp, "EmptyBufferDone", buf);
882 GST_LOG_OBJECT (comp->parent, "%s port %u emptied buffer %p (%p)",
883 comp->name, buf->port->index, buf, buf->omx_buf->pBuffer);
885 gst_omx_component_send_message (comp, msg);
887 return OMX_ErrorNone;
891 FillBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
892 OMX_BUFFERHEADERTYPE * pBuffer)
895 GstOMXComponent *comp;
898 buf = pBuffer->pAppPrivate;
900 GST_ERROR ("Have unknown or deallocated buffer %p", pBuffer);
901 return OMX_ErrorNone;
904 g_assert (buf->omx_buf == pBuffer);
906 if (buf->port->tunneled) {
907 GST_ERROR ("FillBufferDone on tunneled port");
908 return OMX_ErrorBadParameter;
911 comp = buf->port->comp;
913 msg = g_slice_new (GstOMXMessage);
914 msg->type = GST_OMX_MESSAGE_BUFFER_DONE;
915 msg->content.buffer_done.component = hComponent;
916 msg->content.buffer_done.app_data = pAppData;
917 msg->content.buffer_done.buffer = pBuffer;
918 msg->content.buffer_done.empty = OMX_FALSE;
920 log_omx_api_trace_buffer (comp, "FillBufferDone", buf);
921 GST_LOG_OBJECT (comp->parent, "%s port %u filled buffer %p (%p)", comp->name,
922 buf->port->index, buf, buf->omx_buf->pBuffer);
924 gst_omx_component_send_message (comp, msg);
926 return OMX_ErrorNone;
929 static OMX_CALLBACKTYPE callbacks =
930 { EventHandler, EmptyBufferDone, FillBufferDone };
932 GST_DEFINE_MINI_OBJECT_TYPE (GstOMXComponent, gst_omx_component);
934 static void gst_omx_component_free (GstOMXComponent * comp);
936 /* NOTE: Uses comp->lock and comp->messages_lock */
938 gst_omx_component_new (GstObject * parent, const gchar * core_name,
939 const gchar * component_name, const gchar * component_role, guint64 hacks)
943 GstOMXComponent *comp;
946 core = gst_omx_core_acquire (core_name);
950 comp = g_slice_new0 (GstOMXComponent);
953 gst_mini_object_init (GST_MINI_OBJECT_CAST (comp), 0,
954 gst_omx_component_get_type (), NULL, NULL,
955 (GstMiniObjectFreeFunction) gst_omx_component_free);
957 if ((dot = g_strrstr (component_name, ".")))
958 comp->name = g_strdup (dot + 1);
960 comp->name = g_strdup (component_name);
963 core->get_handle (&comp->handle, (OMX_STRING) component_name, comp,
965 if (err != OMX_ErrorNone) {
966 GST_ERROR_OBJECT (parent,
967 "Failed to get component handle '%s' from core '%s': 0x%08x",
968 component_name, core_name, err);
969 gst_omx_core_release (core);
971 g_slice_free (GstOMXComponent, comp);
974 GST_DEBUG_OBJECT (parent,
975 "Successfully got component handle %p (%s) from core '%s'", comp->handle,
976 component_name, core_name);
977 comp->parent = gst_object_ref (parent);
980 comp->ports = g_ptr_array_new ();
981 comp->n_in_ports = 0;
982 comp->n_out_ports = 0;
984 g_mutex_init (&comp->lock);
985 g_mutex_init (&comp->messages_lock);
986 g_cond_init (&comp->messages_cond);
988 g_queue_init (&comp->messages);
989 comp->pending_state = OMX_StateInvalid;
990 comp->last_error = OMX_ErrorNone;
992 /* Set component role if any */
993 if (component_role && !(hacks & GST_OMX_HACK_NO_COMPONENT_ROLE)) {
994 OMX_PARAM_COMPONENTROLETYPE param;
996 GST_OMX_INIT_STRUCT (¶m);
998 g_strlcpy ((gchar *) param.cRole, component_role, sizeof (param.cRole));
1000 gst_omx_component_set_parameter (comp,
1001 OMX_IndexParamStandardComponentRole, ¶m);
1003 DEBUG_IF_OK (comp->parent, err,
1004 "Setting component role to '%s': %s (0x%08x)", component_role,
1005 gst_omx_error_to_string (err), err);
1007 /* If setting the role failed this component is unusable */
1008 if (err != OMX_ErrorNone) {
1009 gst_omx_component_free (comp);
1014 OMX_GetState (comp->handle, &comp->state);
1016 g_mutex_lock (&comp->lock);
1017 gst_omx_component_handle_messages (comp);
1018 g_mutex_unlock (&comp->lock);
1023 /* NOTE: Uses comp->messages_lock */
1025 gst_omx_component_free (GstOMXComponent * comp)
1029 g_return_if_fail (comp != NULL);
1031 GST_INFO_OBJECT (comp->parent, "Unloading component %p %s", comp, comp->name);
1034 n = comp->ports->len;
1035 for (i = 0; i < n; i++) {
1036 GstOMXPort *port = g_ptr_array_index (comp->ports, i);
1038 gst_omx_port_deallocate_buffers (port);
1039 g_assert (port->buffers == NULL);
1040 g_assert (g_queue_get_length (&port->pending_buffers) == 0);
1042 g_slice_free (GstOMXPort, port);
1044 g_ptr_array_unref (comp->ports);
1048 comp->core->free_handle (comp->handle);
1049 gst_omx_core_release (comp->core);
1051 gst_omx_component_flush_messages (comp);
1053 g_cond_clear (&comp->messages_cond);
1054 g_mutex_clear (&comp->messages_lock);
1055 g_mutex_clear (&comp->lock);
1057 gst_object_unref (comp->parent);
1059 g_free (comp->name);
1062 g_slice_free (GstOMXComponent, comp);
1066 gst_omx_component_ref (GstOMXComponent * comp)
1068 g_return_val_if_fail (comp, NULL);
1070 gst_mini_object_ref (GST_MINI_OBJECT_CAST (comp));
1075 gst_omx_component_unref (GstOMXComponent * comp)
1077 g_return_if_fail (comp);
1079 gst_mini_object_unref (GST_MINI_OBJECT_CAST (comp));
1082 static GstStructure *
1083 omx_command_to_debug_struct (OMX_COMMANDTYPE cmd,
1084 guint32 param, gpointer cmd_data)
1086 const gchar *cmd_str;
1088 cmd_str = gst_omx_command_to_string (cmd);
1091 case OMX_CommandStateSet:
1092 return gst_structure_new ("SendCommand",
1093 "command", G_TYPE_STRING, cmd_str,
1094 "state", G_TYPE_STRING, gst_omx_state_to_string (param), NULL);
1095 case OMX_CommandFlush:
1096 case OMX_CommandPortDisable:
1097 case OMX_CommandPortEnable:
1098 return gst_structure_new ("SendCommand",
1099 "command", G_TYPE_STRING, cmd_str, "port", G_TYPE_UINT, param, NULL);
1100 case OMX_CommandMarkBuffer:
1101 return gst_structure_new ("SendCommand",
1102 "command", G_TYPE_STRING, cmd_str,
1103 "mark-type", G_TYPE_POINTER, cmd_data, NULL);
1104 case OMX_CommandKhronosExtensions:
1105 case OMX_CommandVendorStartUnused:
1106 case OMX_CommandMax:
1115 log_omx_api_trace_send_command (GstOMXComponent * comp, OMX_COMMANDTYPE cmd,
1116 guint32 param, gpointer cmd_data)
1118 #ifndef GST_DISABLE_GST_DEBUG
1121 /* Don't bother creating useless structs if not needed */
1122 if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_DEBUG)
1125 s = omx_command_to_debug_struct (cmd, param, cmd_data);
1127 GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
1128 "invalid command 0x%08x Param %u CmdData %p", cmd, param, cmd_data);
1132 GST_CAT_DEBUG_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
1134 gst_structure_free (s);
1135 #endif /* GST_DISABLE_GST_DEBUG */
1138 static OMX_ERRORTYPE
1139 gst_omx_component_send_command (GstOMXComponent * comp, OMX_COMMANDTYPE cmd,
1140 guint32 param, gpointer cmd_data)
1144 log_omx_api_trace_send_command (comp, cmd, param, cmd_data);
1145 err = OMX_SendCommand (comp->handle, cmd, param, cmd_data);
1150 /* NOTE: Uses comp->lock and comp->messages_lock */
1152 gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state)
1154 OMX_STATETYPE old_state;
1155 OMX_ERRORTYPE err = OMX_ErrorNone;
1157 g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
1159 g_mutex_lock (&comp->lock);
1161 gst_omx_component_handle_messages (comp);
1163 old_state = comp->state;
1164 GST_INFO_OBJECT (comp->parent, "Setting %s state from %s to %s", comp->name,
1165 gst_omx_state_to_string (old_state), gst_omx_state_to_string (state));
1167 if ((err = comp->last_error) != OMX_ErrorNone && state > old_state) {
1168 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
1169 comp->name, gst_omx_error_to_string (err), err);
1173 if (old_state == state || comp->pending_state == state) {
1174 GST_DEBUG_OBJECT (comp->parent, "Component %s already in state %s",
1175 comp->name, gst_omx_state_to_string (state));
1179 comp->pending_state = state;
1181 /* Reset some things */
1182 if ((old_state == OMX_StateExecuting || old_state == OMX_StatePause)
1183 && state < old_state) {
1184 g_list_free (comp->pending_reconfigure_outports);
1185 comp->pending_reconfigure_outports = NULL;
1186 /* Notify all inports that are still waiting */
1187 gst_omx_component_send_message (comp, NULL);
1190 err = gst_omx_component_send_command (comp, OMX_CommandStateSet, state, NULL);
1191 /* No need to check if anything has changed here */
1195 gst_omx_component_handle_messages (comp);
1197 if (err != OMX_ErrorNone && comp->last_error == OMX_ErrorNone) {
1198 GST_ERROR_OBJECT (comp->parent,
1199 "Last operation returned an error. Setting last_error manually.");
1200 comp->last_error = err;
1203 g_mutex_unlock (&comp->lock);
1205 if (err != OMX_ErrorNone) {
1206 GST_ERROR_OBJECT (comp->parent,
1207 "Error setting %s state from %s to %s: %s (0x%08x)", comp->name,
1208 gst_omx_state_to_string (old_state), gst_omx_state_to_string (state),
1209 gst_omx_error_to_string (err), err);
1214 /* NOTE: Uses comp->lock and comp->messages_lock */
1216 gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout)
1219 gboolean signalled = TRUE;
1221 g_return_val_if_fail (comp != NULL, OMX_StateInvalid);
1223 GST_DEBUG_OBJECT (comp->parent, "Getting state of %s", comp->name);
1225 g_mutex_lock (&comp->lock);
1227 gst_omx_component_handle_messages (comp);
1229 if (comp->last_error != OMX_ErrorNone) {
1230 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
1231 comp->name, gst_omx_error_to_string (comp->last_error),
1233 ret = OMX_StateInvalid;
1238 if (comp->pending_state == OMX_StateInvalid)
1241 while (signalled && comp->last_error == OMX_ErrorNone
1242 && comp->pending_state != OMX_StateInvalid) {
1244 signalled = gst_omx_component_wait_message (comp, timeout);
1246 gst_omx_component_handle_messages (comp);
1250 if (comp->last_error != OMX_ErrorNone) {
1251 GST_ERROR_OBJECT (comp->parent,
1252 "%s got error while waiting for state change: %s (0x%08x)",
1253 comp->name, gst_omx_error_to_string (comp->last_error),
1255 ret = OMX_StateInvalid;
1256 } else if (comp->pending_state == OMX_StateInvalid) {
1257 /* State change finished and everything's fine */
1260 ret = OMX_StateInvalid;
1261 g_assert_not_reached ();
1264 ret = OMX_StateInvalid;
1265 GST_WARNING_OBJECT (comp->parent, "%s timeout while waiting for state "
1266 "change", comp->name);
1270 g_mutex_unlock (&comp->lock);
1272 GST_DEBUG_OBJECT (comp->parent, "%s returning state %s", comp->name,
1273 gst_omx_state_to_string (ret));
1279 gst_omx_component_add_port (GstOMXComponent * comp, guint32 index)
1283 OMX_PARAM_PORTDEFINITIONTYPE port_def;
1286 g_return_val_if_fail (comp != NULL, NULL);
1288 /* Check if this port exists already */
1289 n = comp->ports->len;
1290 for (i = 0; i < n; i++) {
1291 port = g_ptr_array_index (comp->ports, i);
1292 g_return_val_if_fail (port->index != index, NULL);
1295 GST_DEBUG_OBJECT (comp->parent, "%s adding port %u", comp->name, index);
1297 GST_OMX_INIT_STRUCT (&port_def);
1298 port_def.nPortIndex = index;
1300 err = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
1302 if (err != OMX_ErrorNone) {
1303 GST_ERROR_OBJECT (comp->parent, "%s failed to add port %u: %s (0x%08x)",
1304 comp->name, index, gst_omx_error_to_string (err), err);
1308 port = g_slice_new0 (GstOMXPort);
1310 port->index = index;
1312 port->tunneled = FALSE;
1314 port->port_def = port_def;
1316 g_queue_init (&port->pending_buffers);
1317 port->flushing = TRUE;
1318 port->flushed = FALSE;
1319 port->enabled_pending = FALSE;
1320 port->disabled_pending = FALSE;
1322 port->using_pool = FALSE;
1324 if (port->port_def.eDir == OMX_DirInput)
1327 comp->n_out_ports++;
1329 g_ptr_array_add (comp->ports, port);
1335 gst_omx_component_get_port (GstOMXComponent * comp, guint32 index)
1339 n = comp->ports->len;
1340 for (i = 0; i < n; i++) {
1341 GstOMXPort *tmp = g_ptr_array_index (comp->ports, i);
1343 if (tmp->index == index)
1349 /* NOTE: Uses comp->lock and comp->messages_lock */
1351 gst_omx_component_get_last_error (GstOMXComponent * comp)
1355 g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
1357 g_mutex_lock (&comp->lock);
1358 gst_omx_component_handle_messages (comp);
1359 err = comp->last_error;
1360 g_mutex_unlock (&comp->lock);
1362 GST_DEBUG_OBJECT (comp->parent, "Returning last %s error: %s (0x%08x)",
1363 comp->name, gst_omx_error_to_string (err), err);
1369 gst_omx_component_get_last_error_string (GstOMXComponent * comp)
1371 g_return_val_if_fail (comp != NULL, NULL);
1373 return gst_omx_error_to_string (gst_omx_component_get_last_error (comp));
1376 #ifndef GST_DISABLE_GST_DEBUG
1377 static const gchar *
1378 omx_index_type_to_str (OMX_INDEXTYPE index)
1381 case OMX_IndexComponentStartUnused:
1382 return "OMX_IndexComponentStartUnused";
1383 case OMX_IndexParamPriorityMgmt:
1384 return "OMX_IndexParamPriorityMgmt";
1385 case OMX_IndexParamAudioInit:
1386 return "OMX_IndexParamAudioInit";
1387 case OMX_IndexParamImageInit:
1388 return "OMX_IndexParamImageInit";
1389 case OMX_IndexParamVideoInit:
1390 return "OMX_IndexParamVideoInit";
1391 case OMX_IndexParamOtherInit:
1392 return "OMX_IndexParamOtherInit";
1393 case OMX_IndexParamNumAvailableStreams:
1394 return "OMX_IndexParamNumAvailableStreams";
1395 case OMX_IndexParamActiveStream:
1396 return "OMX_IndexParamActiveStream";
1397 case OMX_IndexParamSuspensionPolicy:
1398 return "OMX_IndexParamSuspensionPolicy";
1399 case OMX_IndexParamComponentSuspended:
1400 return "OMX_IndexParamComponentSuspended";
1401 case OMX_IndexConfigCapturing:
1402 return "OMX_IndexConfigCapturing";
1403 case OMX_IndexConfigCaptureMode:
1404 return "OMX_IndexConfigCaptureMode";
1405 case OMX_IndexAutoPauseAfterCapture:
1406 return "OMX_IndexAutoPauseAfterCapture";
1407 case OMX_IndexParamContentURI:
1408 return "OMX_IndexParamContentURI";
1409 case OMX_IndexParamDisableResourceConcealment:
1410 return "OMX_IndexParamDisableResourceConcealment";
1411 case OMX_IndexConfigMetadataItemCount:
1412 return "OMX_IndexConfigMetadataItemCount";
1413 case OMX_IndexConfigContainerNodeCount:
1414 return "OMX_IndexConfigContainerNodeCount";
1415 case OMX_IndexConfigMetadataItem:
1416 return "OMX_IndexConfigMetadataItem";
1417 case OMX_IndexConfigCounterNodeID:
1418 return "OMX_IndexConfigCounterNodeID";
1419 case OMX_IndexParamMetadataFilterType:
1420 return "OMX_IndexParamMetadataFilterType";
1421 case OMX_IndexParamMetadataKeyFilter:
1422 return "OMX_IndexParamMetadataKeyFilter";
1423 case OMX_IndexConfigPriorityMgmt:
1424 return "OMX_IndexConfigPriorityMgmt";
1425 case OMX_IndexParamStandardComponentRole:
1426 return "OMX_IndexParamStandardComponentRole";
1427 case OMX_IndexPortStartUnused:
1428 return "OMX_IndexPortStartUnused";
1429 case OMX_IndexParamPortDefinition:
1430 return "OMX_IndexParamPortDefinition";
1431 case OMX_IndexParamCompBufferSupplier:
1432 return "OMX_IndexParamCompBufferSupplier";
1433 case OMX_IndexReservedStartUnused:
1434 return "OMX_IndexReservedStartUnused";
1435 case OMX_IndexAudioStartUnused:
1436 return "OMX_IndexAudioStartUnused";
1437 case OMX_IndexParamAudioPortFormat:
1438 return "OMX_IndexParamAudioPortFormat";
1439 case OMX_IndexParamAudioPcm:
1440 return "OMX_IndexParamAudioPcm";
1441 case OMX_IndexParamAudioAac:
1442 return "OMX_IndexParamAudioAac";
1443 case OMX_IndexParamAudioRa:
1444 return "OMX_IndexParamAudioRa";
1445 case OMX_IndexParamAudioMp3:
1446 return "OMX_IndexParamAudioMp3";
1447 case OMX_IndexParamAudioAdpcm:
1448 return "OMX_IndexParamAudioAdpcm";
1449 case OMX_IndexParamAudioG723:
1450 return "OMX_IndexParamAudioG723";
1451 case OMX_IndexParamAudioG729:
1452 return "OMX_IndexParamAudioG729";
1453 case OMX_IndexParamAudioAmr:
1454 return "OMX_IndexParamAudioAmr";
1455 case OMX_IndexParamAudioWma:
1456 return "OMX_IndexParamAudioWma";
1457 case OMX_IndexParamAudioSbc:
1458 return "OMX_IndexParamAudioSbc";
1459 case OMX_IndexParamAudioMidi:
1460 return "OMX_IndexParamAudioMidi";
1461 case OMX_IndexParamAudioGsm_FR:
1462 return "OMX_IndexParamAudioGsm_FR";
1463 case OMX_IndexParamAudioMidiLoadUserSound:
1464 return "OMX_IndexParamAudioMidiLoadUserSound";
1465 case OMX_IndexParamAudioG726:
1466 return "OMX_IndexParamAudioG726";
1467 case OMX_IndexParamAudioGsm_EFR:
1468 return "OMX_IndexParamAudioGsm_EFR";
1469 case OMX_IndexParamAudioGsm_HR:
1470 return "OMX_IndexParamAudioGsm_HR";
1471 case OMX_IndexParamAudioPdc_FR:
1472 return "OMX_IndexParamAudioPdc_FR";
1473 case OMX_IndexParamAudioPdc_EFR:
1474 return "OMX_IndexParamAudioPdc_EFR";
1475 case OMX_IndexParamAudioPdc_HR:
1476 return "OMX_IndexParamAudioPdc_HR";
1477 case OMX_IndexParamAudioTdma_FR:
1478 return "OMX_IndexParamAudioTdma_FR";
1479 case OMX_IndexParamAudioTdma_EFR:
1480 return "OMX_IndexParamAudioTdma_EFR";
1481 case OMX_IndexParamAudioQcelp8:
1482 return "OMX_IndexParamAudioQcelp8";
1483 case OMX_IndexParamAudioQcelp13:
1484 return "OMX_IndexParamAudioQcelp13";
1485 case OMX_IndexParamAudioEvrc:
1486 return "OMX_IndexParamAudioEvrc";
1487 case OMX_IndexParamAudioSmv:
1488 return "OMX_IndexParamAudioSmv";
1489 case OMX_IndexParamAudioVorbis:
1490 return "OMX_IndexParamAudioVorbis";
1491 case OMX_IndexConfigAudioMidiImmediateEvent:
1492 return "OMX_IndexConfigAudioMidiImmediateEvent";
1493 case OMX_IndexConfigAudioMidiControl:
1494 return "OMX_IndexConfigAudioMidiControl";
1495 case OMX_IndexConfigAudioMidiSoundBankProgram:
1496 return "OMX_IndexConfigAudioMidiSoundBankProgram";
1497 case OMX_IndexConfigAudioMidiStatus:
1498 return "OMX_IndexConfigAudioMidiStatus";
1499 case OMX_IndexConfigAudioMidiMetaEvent:
1500 return "OMX_IndexConfigAudioMidiMetaEvent";
1501 case OMX_IndexConfigAudioMidiMetaEventData:
1502 return "OMX_IndexConfigAudioMidiMetaEventData";
1503 case OMX_IndexConfigAudioVolume:
1504 return "OMX_IndexConfigAudioVolume";
1505 case OMX_IndexConfigAudioBalance:
1506 return "OMX_IndexConfigAudioBalance";
1507 case OMX_IndexConfigAudioChannelMute:
1508 return "OMX_IndexConfigAudioChannelMute";
1509 case OMX_IndexConfigAudioMute:
1510 return "OMX_IndexConfigAudioMute";
1511 case OMX_IndexConfigAudioLoudness:
1512 return "OMX_IndexConfigAudioLoudness";
1513 case OMX_IndexConfigAudioEchoCancelation:
1514 return "OMX_IndexConfigAudioEchoCancelation";
1515 case OMX_IndexConfigAudioNoiseReduction:
1516 return "OMX_IndexConfigAudioNoiseReduction";
1517 case OMX_IndexConfigAudioBass:
1518 return "OMX_IndexConfigAudioBass";
1519 case OMX_IndexConfigAudioTreble:
1520 return "OMX_IndexConfigAudioTreble";
1521 case OMX_IndexConfigAudioStereoWidening:
1522 return "OMX_IndexConfigAudioStereoWidening";
1523 case OMX_IndexConfigAudioChorus:
1524 return "OMX_IndexConfigAudioChorus";
1525 case OMX_IndexConfigAudioEqualizer:
1526 return "OMX_IndexConfigAudioEqualizer";
1527 case OMX_IndexConfigAudioReverberation:
1528 return "OMX_IndexConfigAudioReverberation";
1529 case OMX_IndexConfigAudioChannelVolume:
1530 return "OMX_IndexConfigAudioChannelVolume";
1531 case OMX_IndexImageStartUnused:
1532 return "OMX_IndexImageStartUnused";
1533 case OMX_IndexParamImagePortFormat:
1534 return "OMX_IndexParamImagePortFormat";
1535 case OMX_IndexParamFlashControl:
1536 return "OMX_IndexParamFlashControl";
1537 case OMX_IndexConfigFocusControl:
1538 return "OMX_IndexConfigFocusControl";
1539 case OMX_IndexParamQFactor:
1540 return "OMX_IndexParamQFactor";
1541 case OMX_IndexParamQuantizationTable:
1542 return "OMX_IndexParamQuantizationTable";
1543 case OMX_IndexParamHuffmanTable:
1544 return "OMX_IndexParamHuffmanTable";
1545 case OMX_IndexConfigFlashControl:
1546 return "OMX_IndexConfigFlashControl";
1547 case OMX_IndexVideoStartUnused:
1548 return "OMX_IndexVideoStartUnused";
1549 case OMX_IndexParamVideoPortFormat:
1550 return "OMX_IndexParamVideoPortFormat";
1551 case OMX_IndexParamVideoQuantization:
1552 return "OMX_IndexParamVideoQuantization";
1553 case OMX_IndexParamVideoFastUpdate:
1554 return "OMX_IndexParamVideoFastUpdate";
1555 case OMX_IndexParamVideoBitrate:
1556 return "OMX_IndexParamVideoBitrate";
1557 case OMX_IndexParamVideoMotionVector:
1558 return "OMX_IndexParamVideoMotionVector";
1559 case OMX_IndexParamVideoIntraRefresh:
1560 return "OMX_IndexParamVideoIntraRefresh";
1561 case OMX_IndexParamVideoErrorCorrection:
1562 return "OMX_IndexParamVideoErrorCorrection";
1563 case OMX_IndexParamVideoVBSMC:
1564 return "OMX_IndexParamVideoVBSMC";
1565 case OMX_IndexParamVideoMpeg2:
1566 return "OMX_IndexParamVideoMpeg2";
1567 case OMX_IndexParamVideoMpeg4:
1568 return "OMX_IndexParamVideoMpeg4";
1569 case OMX_IndexParamVideoWmv:
1570 return "OMX_IndexParamVideoWmv";
1571 case OMX_IndexParamVideoRv:
1572 return "OMX_IndexParamVideoRv";
1573 case OMX_IndexParamVideoAvc:
1574 return "OMX_IndexParamVideoAvc";
1575 case OMX_IndexParamVideoH263:
1576 return "OMX_IndexParamVideoH263";
1577 case OMX_IndexParamVideoProfileLevelQuerySupported:
1578 return "OMX_IndexParamVideoProfileLevelQuerySupported";
1579 case OMX_IndexParamVideoProfileLevelCurrent:
1580 return "OMX_IndexParamVideoProfileLevelCurrent";
1581 case OMX_IndexConfigVideoBitrate:
1582 return "OMX_IndexConfigVideoBitrate";
1583 case OMX_IndexConfigVideoFramerate:
1584 return "OMX_IndexConfigVideoFramerate";
1585 case OMX_IndexConfigVideoIntraVOPRefresh:
1586 return "OMX_IndexConfigVideoIntraVOPRefresh";
1587 case OMX_IndexConfigVideoIntraMBRefresh:
1588 return "OMX_IndexConfigVideoIntraMBRefresh";
1589 case OMX_IndexConfigVideoMBErrorReporting:
1590 return "OMX_IndexConfigVideoMBErrorReporting";
1591 case OMX_IndexParamVideoMacroblocksPerFrame:
1592 return "OMX_IndexParamVideoMacroblocksPerFrame";
1593 case OMX_IndexConfigVideoMacroBlockErrorMap:
1594 return "OMX_IndexConfigVideoMacroBlockErrorMap";
1595 case OMX_IndexParamVideoSliceFMO:
1596 return "OMX_IndexParamVideoSliceFMO";
1597 case OMX_IndexConfigVideoAVCIntraPeriod:
1598 return "OMX_IndexConfigVideoAVCIntraPeriod";
1599 case OMX_IndexConfigVideoNalSize:
1600 return "OMX_IndexConfigVideoNalSize";
1601 case OMX_IndexCommonStartUnused:
1602 return "OMX_IndexCommonStartUnused";
1603 case OMX_IndexParamCommonDeblocking:
1604 return "OMX_IndexParamCommonDeblocking";
1605 case OMX_IndexParamCommonSensorMode:
1606 return "OMX_IndexParamCommonSensorMode";
1607 case OMX_IndexParamCommonInterleave:
1608 return "OMX_IndexParamCommonInterleave";
1609 case OMX_IndexConfigCommonColorFormatConversion:
1610 return "OMX_IndexConfigCommonColorFormatConversion";
1611 case OMX_IndexConfigCommonScale:
1612 return "OMX_IndexConfigCommonScale";
1613 case OMX_IndexConfigCommonImageFilter:
1614 return "OMX_IndexConfigCommonImageFilter";
1615 case OMX_IndexConfigCommonColorEnhancement:
1616 return "OMX_IndexConfigCommonColorEnhancement";
1617 case OMX_IndexConfigCommonColorKey:
1618 return "OMX_IndexConfigCommonColorKey";
1619 case OMX_IndexConfigCommonColorBlend:
1620 return "OMX_IndexConfigCommonColorBlend";
1621 case OMX_IndexConfigCommonFrameStabilisation:
1622 return "OMX_IndexConfigCommonFrameStabilisation";
1623 case OMX_IndexConfigCommonRotate:
1624 return "OMX_IndexConfigCommonRotate";
1625 case OMX_IndexConfigCommonMirror:
1626 return "OMX_IndexConfigCommonMirror";
1627 case OMX_IndexConfigCommonOutputPosition:
1628 return "OMX_IndexConfigCommonOutputPosition";
1629 case OMX_IndexConfigCommonInputCrop:
1630 return "OMX_IndexConfigCommonInputCrop";
1631 case OMX_IndexConfigCommonOutputCrop:
1632 return "OMX_IndexConfigCommonOutputCrop";
1633 case OMX_IndexConfigCommonDigitalZoom:
1634 return "OMX_IndexConfigCommonDigitalZoom";
1635 case OMX_IndexConfigCommonOpticalZoom:
1636 return "OMX_IndexConfigCommonOpticalZoom";
1637 case OMX_IndexConfigCommonWhiteBalance:
1638 return "OMX_IndexConfigCommonWhiteBalance";
1639 case OMX_IndexConfigCommonExposure:
1640 return "OMX_IndexConfigCommonExposure";
1641 case OMX_IndexConfigCommonContrast:
1642 return "OMX_IndexConfigCommonContrast";
1643 case OMX_IndexConfigCommonBrightness:
1644 return "OMX_IndexConfigCommonBrightness";
1645 case OMX_IndexConfigCommonBacklight:
1646 return "OMX_IndexConfigCommonBacklight";
1647 case OMX_IndexConfigCommonGamma:
1648 return "OMX_IndexConfigCommonGamma";
1649 case OMX_IndexConfigCommonSaturation:
1650 return "OMX_IndexConfigCommonSaturation";
1651 case OMX_IndexConfigCommonLightness:
1652 return "OMX_IndexConfigCommonLightness";
1653 case OMX_IndexConfigCommonExclusionRect:
1654 return "OMX_IndexConfigCommonExclusionRect";
1655 case OMX_IndexConfigCommonDithering:
1656 return "OMX_IndexConfigCommonDithering";
1657 case OMX_IndexConfigCommonPlaneBlend:
1658 return "OMX_IndexConfigCommonPlaneBlend";
1659 case OMX_IndexConfigCommonExposureValue:
1660 return "OMX_IndexConfigCommonExposureValue";
1661 case OMX_IndexConfigCommonOutputSize:
1662 return "OMX_IndexConfigCommonOutputSize";
1663 case OMX_IndexParamCommonExtraQuantData:
1664 return "OMX_IndexParamCommonExtraQuantData";
1665 case OMX_IndexConfigCommonTransitionEffect:
1666 return "OMX_IndexConfigCommonTransitionEffect";
1667 case OMX_IndexOtherStartUnused:
1668 return "OMX_IndexOtherStartUnused";
1669 case OMX_IndexParamOtherPortFormat:
1670 return "OMX_IndexParamOtherPortFormat";
1671 case OMX_IndexConfigOtherPower:
1672 return "OMX_IndexConfigOtherPower";
1673 case OMX_IndexConfigOtherStats:
1674 return "OMX_IndexConfigOtherStats";
1675 case OMX_IndexTimeStartUnused:
1676 return "OMX_IndexTimeStartUnused";
1677 case OMX_IndexConfigTimeScale:
1678 return "OMX_IndexConfigTimeScale";
1679 case OMX_IndexConfigTimeClockState:
1680 return "OMX_IndexConfigTimeClockState";
1681 case OMX_IndexConfigTimeCurrentMediaTime:
1682 return "OMX_IndexConfigTimeCurrentMediaTime";
1683 case OMX_IndexConfigTimeCurrentWallTime:
1684 return "OMX_IndexConfigTimeCurrentWallTime";
1685 case OMX_IndexConfigTimeMediaTimeRequest:
1686 return "OMX_IndexConfigTimeMediaTimeRequest";
1687 case OMX_IndexConfigTimeClientStartTime:
1688 return "OMX_IndexConfigTimeClientStartTime";
1689 case OMX_IndexConfigTimePosition:
1690 return "OMX_IndexConfigTimePosition";
1691 case OMX_IndexConfigTimeSeekMode:
1692 return "OMX_IndexConfigTimeSeekMode";
1693 case OMX_IndexKhronosExtensions:
1694 return "OMX_IndexKhronosExtensions";
1695 case OMX_IndexVendorStartUnused:
1696 return "OMX_IndexVendorStartUnused";
1698 return "OMX_IndexMax";
1703 #if OMX_VERSION_MINOR == 1
1705 case OMX_IndexParamCustomContentPipe:
1706 return "OMX_IndexParamCustomContentPipe";
1707 case OMX_IndexConfigCommonFocusRegion:
1708 return "OMX_IndexConfigCommonFocusRegion";
1709 case OMX_IndexConfigCommonFocusStatus:
1710 return "OMX_IndexConfigCommonFocusStatus";
1711 case OMX_IndexConfigTimeActiveRefClock:
1712 return "OMX_IndexConfigTimeActiveRefClock";
1713 case OMX_IndexConfigTimeCurrentAudioReference:
1714 return "OMX_IndexConfigTimeCurrentAudioReference";
1715 case OMX_IndexConfigTimeCurrentVideoReference:
1716 return "OMX_IndexConfigTimeCurrentVideoReference";
1722 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
1723 switch ((OMX_ALG_INDEXTYPE) index) {
1724 case OMX_ALG_IndexVendorComponentStartUnused:
1725 return "OMX_ALG_IndexVendorComponentStartUnused";
1726 case OMX_ALG_IndexParamReportedLatency:
1727 return "OMX_ALG_IndexParamReportedLatency";
1728 case OMX_ALG_IndexParamPreallocation:
1729 return "OMX_ALG_IndexParamPreallocation";
1730 case OMX_ALG_IndexVendorPortStartUnused:
1731 return "OMX_ALG_IndexVendorPortStartUnused";
1732 case OMX_ALG_IndexPortParamBufferMode:
1733 return "OMX_ALG_IndexPortParamBufferMode";
1734 case OMX_ALG_IndexParamVendorVideoStartUnused:
1735 return "OMX_ALG_IndexParamVendorVideoStartUnused";
1736 case OMX_ALG_IndexParamVideoHevc:
1737 return "OMX_ALG_IndexParamVideoHevc";
1738 case OMX_ALG_IndexParamVideoVp9:
1739 return "OMX_ALG_IndexParamVideoVp9";
1740 case OMX_ALG_IndexParamVideoGopControl:
1741 return "OMX_ALG_IndexParamVideoGopControl";
1742 case OMX_ALG_IndexParamVideoSlices:
1743 return "OMX_ALG_IndexParamVideoSlices";
1744 case OMX_ALG_IndexParamVideoSceneChangeResilience:
1745 return "OMX_ALG_IndexParamVideoSceneChangeResilience";
1746 case OMX_ALG_IndexParamVideoPrefetchBuffer:
1747 return "OMX_ALG_IndexParamVideoPrefetchBuffer";
1748 case OMX_ALG_IndexParamVideoCodedPictureBuffer:
1749 return "OMX_ALG_IndexParamVideoCodedPictureBuffer";
1750 case OMX_ALG_IndexParamVideoQuantizationControl:
1751 return "OMX_ALG_IndexParamVideoQuantizationControl";
1752 case OMX_ALG_IndexParamVideoQuantizationExtension:
1753 return "OMX_ALG_IndexParamVideoQuantizationExtension";
1754 case OMX_ALG_IndexParamVideoScalingList:
1755 return "OMX_ALG_IndexParamVideoScalingList";
1756 case OMX_ALG_IndexParamVideoDecodedPictureBuffer:
1757 return "OMX_ALG_IndexParamVideoDecodedPictureBuffer";
1758 case OMX_ALG_IndexParamVideoInternalEntropyBuffers:
1759 return "OMX_ALG_IndexParamVideoInternalEntropyBuffers";
1760 case OMX_ALG_IndexParamVideoLowBandwidth:
1761 return "OMX_ALG_IndexParamVideoLowBandwidth";
1762 case OMX_ALG_IndexParamVideoAspectRatio:
1763 return "OMX_ALG_IndexParamVideoAspectRatio";
1764 case OMX_ALG_IndexParamVideoSubframe:
1765 return "OMX_ALG_IndexParamVideoSubframe";
1766 case OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh:
1767 return "OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh";
1768 case OMX_ALG_IndexParamVideoMaxBitrate:
1769 return "OMX_ALG_IndexParamVideoMaxBitrate";
1770 case OMX_ALG_IndexParamVideoFillerData:
1771 return "OMX_ALG_IndexParamVideoFillerData";
1772 case OMX_ALG_IndexParamVideoBufferMode:
1773 return "OMX_ALG_IndexParamVideoBufferMode";
1774 case OMX_ALG_IndexParamVideoInterlaceFormatCurrent:
1775 return "OMX_ALG_IndexParamVideoInterlaceFormatCurrent";
1776 case OMX_ALG_IndexParamVideoLongTerm:
1777 return "OMX_ALG_IndexParamVideoLongTerm";
1778 case OMX_ALG_IndexParamVideoLookAhead:
1779 return "OMX_ALG_IndexParamVideoLookAhead";
1780 case OMX_ALG_IndexConfigVendorVideoStartUnused:
1781 return "OMX_ALG_IndexConfigVendorVideoStartUnused";
1782 case OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh:
1783 return "OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh";
1784 case OMX_ALG_IndexConfigVideoGroupOfPictures:
1785 return "OMX_ALG_IndexConfigVideoGroupOfPictures";
1786 case OMX_ALG_IndexConfigVideoRegionOfInterest:
1787 return "OMX_ALG_IndexConfigVideoRegionOfInterest";
1788 case OMX_ALG_IndexConfigVideoNotifySceneChange:
1789 return "OMX_ALG_IndexConfigVideoNotifySceneChange";
1790 case OMX_ALG_IndexConfigVideoInsertLongTerm:
1791 return "OMX_ALG_IndexConfigVideoInsertLongTerm";
1792 case OMX_ALG_IndexConfigVideoUseLongTerm:
1793 return "OMX_ALG_IndexConfigVideoUseLongTerm";
1794 case OMX_ALG_IndexVendorCommonStartUnused:
1795 return "OMX_ALG_IndexVendorCommonStartUnused";
1796 case OMX_ALG_IndexParamCommonSequencePictureModeCurrent:
1797 return "OMX_ALG_IndexParamCommonSequencePictureModeCurrent";
1798 case OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported:
1799 return "OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported";
1800 case OMX_ALG_IndexParamVideoTwoPass:
1801 return "OMX_ALG_IndexParamVideoTwoPass";
1802 case OMX_ALG_IndexParamVideoColorPrimaries:
1803 return "OMX_ALG_IndexParamVideoColorPrimaries";
1804 case OMX_ALG_IndexParamVideoSkipFrame:
1805 return "OMX_ALG_IndexParamVideoSkipFrame";
1806 case OMX_ALG_IndexConfigVideoNotifyResolutionChange:
1807 return "OMX_ALG_IndexConfigVideoNotifyResolutionChange";
1808 case OMX_ALG_IndexConfigVideoInsertPrefixSEI:
1809 return "OMX_ALG_IndexConfigVideoInsertPrefixSEI";
1810 case OMX_ALG_IndexConfigVideoInsertSuffixSEI:
1811 return "OMX_ALG_IndexConfigVideoInsertSuffixSEI";
1812 case OMX_ALG_IndexConfigVideoQuantizationParameterTable:
1813 return "OMX_ALG_IndexConfigVideoQuantizationParameterTable";
1814 case OMX_ALG_IndexParamVideoInputParsed:
1815 return "OMX_ALG_IndexParamVideoInputParsed";
1816 case OMX_ALG_IndexParamVideoMaxPictureSize:
1817 return "OMX_ALG_IndexParamVideoMaxPictureSize";
1818 case OMX_ALG_IndexParamVideoMaxPictureSizes:
1819 return "OMX_ALG_IndexParamVideoMaxPictureSizes";
1820 case OMX_ALG_IndexConfigVideoLoopFilterBeta:
1821 return "OMX_ALG_IndexConfigVideoLoopFilterBeta";
1822 case OMX_ALG_IndexConfigVideoLoopFilterTc:
1823 return "OMX_ALG_IndexConfigVideoLoopFilterTc";
1824 case OMX_ALG_IndexParamVideoLoopFilterBeta:
1825 return "OMX_ALG_IndexParamVideoLoopFilterBeta";
1826 case OMX_ALG_IndexParamVideoLoopFilterTc:
1827 return "OMX_ALG_IndexParamVideoLoopFilterTc";
1828 case OMX_ALG_IndexPortParamEarlyCallback:
1829 return "OMX_ALG_IndexPortParamEarlyCallback";
1830 case OMX_ALG_IndexParamVideoTransferCharacteristics:
1831 return "OMX_ALG_IndexParamVideoTransferCharacteristics";
1832 case OMX_ALG_IndexParamVideoColorMatrix:
1833 return "OMX_ALG_IndexParamVideoColorMatrix";
1834 case OMX_ALG_IndexConfigVideoTransferCharacteristics:
1835 return "OMX_ALG_IndexConfigVideoTransferCharacteristics";
1836 case OMX_ALG_IndexConfigVideoColorMatrix:
1837 return "OMX_ALG_IndexConfigVideoColorMatrix";
1838 case OMX_ALG_IndexConfigVideoHighDynamicRangeSEI:
1839 return "OMX_ALG_IndexConfigVideoHighDynamicRangeSEI";
1840 case OMX_ALG_IndexConfigVideoMaxResolutionChange:
1841 return "OMX_ALG_IndexConfigVideoMaxResolutionChange";
1842 case OMX_ALG_IndexParamVideoQuantizationTable:
1843 return "OMX_ALG_IndexParamVideoQuantizationTable";
1844 case OMX_ALG_IndexParamVideoAccessUnitDelimiter:
1845 return "OMX_ALG_IndexParamVideoAccessUnitDelimiter";
1846 case OMX_ALG_IndexParamVideoBufferingPeriodSEI:
1847 return "OMX_ALG_IndexParamVideoBufferingPeriodSEI";
1848 case OMX_ALG_IndexParamVideoPictureTimingSEI:
1849 return "OMX_ALG_IndexParamVideoPictureTimingSEI";
1850 case OMX_ALG_IndexParamVideoRecoveryPointSEI:
1851 return "OMX_ALG_IndexParamVideoRecoveryPointSEI";
1852 case OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI:
1853 return "OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI";
1854 case OMX_ALG_IndexParamVideoContentLightLevelSEI:
1855 return "OMX_ALG_IndexParamVideoContentLightLevelSEI";
1856 case OMX_ALG_IndexConfigVideoRegionOfInterestByValue:
1857 return "OMX_ALG_IndexConfigVideoRegionOfInterestByValue";
1858 case OMX_ALG_IndexConfigVideoColorPrimaries:
1859 return "OMX_ALG_IndexConfigVideoColorPrimaries";
1860 case OMX_ALG_IndexMaxEnum:
1861 return "OMX_ALG_IndexMaxEnum";
1865 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
1866 /* Not part of the enum in OMX_IndexAlg.h */
1867 if (index == OMX_ALG_IndexParamVideoInterlaceFormatSupported)
1868 return "OMX_ALG_IndexParamVideoInterlaceFormatSupported";
1873 #endif /* GST_DISABLE_GST_DEBUG */
1876 log_omx_api_trace_call (GstOMXComponent * comp, const gchar * function,
1877 OMX_INDEXTYPE index, GstDebugLevel level)
1879 #ifndef GST_DISABLE_GST_DEBUG
1881 const gchar *index_name;
1883 /* Don't bother creating useless structs if not needed */
1884 if (gst_debug_category_get_threshold (OMX_API_TRACE) < level)
1887 index_name = omx_index_type_to_str (index);
1889 GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
1890 "unknown call of %s with index 0x%08x", function, index);
1894 s = gst_structure_new (function, "index", G_TYPE_STRING, index_name, NULL);
1895 GST_CAT_LEVEL_LOG (OMX_API_TRACE, level, comp->parent, "%" GST_PTR_FORMAT, s);
1896 gst_structure_free (s);
1897 #endif /* GST_DISABLE_GST_DEBUG */
1900 /* comp->lock must be unlocked while calling this */
1902 gst_omx_component_get_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index,
1907 g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
1908 g_return_val_if_fail (param != NULL, OMX_ErrorUndefined);
1910 GST_DEBUG_OBJECT (comp->parent, "Getting %s parameter at index 0x%08x",
1912 log_omx_api_trace_call (comp, "GetParameter", index, GST_LEVEL_LOG);
1913 err = OMX_GetParameter (comp->handle, index, param);
1914 DEBUG_IF_OK (comp->parent, err, "Got %s parameter at index 0x%08x: %s "
1915 "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
1920 /* comp->lock must be unlocked while calling this */
1922 gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index,
1927 g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
1928 g_return_val_if_fail (param != NULL, OMX_ErrorUndefined);
1930 GST_DEBUG_OBJECT (comp->parent, "Setting %s parameter at index 0x%08x",
1933 log_omx_api_trace_call (comp, "SetParameter", index, GST_LEVEL_DEBUG);
1934 err = OMX_SetParameter (comp->handle, index, param);
1935 DEBUG_IF_OK (comp->parent, err, "Set %s parameter at index 0x%08x: %s "
1936 "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
1941 /* comp->lock must be unlocked while calling this */
1943 gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
1948 g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
1949 g_return_val_if_fail (config != NULL, OMX_ErrorUndefined);
1951 GST_DEBUG_OBJECT (comp->parent, "Getting %s configuration at index 0x%08x",
1953 log_omx_api_trace_call (comp, "GetConfig", index, GST_LEVEL_LOG);
1954 err = OMX_GetConfig (comp->handle, index, config);
1955 DEBUG_IF_OK (comp->parent, err, "Got %s parameter at index 0x%08x: %s "
1956 "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
1961 /* comp->lock must be unlocked while calling this */
1963 gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
1968 g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
1969 g_return_val_if_fail (config != NULL, OMX_ErrorUndefined);
1971 GST_DEBUG_OBJECT (comp->parent, "Setting %s configuration at index 0x%08x",
1973 log_omx_api_trace_call (comp, "SetConfig", index, GST_LEVEL_DEBUG);
1974 err = OMX_SetConfig (comp->handle, index, config);
1975 DEBUG_IF_OK (comp->parent, err, "Set %s parameter at index 0x%08x: %s "
1976 "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
1982 gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2)
1984 GstOMXComponent *comp1;
1985 GstOMXComponent *comp2;
1988 g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
1989 g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
1990 OMX_ErrorUndefined);
1991 comp1 = port1->comp;
1993 g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
1994 g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
1995 OMX_ErrorUndefined);
1996 comp2 = port2->comp;
1998 g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
2000 g_mutex_lock (&comp1->lock);
2001 g_mutex_lock (&comp2->lock);
2002 GST_DEBUG_OBJECT (comp1->parent,
2003 "Setup tunnel between %s port %u and %s port %u",
2004 comp1->name, port1->index, comp2->name, port2->index);
2006 err = comp1->core->setup_tunnel (comp1->handle, port1->index, comp2->handle,
2009 if (err == OMX_ErrorNone) {
2010 port1->tunneled = TRUE;
2011 port2->tunneled = TRUE;
2014 DEBUG_IF_OK (comp1->parent, err,
2015 "Setup tunnel between %s port %u and %s port %u: %s (0x%08x)",
2016 comp1->name, port1->index,
2017 comp2->name, port2->index, gst_omx_error_to_string (err), err);
2019 g_mutex_unlock (&comp2->lock);
2020 g_mutex_unlock (&comp1->lock);
2026 gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2)
2028 GstOMXComponent *comp1;
2029 GstOMXComponent *comp2;
2032 g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
2033 g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
2034 OMX_ErrorUndefined);
2035 comp1 = port1->comp;
2037 g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
2038 g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
2039 OMX_ErrorUndefined);
2040 comp2 = port2->comp;
2042 g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
2043 g_return_val_if_fail (port1->tunneled && port2->tunneled, OMX_ErrorUndefined);
2045 g_mutex_lock (&comp1->lock);
2046 g_mutex_lock (&comp2->lock);
2047 GST_DEBUG_OBJECT (comp1->parent,
2048 "Closing tunnel between %s port %u and %s port %u",
2049 comp1->name, port1->index, comp2->name, port2->index);
2051 err = comp1->core->setup_tunnel (comp1->handle, port1->index, 0, 0);
2052 if (err != OMX_ErrorNone) {
2053 GST_ERROR_OBJECT (comp1->parent,
2054 "Failed to close tunnel on output side %s (0x%08x)",
2055 gst_omx_error_to_string (err), err);
2057 err = comp2->core->setup_tunnel (0, 0, comp2->handle, port2->index);
2058 if (err != OMX_ErrorNone) {
2059 GST_ERROR_OBJECT (comp2->parent,
2060 "Failed to close tunnel on input side %s (0x%08x)",
2061 gst_omx_error_to_string (err), err);
2064 port1->tunneled = FALSE;
2065 port2->tunneled = FALSE;
2067 GST_DEBUG_OBJECT (comp1->parent,
2068 "Closed tunnel between %s port %u and %s port %u",
2069 comp1->name, port1->index, comp2->name, port2->index);
2071 g_mutex_unlock (&comp2->lock);
2072 g_mutex_unlock (&comp1->lock);
2078 gst_omx_port_get_port_definition (GstOMXPort * port,
2079 OMX_PARAM_PORTDEFINITIONTYPE * port_def)
2081 GstOMXComponent *comp;
2084 g_return_val_if_fail (port != NULL, OMX_ErrorBadParameter);
2088 GST_OMX_INIT_STRUCT (port_def);
2089 port_def->nPortIndex = port->index;
2091 err = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
2098 gst_omx_port_update_port_definition (GstOMXPort * port,
2099 OMX_PARAM_PORTDEFINITIONTYPE * port_def)
2101 OMX_ERRORTYPE err_get, err_set = OMX_ErrorNone;
2102 GstOMXComponent *comp;
2104 g_return_val_if_fail (port != NULL, FALSE);
2110 gst_omx_component_set_parameter (comp, OMX_IndexParamPortDefinition,
2112 err_get = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
2115 DEBUG_IF_OK (comp->parent, err_set,
2116 "Updated %s port %u definition: %s (0x%08x)", comp->name, port->index,
2117 gst_omx_error_to_string (err_set), err_set);
2119 if (err_set != OMX_ErrorNone)
2125 /* NOTE: Uses comp->lock and comp->messages_lock */
2126 GstOMXAcquireBufferReturn
2127 gst_omx_port_acquire_buffer (GstOMXPort * port, GstOMXBuffer ** buf,
2130 GstOMXAcquireBufferReturn ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
2131 GstOMXComponent *comp;
2133 GstOMXBuffer *_buf = NULL;
2134 gint64 timeout = GST_CLOCK_TIME_NONE;
2136 g_return_val_if_fail (port != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
2137 g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR);
2138 g_return_val_if_fail (buf != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
2144 g_mutex_lock (&comp->lock);
2145 GST_DEBUG_OBJECT (comp->parent, "Acquiring %s buffer from port %u",
2146 comp->name, port->index);
2149 gst_omx_component_handle_messages (comp);
2151 /* If we are in the case where we waited for a buffer after EOS,
2152 * make sure we don't do that again */
2156 /* Check if the component is in an error state */
2157 if ((err = comp->last_error) != OMX_ErrorNone) {
2158 GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s",
2159 comp->name, gst_omx_error_to_string (err));
2160 ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
2164 /* Check if the port is flushing */
2165 if (port->flushing) {
2166 GST_DEBUG_OBJECT (comp->parent, "Component %s port %d is flushing",
2167 comp->name, port->index);
2168 ret = GST_OMX_ACQUIRE_BUFFER_FLUSHING;
2172 /* If this is an input port and at least one of the output ports
2173 * needs to be reconfigured, we wait until all output ports are
2174 * reconfigured. Afterwards this port is reconfigured if required
2175 * or buffers are returned to be filled as usual.
2177 if (port->port_def.eDir == OMX_DirInput) {
2178 if (comp->pending_reconfigure_outports) {
2179 gst_omx_component_handle_messages (comp);
2180 while (comp->pending_reconfigure_outports &&
2181 (err = comp->last_error) == OMX_ErrorNone && !port->flushing) {
2182 GST_DEBUG_OBJECT (comp->parent,
2183 "Waiting for %s output ports to reconfigure", comp->name);
2184 gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE);
2185 gst_omx_component_handle_messages (comp);
2190 /* Only if this port needs to be reconfigured too notify
2191 * the caller about it */
2192 if (port->settings_cookie != port->configured_settings_cookie) {
2193 GST_DEBUG_OBJECT (comp->parent,
2194 "Component %s port %d needs reconfiguring", comp->name, port->index);
2195 ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE;
2200 /* If we have an output port that needs to be reconfigured
2201 * and it still has buffers pending for the old configuration
2202 * we first return them.
2203 * NOTE: If buffers for this configuration arrive later
2204 * we have to drop them... */
2205 if (port->port_def.eDir == OMX_DirOutput &&
2206 port->settings_cookie != port->configured_settings_cookie) {
2207 if (!g_queue_is_empty (&port->pending_buffers)) {
2208 GST_DEBUG_OBJECT (comp->parent,
2209 "%s output port %u needs reconfiguration but has buffers pending",
2210 comp->name, port->index);
2211 _buf = g_queue_pop_head (&port->pending_buffers);
2213 ret = GST_OMX_ACQUIRE_BUFFER_OK;
2217 GST_DEBUG_OBJECT (comp->parent, "Component %s port %d needs reconfiguring",
2218 comp->name, port->index);
2219 ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE;
2223 if (port->port_def.eDir == OMX_DirOutput && port->eos) {
2224 if (!g_queue_is_empty (&port->pending_buffers)) {
2225 GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but has "
2226 "%d buffers pending", comp->name, port->index,
2227 g_queue_get_length (&port->pending_buffers));
2228 _buf = g_queue_pop_head (&port->pending_buffers);
2230 ret = GST_OMX_ACQUIRE_BUFFER_OK;
2234 if (comp->hacks & GST_OMX_HACK_SIGNALS_PREMATURE_EOS && timeout != -2) {
2235 timeout = 33 * GST_MSECOND;
2237 GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but waiting "
2238 "in case it spits out more buffers", comp->name, port->index);
2240 GST_DEBUG_OBJECT (comp->parent, "Component %s port %d signalled EOS",
2241 comp->name, port->index);
2242 ret = GST_OMX_ACQUIRE_BUFFER_EOS;
2249 * At this point we have no error or flushing/eos port
2250 * and a properly configured port.
2254 /* If the queue is empty we wait until a buffer
2255 * arrives, an error happens, the port is flushing
2256 * or the port needs to be reconfigured.
2258 if (g_queue_is_empty (&port->pending_buffers)) {
2259 GST_DEBUG_OBJECT (comp->parent, "Queue of %s port %u is empty",
2260 comp->name, port->index);
2262 if (wait == GST_OMX_WAIT) {
2263 gst_omx_component_wait_message (comp,
2264 timeout == -2 ? GST_CLOCK_TIME_NONE : timeout);
2266 /* And now check everything again and maybe get a buffer */
2269 ret = GST_OMX_ACQUIRE_BUFFER_NO_AVAILABLE;
2274 GST_DEBUG_OBJECT (comp->parent, "%s port %u has pending buffers",
2275 comp->name, port->index);
2276 _buf = g_queue_pop_head (&port->pending_buffers);
2277 ret = GST_OMX_ACQUIRE_BUFFER_OK;
2280 g_mutex_unlock (&comp->lock);
2283 g_assert (_buf == _buf->omx_buf->pAppPrivate);
2287 GST_DEBUG_OBJECT (comp->parent, "Acquired buffer %p (%p) from %s port %u: %d",
2288 _buf, (_buf ? _buf->omx_buf->pBuffer : NULL), comp->name, port->index,
2294 /* NOTE: Uses comp->lock and comp->messages_lock */
2296 gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf)
2298 GstOMXComponent *comp;
2299 OMX_ERRORTYPE err = OMX_ErrorNone;
2301 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2302 g_return_val_if_fail (!port->tunneled, OMX_ErrorUndefined);
2303 g_return_val_if_fail (buf != NULL, OMX_ErrorUndefined);
2304 g_return_val_if_fail (buf->port == port, OMX_ErrorUndefined);
2308 g_mutex_lock (&comp->lock);
2310 GST_DEBUG_OBJECT (comp->parent, "Releasing buffer %p (%p) to %s port %u",
2311 buf, buf->omx_buf->pBuffer, comp->name, port->index);
2313 gst_omx_component_handle_messages (comp);
2315 if (port->port_def.eDir == OMX_DirOutput) {
2316 /* Reset all flags, some implementations don't
2317 * reset them themselves and the flags are not
2318 * valid anymore after the buffer was consumed
2320 gst_omx_buffer_reset (buf);
2323 if ((err = comp->last_error) != OMX_ErrorNone) {
2324 GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s "
2325 "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
2326 g_queue_push_tail (&port->pending_buffers, buf);
2327 gst_omx_component_send_message (comp, NULL);
2331 if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
2332 GST_DEBUG_OBJECT (comp->parent,
2333 "%s port %u is flushing or disabled, not releasing " "buffer",
2334 comp->name, port->index);
2335 g_queue_push_tail (&port->pending_buffers, buf);
2336 gst_omx_component_send_message (comp, NULL);
2340 g_assert (buf == buf->omx_buf->pAppPrivate);
2342 /* FIXME: What if the settings cookies don't match? */
2346 if (port->port_def.eDir == OMX_DirInput) {
2347 log_omx_api_trace_buffer (comp, "EmptyThisBuffer", buf);
2348 err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf);
2350 log_omx_api_trace_buffer (comp, "FillThisBuffer", buf);
2351 err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
2353 DEBUG_IF_OK (comp->parent, err, "Released buffer %p to %s port %u: %s "
2354 "(0x%08x)", buf, comp->name, port->index, gst_omx_error_to_string (err),
2358 gst_omx_component_handle_messages (comp);
2359 g_mutex_unlock (&comp->lock);
2364 /* NOTE: Must be called while holding comp->lock */
2366 should_wait_until_flushed (GstOMXPort * port)
2369 /* Flush command hasn't been completed yet by OMX */
2372 if (port->buffers) {
2375 /* Wait for all the buffers used by OMX to be released */
2376 for (i = 0; i < port->buffers->len; i++) {
2377 GstOMXBuffer *buf = g_ptr_array_index (port->buffers, i);
2387 /* NOTE: Uses comp->lock and comp->messages_lock */
2389 gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
2392 GstOMXComponent *comp;
2393 OMX_ERRORTYPE err = OMX_ErrorNone;
2395 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2399 g_mutex_lock (&comp->lock);
2401 GST_DEBUG_OBJECT (comp->parent, "Setting %s port %d to %sflushing",
2402 comp->name, port->index, (flush ? "" : "not "));
2404 gst_omx_component_handle_messages (comp);
2406 if (flush == port->flushing) {
2407 GST_DEBUG_OBJECT (comp->parent, "%s port %u was %sflushing already",
2408 comp->name, port->index, (flush ? "" : "not "));
2412 if ((err = comp->last_error) != OMX_ErrorNone) {
2413 GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s "
2414 "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
2418 port->flushing = flush;
2421 OMX_ERRORTYPE last_error;
2423 gst_omx_component_send_message (comp, NULL);
2425 /* Now flush the port */
2426 port->flushed = FALSE;
2429 gst_omx_component_send_command (comp, OMX_CommandFlush, port->index,
2432 if (err != OMX_ErrorNone) {
2433 GST_ERROR_OBJECT (comp->parent,
2434 "Error sending flush command to %s port %u: %s (0x%08x)", comp->name,
2435 port->index, gst_omx_error_to_string (err), err);
2439 if ((err = comp->last_error) != OMX_ErrorNone) {
2440 GST_ERROR_OBJECT (comp->parent,
2441 "Component %s is in error state: %s (0x%08x)", comp->name,
2442 gst_omx_error_to_string (err), err);
2446 if (port->flushing != flush) {
2447 GST_ERROR_OBJECT (comp->parent, "%s: another flush happened in the "
2448 " meantime", comp->name);
2453 if (should_wait_until_flushed (port))
2454 err = OMX_ErrorTimeout;
2458 /* Retry until timeout or until an error happend or
2459 * until all buffers were released by the component and
2460 * the flush command completed */
2462 last_error = OMX_ErrorNone;
2463 gst_omx_component_handle_messages (comp);
2464 while (should_wait_until_flushed (port)) {
2465 signalled = gst_omx_component_wait_message (comp, timeout);
2467 gst_omx_component_handle_messages (comp);
2469 last_error = comp->last_error;
2471 if (!signalled || last_error != OMX_ErrorNone)
2472 /* Something gone wrong or we timed out */
2475 port->flushed = FALSE;
2477 GST_DEBUG_OBJECT (comp->parent, "%s port %d flushed", comp->name,
2479 if (last_error != OMX_ErrorNone) {
2480 GST_ERROR_OBJECT (comp->parent,
2481 "Got error while flushing %s port %u: %s (0x%08x)", comp->name,
2482 port->index, gst_omx_error_to_string (last_error), last_error);
2485 } else if (!signalled) {
2486 GST_ERROR_OBJECT (comp->parent, "Timeout while flushing %s port %u",
2487 comp->name, port->index);
2488 err = OMX_ErrorTimeout;
2493 /* Reset EOS flag */
2497 gst_omx_port_update_port_definition (port, NULL);
2499 DEBUG_IF_OK (comp->parent, err, "Set %s port %u to %sflushing: %s (0x%08x)",
2500 comp->name, port->index, (flush ? "" : "not "),
2501 gst_omx_error_to_string (err), err);
2502 gst_omx_component_handle_messages (comp);
2503 g_mutex_unlock (&comp->lock);
2508 /* NOTE: Uses comp->lock and comp->messages_lock */
2510 gst_omx_port_is_flushing (GstOMXPort * port)
2512 GstOMXComponent *comp;
2515 g_return_val_if_fail (port != NULL, FALSE);
2519 g_mutex_lock (&comp->lock);
2520 gst_omx_component_handle_messages (port->comp);
2521 flushing = port->flushing;
2522 g_mutex_unlock (&comp->lock);
2524 GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing: %d", comp->name,
2525 port->index, flushing);
2530 static OMX_ERRORTYPE gst_omx_port_deallocate_buffers_unlocked (GstOMXPort *
2533 /* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
2534 static OMX_ERRORTYPE
2535 gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
2536 const GList * buffers, const GList * images, guint n)
2538 GstOMXComponent *comp;
2539 OMX_ERRORTYPE err = OMX_ErrorNone;
2543 g_assert (!port->buffers || port->buffers->len == 0);
2545 g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter);
2549 gst_omx_component_handle_messages (port->comp);
2550 if ((err = comp->last_error) != OMX_ErrorNone) {
2551 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
2552 comp->name, gst_omx_error_to_string (err), err);
2556 /* Update the port definition to check if we need more
2557 * buffers after the port configuration was done and to
2558 * update the buffer size
2560 gst_omx_port_update_port_definition (port, NULL);
2562 g_return_val_if_fail (n != -1 || (!buffers
2563 && !images), OMX_ErrorBadParameter);
2566 n = port->port_def.nBufferCountActual;
2568 g_return_val_if_fail (n == port->port_def.nBufferCountActual,
2569 OMX_ErrorBadParameter);
2571 GST_INFO_OBJECT (comp->parent,
2572 "Allocating %d buffers of size %" G_GSIZE_FORMAT " for %s port %u", n,
2573 (size_t) port->port_def.nBufferSize, comp->name, (guint) port->index);
2576 port->buffers = g_ptr_array_sized_new (n);
2578 l = (buffers ? buffers : images);
2579 for (i = 0; i < n; i++) {
2582 buf = g_slice_new0 (GstOMXBuffer);
2585 buf->settings_cookie = port->settings_cookie;
2586 g_ptr_array_add (port->buffers, buf);
2590 OMX_UseBuffer (comp->handle, &buf->omx_buf, port->index, buf,
2591 port->port_def.nBufferSize, l->data);
2592 buf->eglimage = FALSE;
2593 } else if (images) {
2595 OMX_UseEGLImage (comp->handle, &buf->omx_buf, port->index, buf,
2597 buf->eglimage = TRUE;
2600 OMX_AllocateBuffer (comp->handle, &buf->omx_buf, port->index, buf,
2601 port->port_def.nBufferSize);
2602 buf->eglimage = FALSE;
2605 /* Let the caller decide to print an error when OMX_UseBuffer or
2606 * OMX_UseEGLImage fail. Indeed it can be part of a trial path. So
2607 * it is not necessary to warn the user if the fallback path succeeds.
2609 if (err != OMX_ErrorNone) {
2610 GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (buffers
2611 || images) ? GST_LEVEL_INFO : GST_LEVEL_ERROR, comp->parent,
2612 "Failed to allocate buffer for %s port %u: %s (0x%08x)", comp->name,
2613 port->index, gst_omx_error_to_string (err), err);
2614 gst_omx_port_deallocate_buffers_unlocked (port);
2618 GST_DEBUG_OBJECT (comp->parent, "%s: allocated buffer %p (%p)",
2619 comp->name, buf, buf->omx_buf->pBuffer);
2621 g_assert (buf->omx_buf->pAppPrivate == buf);
2623 /* In the beginning all buffers are not owned by the component */
2624 g_queue_push_tail (&port->pending_buffers, buf);
2625 if (buffers || images)
2629 gst_omx_component_handle_messages (comp);
2632 gst_omx_port_update_port_definition (port, NULL);
2634 INFO_IF_OK (comp->parent, err, "Allocated buffers for %s port %u: %s "
2635 "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
2640 /* NOTE: Uses comp->lock and comp->messages_lock */
2642 gst_omx_port_allocate_buffers (GstOMXPort * port)
2646 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2648 g_mutex_lock (&port->comp->lock);
2649 err = gst_omx_port_allocate_buffers_unlocked (port, NULL, NULL, -1);
2650 port->allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
2651 g_mutex_unlock (&port->comp->lock);
2656 /* NOTE: Uses comp->lock and comp->messages_lock */
2658 gst_omx_port_use_buffers (GstOMXPort * port, const GList * buffers)
2663 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2665 g_mutex_lock (&port->comp->lock);
2666 n = g_list_length ((GList *) buffers);
2667 err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
2668 port->allocation = GST_OMX_BUFFER_ALLOCATION_USE_BUFFER;
2669 g_mutex_unlock (&port->comp->lock);
2675 gst_omx_is_dynamic_allocation_supported (void)
2677 /* The Zynqultrascaleplus stack implements OMX 1.1.0 but supports the dynamic
2678 * allocation mode from 1.2.0 as an extension. */
2679 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
2683 #if OMX_VERSION_MINOR == 2
2690 /* OMX 1.2.0 introduced a dynamic allocation mode where only buffer headers are
2691 * being allocated during component's initialization. The actual buffers are
2692 * allocated upstream and passed to OMX by setting the pBuffer dynamically
2693 * for each input buffer.
2695 * This function takes care of allocating the buffer headers. Element should
2696 * then use one of the gst_omx_buffer_map_*() method to update buffer's pBuffer
2697 * pointers for each incoming buffer.
2699 * NOTE: Uses comp->lock and comp->messages_lock */
2701 gst_omx_port_use_dynamic_buffers (GstOMXPort * port)
2704 GList *buffers = NULL;
2707 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2709 n = port->port_def.nBufferCountActual;
2710 for (i = 0; i < port->port_def.nBufferCountActual; i++)
2711 /* Pass NULL to UseBuffer() as the buffer is dynamic and so its payload
2712 * will be set each time before being passed to OMX. */
2713 buffers = g_list_prepend (buffers, GUINT_TO_POINTER (NULL));
2715 g_mutex_lock (&port->comp->lock);
2716 err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
2717 port->allocation = GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC;
2718 g_mutex_unlock (&port->comp->lock);
2720 g_list_free (buffers);
2725 /* gst_omx_buffer_map_* methods are used in dynamic buffer mode to map
2726 * a frame/memory/buffer and update @buffer so its pBuffer points to the
2727 * mapped data. It also ensures that the input will stay alive until
2728 * gst_omx_buffer_unmap() is called.
2729 * This is used in OMX 1.2.0 dynamic allocation mode so an OMX component can
2730 * safely process @buffer's content without having to copy it.
2731 * The input will be automatically unmapped when @buffer is released by OMX.
2734 gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input,
2735 GstVideoInfo * info)
2737 g_return_val_if_fail (buffer != NULL, FALSE);
2738 g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
2739 g_return_val_if_fail (!buffer->input_mem, FALSE);
2740 g_return_val_if_fail (!buffer->input_buffer, FALSE);
2741 g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
2743 if (!gst_video_frame_map (&buffer->input_frame, info, input, GST_MAP_READ))
2746 buffer->input_frame_mapped = TRUE;
2747 buffer->omx_buf->pBuffer =
2748 GST_VIDEO_FRAME_PLANE_DATA (&buffer->input_frame, 0);
2749 buffer->omx_buf->nAllocLen = gst_buffer_get_size (input);
2750 buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
2756 gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem)
2758 g_return_val_if_fail (buffer != NULL, FALSE);
2759 g_return_val_if_fail (mem != NULL, FALSE);
2760 g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
2761 g_return_val_if_fail (!buffer->input_mem, FALSE);
2762 g_return_val_if_fail (!buffer->input_buffer, FALSE);
2763 g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
2765 if (!gst_memory_map (mem, &buffer->map, GST_MAP_READ))
2768 buffer->input_mem = gst_memory_ref (mem);
2769 buffer->omx_buf->pBuffer = buffer->map.data;
2770 buffer->omx_buf->nAllocLen = buffer->map.size;
2771 buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
2777 gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input)
2782 g_return_val_if_fail (buffer != NULL, FALSE);
2783 g_return_val_if_fail (input != NULL, FALSE);
2784 g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
2785 g_return_val_if_fail (!buffer->input_mem, FALSE);
2786 g_return_val_if_fail (!buffer->input_buffer, FALSE);
2787 g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
2789 mem = gst_buffer_peek_memory (input, 0);
2790 g_return_val_if_fail (gst_is_dmabuf_memory (mem), FALSE);
2792 fd = gst_dmabuf_memory_get_fd (mem);
2794 buffer->input_buffer = gst_buffer_ref (input);
2795 buffer->omx_buf->pBuffer = GUINT_TO_POINTER (fd);
2796 buffer->omx_buf->nAllocLen = gst_memory_get_sizes (mem, NULL, NULL);
2797 buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
2803 gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input)
2805 g_return_val_if_fail (buffer != NULL, FALSE);
2806 g_return_val_if_fail (input != NULL, FALSE);
2807 g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
2808 g_return_val_if_fail (!buffer->input_mem, FALSE);
2809 g_return_val_if_fail (!buffer->input_buffer, FALSE);
2810 g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
2812 if (!gst_buffer_map (input, &buffer->map, GST_MAP_READ))
2815 buffer->input_buffer_mapped = TRUE;
2816 buffer->input_buffer = gst_buffer_ref (input);
2817 buffer->omx_buf->pBuffer = buffer->map.data;
2818 buffer->omx_buf->nAllocLen = buffer->map.size;
2819 buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
2824 /* NOTE: Uses comp->lock and comp->messages_lock */
2826 gst_omx_port_use_eglimages (GstOMXPort * port, const GList * images)
2831 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2833 g_mutex_lock (&port->comp->lock);
2834 n = g_list_length ((GList *) images);
2835 err = gst_omx_port_allocate_buffers_unlocked (port, NULL, images, n);
2836 g_mutex_unlock (&port->comp->lock);
2841 /* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
2842 static OMX_ERRORTYPE
2843 gst_omx_port_deallocate_buffers_unlocked (GstOMXPort * port)
2845 GstOMXComponent *comp;
2846 OMX_ERRORTYPE err = OMX_ErrorNone;
2849 g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter);
2853 GST_INFO_OBJECT (comp->parent, "Deallocating buffers of %s port %u",
2854 comp->name, port->index);
2856 gst_omx_component_handle_messages (port->comp);
2858 if (!port->buffers) {
2859 GST_DEBUG_OBJECT (comp->parent, "No buffers allocated for %s port %u",
2860 comp->name, port->index);
2864 if ((err = comp->last_error) != OMX_ErrorNone) {
2865 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
2866 comp->name, gst_omx_error_to_string (err), err);
2867 /* We still try to deallocate all buffers */
2870 /* We only allow deallocation of buffers after they
2871 * were all released from the port, either by flushing
2872 * the port or by disabling it.
2874 n = port->buffers->len;
2875 for (i = 0; i < n; i++) {
2876 GstOMXBuffer *buf = g_ptr_array_index (port->buffers, i);
2877 OMX_ERRORTYPE tmp = OMX_ErrorNone;
2880 GST_ERROR_OBJECT (comp->parent, "Trying to free used buffer %p of %s "
2881 "port %u", buf, comp->name, port->index);
2884 /* omx_buf can be NULL if allocation failed earlier
2885 * and we're just shutting down
2887 * errors do not cause exiting this loop because we want
2888 * to deallocate as much as possible.
2891 g_assert (buf == buf->omx_buf->pAppPrivate);
2892 buf->omx_buf->pAppPrivate = NULL;
2893 GST_DEBUG_OBJECT (comp->parent, "%s: deallocating buffer %p (%p)",
2894 comp->name, buf, buf->omx_buf->pBuffer);
2896 tmp = OMX_FreeBuffer (comp->handle, port->index, buf->omx_buf);
2898 if (tmp != OMX_ErrorNone) {
2899 GST_ERROR_OBJECT (comp->parent,
2900 "Failed to deallocate buffer %d of %s port %u: %s (0x%08x)", i,
2901 comp->name, port->index, gst_omx_error_to_string (tmp), tmp);
2902 if (err == OMX_ErrorNone)
2906 g_slice_free (GstOMXBuffer, buf);
2908 g_queue_clear (&port->pending_buffers);
2909 g_ptr_array_unref (port->buffers);
2910 port->buffers = NULL;
2912 gst_omx_component_handle_messages (comp);
2915 gst_omx_port_update_port_definition (port, NULL);
2917 DEBUG_IF_OK (comp->parent, err, "Deallocated buffers of %s port %u: %s "
2918 "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
2923 /* NOTE: Uses comp->lock and comp->messages_lock */
2925 gst_omx_port_deallocate_buffers (GstOMXPort * port)
2929 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
2931 g_mutex_lock (&port->comp->lock);
2932 err = gst_omx_port_deallocate_buffers_unlocked (port);
2933 g_mutex_unlock (&port->comp->lock);
2938 /* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
2939 static OMX_ERRORTYPE
2940 gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
2942 GstOMXComponent *comp;
2943 OMX_ERRORTYPE err = OMX_ErrorNone;
2947 gst_omx_component_handle_messages (comp);
2949 if ((err = comp->last_error) != OMX_ErrorNone) {
2950 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
2951 comp->name, gst_omx_error_to_string (err), err);
2955 if (port->enabled_pending || port->disabled_pending) {
2956 GST_ERROR_OBJECT (comp->parent, "%s port %d enabled/disabled pending "
2957 "already", comp->name, port->index);
2958 #if OMX_VERSION_MINOR == 2
2959 err = OMX_ErrorBadParameter;
2961 err = OMX_ErrorInvalidState;
2966 GST_INFO_OBJECT (comp->parent, "Setting %s port %u to %s", comp->name,
2967 port->index, (enabled ? "enabled" : "disabled"));
2969 /* Check if the port is already enabled/disabled first */
2970 gst_omx_port_update_port_definition (port, NULL);
2971 if (! !port->port_def.bEnabled == ! !enabled)
2975 port->enabled_pending = TRUE;
2977 port->disabled_pending = TRUE;
2981 gst_omx_component_send_command (comp, OMX_CommandPortEnable,
2985 gst_omx_component_send_command (comp, OMX_CommandPortDisable,
2988 if (err != OMX_ErrorNone) {
2989 GST_ERROR_OBJECT (comp->parent,
2990 "Failed to send enable/disable command to %s port %u: %s (0x%08x)",
2991 comp->name, port->index, gst_omx_error_to_string (err), err);
2995 if ((err = comp->last_error) != OMX_ErrorNone) {
2996 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
2997 comp->name, gst_omx_error_to_string (err), err);
3002 gst_omx_component_handle_messages (comp);
3004 gst_omx_port_update_port_definition (port, NULL);
3006 INFO_IF_OK (comp->parent, err, "Set %s port %u to %s%s: %s (0x%08x)",
3007 comp->name, port->index, (err == OMX_ErrorNone ? "" : "not "),
3008 (enabled ? "enabled" : "disabled"), gst_omx_error_to_string (err), err);
3013 static OMX_ERRORTYPE
3014 gst_omx_port_wait_buffers_released_unlocked (GstOMXPort * port,
3015 GstClockTime timeout)
3017 GstOMXComponent *comp;
3018 OMX_ERRORTYPE err = OMX_ErrorNone;
3019 OMX_ERRORTYPE last_error;
3024 gst_omx_component_handle_messages (comp);
3026 if ((err = comp->last_error) != OMX_ErrorNone) {
3027 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
3028 comp->name, gst_omx_error_to_string (err), err);
3032 GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to release all "
3033 "buffers", comp->name, port->index);
3036 if (!port->flushed || (port->buffers
3037 && port->buffers->len >
3038 g_queue_get_length (&port->pending_buffers)))
3039 err = OMX_ErrorTimeout;
3043 /* Wait until all buffers are released by the port */
3045 last_error = OMX_ErrorNone;
3046 gst_omx_component_handle_messages (comp);
3047 while (signalled && last_error == OMX_ErrorNone && (port->buffers
3048 && port->buffers->len >
3049 g_queue_get_length (&port->pending_buffers))) {
3050 signalled = gst_omx_component_wait_message (comp, timeout);
3052 gst_omx_component_handle_messages (comp);
3053 last_error = comp->last_error;
3056 if (last_error != OMX_ErrorNone) {
3058 GST_ERROR_OBJECT (comp->parent,
3059 "Got error while waiting for %s port %u to release all buffers: %s "
3060 "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err),
3063 } else if (!signalled) {
3064 GST_ERROR_OBJECT (comp->parent, "Timeout waiting for %s port %u to "
3065 "release all buffers", comp->name, port->index);
3066 err = OMX_ErrorTimeout;
3071 gst_omx_component_handle_messages (comp);
3073 gst_omx_port_update_port_definition (port, NULL);
3075 DEBUG_IF_OK (comp->parent, err,
3076 "Waited for %s port %u to release all buffers: %s (0x%08x)", comp->name,
3077 port->index, gst_omx_error_to_string (err), err);
3082 /* NOTE: Uses comp->lock and comp->messages_lock */
3084 gst_omx_port_wait_buffers_released (GstOMXPort * port, GstClockTime timeout)
3088 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
3090 g_mutex_lock (&port->comp->lock);
3091 err = gst_omx_port_wait_buffers_released_unlocked (port, timeout);
3092 g_mutex_unlock (&port->comp->lock);
3098 gst_omx_port_requeue_buffer (GstOMXPort * port, GstOMXBuffer * buf)
3100 g_mutex_lock (&port->comp->lock);
3101 g_queue_push_tail (&port->pending_buffers, buf);
3102 g_mutex_unlock (&port->comp->lock);
3104 /* awake gst_omx_port_acquire_buffer() */
3105 gst_omx_component_send_message (port->comp, NULL);
3108 /* NOTE: Uses comp->lock and comp->messages_lock */
3110 gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled)
3114 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
3116 g_mutex_lock (&port->comp->lock);
3117 err = gst_omx_port_set_enabled_unlocked (port, enabled);
3118 g_mutex_unlock (&port->comp->lock);
3123 static OMX_ERRORTYPE
3124 gst_omx_port_populate_unlocked (GstOMXPort * port)
3126 GstOMXComponent *comp;
3127 OMX_ERRORTYPE err = OMX_ErrorNone;
3130 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
3134 GST_DEBUG_OBJECT (comp->parent, "Populating %s port %d", comp->name,
3137 gst_omx_component_handle_messages (comp);
3139 if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
3140 GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing or disabled",
3141 comp->name, port->index);
3142 err = OMX_ErrorIncorrectStateOperation;
3146 if ((err = comp->last_error) != OMX_ErrorNone) {
3147 GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s"
3148 "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
3152 if (port->port_def.eDir == OMX_DirOutput && port->buffers && !port->tunneled) {
3153 /* Enqueue all buffers for the component to fill */
3154 while ((buf = g_queue_pop_head (&port->pending_buffers))) {
3155 g_assert (!buf->used);
3157 /* Reset all flags, some implementations don't
3158 * reset them themselves and the flags are not
3159 * valid anymore after the buffer was consumed.
3160 * Also reset nFilledLen as FillThisBuffer() expects an empty buffer.
3162 gst_omx_buffer_reset (buf);
3164 log_omx_api_trace_buffer (comp, "FillThisBuffer", buf);
3165 err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
3167 if (err != OMX_ErrorNone) {
3168 GST_ERROR_OBJECT (comp->parent,
3169 "Failed to pass buffer %p (%p) to %s port %u: %s (0x%08x)", buf,
3170 buf->omx_buf->pBuffer, comp->name, port->index,
3171 gst_omx_error_to_string (err), err);
3174 GST_DEBUG_OBJECT (comp->parent, "Passed buffer %p (%p) to component %s",
3175 buf, buf->omx_buf->pBuffer, comp->name);
3180 gst_omx_port_update_port_definition (port, NULL);
3182 DEBUG_IF_OK (comp->parent, err, "Populated %s port %u: %s (0x%08x)",
3183 comp->name, port->index, gst_omx_error_to_string (err), err);
3184 gst_omx_component_handle_messages (comp);
3189 /* NOTE: Uses comp->lock and comp->messages_lock */
3191 gst_omx_port_populate (GstOMXPort * port)
3195 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
3197 g_mutex_lock (&port->comp->lock);
3198 err = gst_omx_port_populate_unlocked (port);
3199 g_mutex_unlock (&port->comp->lock);
3204 /* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
3205 static OMX_ERRORTYPE
3206 gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
3208 GstOMXComponent *comp;
3209 OMX_ERRORTYPE err = OMX_ErrorNone;
3211 OMX_ERRORTYPE last_error;
3216 /* Check the current port status */
3217 gst_omx_port_update_port_definition (port, NULL);
3219 if (port->enabled_pending)
3221 else if (port->disabled_pending)
3224 enabled = port->port_def.bEnabled;
3226 gst_omx_component_handle_messages (comp);
3228 if ((err = comp->last_error) != OMX_ErrorNone) {
3229 GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
3230 comp->name, gst_omx_error_to_string (err), err);
3234 GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to be %s",
3235 comp->name, port->index, (enabled ? "enabled" : "disabled"));
3238 if (port->enabled_pending || port->disabled_pending)
3239 err = OMX_ErrorTimeout;
3243 /* And now wait until the enable/disable command is finished */
3245 last_error = OMX_ErrorNone;
3246 gst_omx_port_update_port_definition (port, NULL);
3247 gst_omx_component_handle_messages (comp);
3248 while (signalled && last_error == OMX_ErrorNone &&
3249 (! !port->port_def.bEnabled != ! !enabled || port->enabled_pending
3250 || port->disabled_pending)) {
3251 signalled = gst_omx_component_wait_message (comp, timeout);
3253 gst_omx_component_handle_messages (comp);
3254 last_error = comp->last_error;
3255 gst_omx_port_update_port_definition (port, NULL);
3257 port->enabled_pending = FALSE;
3258 port->disabled_pending = FALSE;
3261 GST_ERROR_OBJECT (comp->parent,
3262 "Timeout waiting for %s port %u to be %s", comp->name, port->index,
3263 (enabled ? "enabled" : "disabled"));
3264 err = OMX_ErrorTimeout;
3266 } else if (last_error != OMX_ErrorNone) {
3267 GST_ERROR_OBJECT (comp->parent,
3268 "Got error while waiting for %s port %u to be %s: %s (0x%08x)",
3269 comp->name, port->index, (enabled ? "enabled" : "disabled"),
3270 gst_omx_error_to_string (err), err);
3274 /* Reset EOS flag */
3279 gst_omx_component_handle_messages (comp);
3282 gst_omx_port_update_port_definition (port, NULL);
3284 GST_INFO_OBJECT (comp->parent, "%s port %u is %s%s: %s (0x%08x)", comp->name,
3285 port->index, (err == OMX_ErrorNone ? "" : "not "),
3286 (enabled ? "enabled" : "disabled"), gst_omx_error_to_string (err), err);
3291 /* NOTE: Uses comp->lock and comp->messages_lock */
3293 gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout)
3297 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
3299 g_mutex_lock (&port->comp->lock);
3300 err = gst_omx_port_wait_enabled_unlocked (port, timeout);
3301 g_mutex_unlock (&port->comp->lock);
3307 gst_omx_port_is_enabled (GstOMXPort * port)
3311 g_return_val_if_fail (port != NULL, FALSE);
3313 gst_omx_port_update_port_definition (port, NULL);
3314 enabled = ! !port->port_def.bEnabled;
3316 GST_DEBUG_OBJECT (port->comp->parent, "%s port %u is enabled: %d",
3317 port->comp->name, port->index, enabled);
3322 /* NOTE: Uses comp->lock and comp->messages_lock */
3324 gst_omx_port_mark_reconfigured (GstOMXPort * port)
3326 GstOMXComponent *comp;
3327 OMX_ERRORTYPE err = OMX_ErrorNone;
3329 g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
3333 g_mutex_lock (&comp->lock);
3334 GST_INFO_OBJECT (comp->parent, "Marking %s port %u is reconfigured",
3335 comp->name, port->index);
3337 gst_omx_component_handle_messages (comp);
3339 if ((err = comp->last_error) != OMX_ErrorNone)
3342 port->configured_settings_cookie = port->settings_cookie;
3344 if (port->port_def.eDir == OMX_DirOutput) {
3347 for (l = comp->pending_reconfigure_outports; l; l = l->next) {
3348 if (l->data == (gpointer) port) {
3349 comp->pending_reconfigure_outports =
3350 g_list_delete_link (comp->pending_reconfigure_outports, l);
3354 if (!comp->pending_reconfigure_outports)
3355 gst_omx_component_send_message (comp, NULL);
3359 gst_omx_port_update_port_definition (port, NULL);
3361 INFO_IF_OK (comp->parent, err, "Marked %s port %u as reconfigured: %s "
3362 "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
3364 g_mutex_unlock (&comp->lock);
3369 /* The OMX specs states that the nBufferCountActual of a port has to default
3370 * to its nBufferCountMin. If we don't change nBufferCountActual we purely rely
3371 * on this default. But in some cases, OMX may change nBufferCountMin before we
3372 * allocate buffers. Like for example when configuring the input ports with the
3373 * actual format, it may decrease the number of minimal buffers required.
3374 * This method checks this and update nBufferCountActual if needed so we'll use
3375 * less buffers than the worst case in such scenarios.
3378 gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra)
3380 OMX_PARAM_PORTDEFINITIONTYPE port_def;
3383 gst_omx_port_get_port_definition (port, &port_def);
3385 nb = port_def.nBufferCountMin + extra;
3386 if (port_def.nBufferCountActual != nb) {
3387 port_def.nBufferCountActual = nb;
3389 GST_DEBUG_OBJECT (port->comp->parent,
3390 "set port %d nBufferCountActual to %d", (guint) port->index, nb);
3392 if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
3400 gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb)
3402 OMX_PARAM_PORTDEFINITIONTYPE port_def;
3404 gst_omx_port_get_port_definition (port, &port_def);
3406 if (nb < port_def.nBufferCountMin) {
3407 GST_DEBUG_OBJECT (port->comp->parent,
3408 "Requested to use %d buffers on port %d but it's minimum is %d", nb,
3409 (guint) port->index, (guint) port_def.nBufferCountMin);
3411 nb = port_def.nBufferCountMin;
3414 if (port_def.nBufferCountActual != nb) {
3415 port_def.nBufferCountActual = nb;
3417 GST_DEBUG_OBJECT (port->comp->parent,
3418 "set port %d nBufferCountActual to %d", (guint) port->index, nb);
3420 if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
3428 gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf)
3430 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
3431 OMX_ALG_PORT_PARAM_BUFFER_MODE buffer_mode;
3434 GST_OMX_INIT_STRUCT (&buffer_mode);
3435 buffer_mode.nPortIndex = port->index;
3438 buffer_mode.eMode = OMX_ALG_BUF_DMA;
3440 buffer_mode.eMode = OMX_ALG_BUF_NORMAL;
3443 gst_omx_component_set_parameter (port->comp,
3444 (OMX_INDEXTYPE) OMX_ALG_IndexPortParamBufferMode, &buffer_mode);
3445 if (err != OMX_ErrorNone) {
3446 GST_WARNING_OBJECT (port->comp->parent,
3447 "Failed to set port %d in %sdmabuf mode: %s (0x%08x)",
3448 port->index, dmabuf ? "" : "non-", gst_omx_error_to_string (err), err);
3454 /* dmabuf not supported for this platform */
3460 gst_omx_port_set_subframe (GstOMXPort * port, gboolean enabled)
3462 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
3463 OMX_ALG_VIDEO_PARAM_SUBFRAME subframe_mode;
3466 GST_OMX_INIT_STRUCT (&subframe_mode);
3467 subframe_mode.nPortIndex = port->index;
3469 subframe_mode.bEnableSubframe = enabled;
3471 err = gst_omx_component_set_parameter (port->comp,
3472 (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSubframe, &subframe_mode);
3473 if (err != OMX_ErrorNone) {
3474 GST_WARNING_OBJECT (port->comp->parent,
3475 "Failed to %s subframe mode on port %d: %s (0x%08x)",
3476 enabled ? "enable" : "disable", port->index,
3477 gst_omx_error_to_string (err), err);
3483 /* subframe mode is not supported on this platform */
3489 gst_omx_port_get_subframe (GstOMXPort * port)
3491 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
3492 OMX_ALG_VIDEO_PARAM_SUBFRAME subframe_mode;
3495 GST_OMX_INIT_STRUCT (&subframe_mode);
3496 subframe_mode.nPortIndex = port->index;
3498 err = gst_omx_component_get_parameter (port->comp,
3499 (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSubframe, &subframe_mode);
3500 if (err != OMX_ErrorNone) {
3501 GST_WARNING_OBJECT (port->comp->parent,
3502 "Failed to get subframe mode on port %d: %s (0x%08x)",
3503 port->index, gst_omx_error_to_string (err), err);
3507 return subframe_mode.bEnableSubframe;
3509 /* subframe mode is not supported on this platform */
3514 typedef GType (*GGetTypeFunction) (void);
3516 static const GGetTypeFunction types[] = {
3517 gst_omx_analog_audio_sink_get_type, gst_omx_hdmi_audio_sink_get_type,
3518 gst_omx_mpeg2_video_dec_get_type, gst_omx_mpeg4_video_dec_get_type,
3519 gst_omx_h264_dec_get_type, gst_omx_h263_dec_get_type,
3520 gst_omx_wmv_dec_get_type, gst_omx_mpeg4_video_enc_get_type,
3521 gst_omx_h264_enc_get_type, gst_omx_h263_enc_get_type,
3522 gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type,
3523 gst_omx_aac_dec_get_type, gst_omx_mp3_dec_get_type,
3524 gst_omx_aac_dec_get_type, gst_omx_mp3_enc_get_type,
3525 gst_omx_amr_dec_get_type
3527 , gst_omx_vp8_dec_get_type
3530 , gst_omx_theora_dec_get_type
3533 , gst_omx_h265_enc_get_type, gst_omx_h265_dec_get_type
3539 GType (*get_type) (void);
3543 static const struct TypeOffest base_types[] = {
3544 {gst_omx_audio_sink_get_type, G_STRUCT_OFFSET (GstOMXAudioSinkClass, cdata)},
3545 {gst_omx_video_dec_get_type, G_STRUCT_OFFSET (GstOMXVideoDecClass, cdata)},
3546 {gst_omx_video_enc_get_type, G_STRUCT_OFFSET (GstOMXVideoEncClass, cdata)},
3547 {gst_omx_audio_dec_get_type, G_STRUCT_OFFSET (GstOMXAudioDecClass, cdata)},
3548 {gst_omx_audio_enc_get_type, G_STRUCT_OFFSET (GstOMXAudioEncClass, cdata)},
3551 static GKeyFile *config = NULL;
3553 gst_omx_get_configuration (void)
3559 gst_omx_error_to_string (OMX_ERRORTYPE err)
3561 guint err_u = (guint) err;
3566 case OMX_ErrorInsufficientResources:
3567 return "Insufficient resources";
3568 case OMX_ErrorUndefined:
3570 case OMX_ErrorInvalidComponentName:
3571 return "Invalid component name";
3572 case OMX_ErrorComponentNotFound:
3573 return "Component not found";
3574 case OMX_ErrorBadParameter:
3575 return "Bad parameter";
3576 case OMX_ErrorNotImplemented:
3577 return "Not implemented";
3578 case OMX_ErrorUnderflow:
3580 case OMX_ErrorOverflow:
3582 case OMX_ErrorHardware:
3584 case OMX_ErrorStreamCorrupt:
3585 return "Stream corrupt";
3586 case OMX_ErrorPortsNotCompatible:
3587 return "Ports not compatible";
3588 case OMX_ErrorResourcesLost:
3589 return "Resources lost";
3590 case OMX_ErrorNoMore:
3592 case OMX_ErrorVersionMismatch:
3593 return "Version mismatch";
3594 case OMX_ErrorNotReady:
3596 case OMX_ErrorTimeout:
3598 case OMX_ErrorSameState:
3599 return "Same state";
3600 case OMX_ErrorResourcesPreempted:
3601 return "Resources preempted";
3602 case OMX_ErrorIncorrectStateTransition:
3603 return "Incorrect state transition";
3604 case OMX_ErrorIncorrectStateOperation:
3605 return "Incorrect state operation";
3606 case OMX_ErrorUnsupportedSetting:
3607 return "Unsupported setting";
3608 case OMX_ErrorUnsupportedIndex:
3609 return "Unsupported index";
3610 case OMX_ErrorBadPortIndex:
3611 return "Bad port index";
3612 case OMX_ErrorPortUnpopulated:
3613 return "Port unpopulated";
3614 case OMX_ErrorComponentSuspended:
3615 return "Component suspended";
3616 case OMX_ErrorDynamicResourcesUnavailable:
3617 return "Dynamic resources unavailable";
3618 case OMX_ErrorMbErrorsInFrame:
3619 return "Macroblock errors in frame";
3620 case OMX_ErrorFormatNotDetected:
3621 return "Format not detected";
3622 case OMX_ErrorSeperateTablesUsed:
3623 return "Separate tables used";
3624 case OMX_ErrorTunnelingUnsupported:
3625 return "Tunneling unsupported";
3626 #if OMX_VERSION_MINOR == 1
3627 case OMX_ErrorInvalidComponent:
3628 return "Invalid component";
3629 case OMX_ErrorInvalidState:
3630 return "Invalid state";
3631 case OMX_ErrorPortUnresponsiveDuringAllocation:
3632 return "Port unresponsive during allocation";
3633 case OMX_ErrorPortUnresponsiveDuringDeallocation:
3634 return "Port unresponsive during deallocation";
3635 case OMX_ErrorPortUnresponsiveDuringStop:
3636 return "Port unresponsive during stop";
3637 case OMX_ErrorContentPipeOpenFailed:
3638 return "Content pipe open failed";
3639 case OMX_ErrorContentPipeCreationFailed:
3640 return "Content pipe creation failed";
3643 if (err_u >= (guint) OMX_ErrorKhronosExtensions
3644 && err_u < (guint) OMX_ErrorVendorStartUnused) {
3645 return "Khronos extension error";
3646 } else if (err_u >= (guint) OMX_ErrorVendorStartUnused
3647 && err_u < (guint) OMX_ErrorMax) {
3648 return "Vendor specific error";
3650 return "Unknown error";
3656 gst_omx_state_to_string (OMX_STATETYPE state)
3659 case OMX_StateInvalid:
3661 case OMX_StateLoaded:
3665 case OMX_StateExecuting:
3667 case OMX_StatePause:
3669 case OMX_StateWaitForResources:
3670 return "WaitForResources";
3672 if (state >= OMX_StateKhronosExtensions
3673 && state < OMX_StateVendorStartUnused)
3674 return "KhronosExtensionState";
3675 else if (state >= OMX_StateVendorStartUnused && state < OMX_StateMax)
3676 return "CustomVendorState";
3679 return "Unknown state";
3683 gst_omx_command_to_string (OMX_COMMANDTYPE cmd)
3686 case OMX_CommandStateSet:
3688 case OMX_CommandFlush:
3690 case OMX_CommandPortDisable:
3691 return "DisablePort";
3692 case OMX_CommandPortEnable:
3693 return "EnablePort";
3694 case OMX_CommandMarkBuffer:
3695 return "MarkBuffer";
3697 if (cmd >= OMX_CommandKhronosExtensions
3698 && cmd < OMX_CommandVendorStartUnused)
3699 return "KhronosExtensionCommand";
3700 if (cmd >= OMX_CommandVendorStartUnused && cmd < OMX_CommandMax)
3701 return "VendorExtensionCommand";
3704 return "Unknown command";
3707 struct BufferFlagString
3713 struct BufferFlagString buffer_flags_map[] = {
3714 {OMX_BUFFERFLAG_EOS, "eos"},
3715 {OMX_BUFFERFLAG_STARTTIME, "start-time"},
3716 {OMX_BUFFERFLAG_DECODEONLY, "decode-only"},
3717 {OMX_BUFFERFLAG_DATACORRUPT, "data-corrupt"},
3718 {OMX_BUFFERFLAG_ENDOFFRAME, "end-of-frame"},
3719 {OMX_BUFFERFLAG_SYNCFRAME, "sync-frame"},
3720 {OMX_BUFFERFLAG_EXTRADATA, "extra-data"},
3721 {OMX_BUFFERFLAG_CODECCONFIG, "codec-config"},
3722 /* Introduced in OMX 1.2.0 */
3723 #ifdef OMX_BUFFERFLAG_TIMESTAMPINVALID
3724 {OMX_BUFFERFLAG_TIMESTAMPINVALID, "timestamp-invalid"},
3726 #ifdef OMX_BUFFERFLAG_READONLY
3727 {OMX_BUFFERFLAG_READONLY, "read-only"},
3729 #ifdef OMX_BUFFERFLAG_ENDOFSUBFRAME
3730 {OMX_BUFFERFLAG_ENDOFSUBFRAME, "end-of-subframe"},
3732 #ifdef OMX_BUFFERFLAG_SKIPFRAME
3733 {OMX_BUFFERFLAG_SKIPFRAME, "skip-frame"},
3735 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
3736 {OMX_ALG_BUFFERFLAG_TOP_FIELD, "top-field"},
3737 {OMX_ALG_BUFFERFLAG_BOT_FIELD, "bottom-field"},
3744 gst_omx_buffer_flags_to_string (guint32 flags)
3753 /* Keep a cache of the string representation of the flags so we don't allocate
3754 * and free strings for each buffer. In practice we should only have a handfull
3755 * of flags so the cache won't consume much memory. */
3756 if (!buffer_flags_str) {
3757 G_LOCK (buffer_flags_str);
3758 buffer_flags_str = g_hash_table_new_full (NULL, NULL, NULL, g_free);
3759 G_UNLOCK (buffer_flags_str);
3762 str = g_hash_table_lookup (buffer_flags_str, GUINT_TO_POINTER (flags));
3766 for (i = 0; buffer_flags_map[i].str != NULL; i++) {
3767 if ((flags & buffer_flags_map[i].flag) == 0)
3771 s = g_string_new (buffer_flags_map[i].str);
3773 g_string_append_printf (s, ", %s", buffer_flags_map[i].str);
3779 str = g_string_free (s, FALSE);
3781 G_LOCK (buffer_flags_str);
3782 /* Transfer ownership of str to hash table */
3783 g_hash_table_insert (buffer_flags_str, GUINT_TO_POINTER (flags),
3785 G_UNLOCK (buffer_flags_str);
3790 #if defined(USE_OMX_TARGET_RPI)
3791 #define DEFAULT_HACKS (GST_OMX_HACK_NO_COMPONENT_ROLE | GST_OMX_HACK_HEIGHT_MULTIPLE_16)
3793 #define DEFAULT_HACKS (0)
3797 gst_omx_parse_hacks (gchar ** hacks)
3799 guint64 hacks_flags = DEFAULT_HACKS;
3805 if (g_str_equal (*hacks,
3806 "event-port-settings-changed-ndata-parameter-swap"))
3808 GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP;
3809 else if (g_str_equal (*hacks, "event-port-settings-changed-port-0-to-1"))
3810 hacks_flags |= GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1;
3811 else if (g_str_equal (*hacks, "video-framerate-integer"))
3812 hacks_flags |= GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER;
3813 else if (g_str_equal (*hacks, "syncframe-flag-not-used"))
3814 hacks_flags |= GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED;
3815 else if (g_str_equal (*hacks, "no-component-reconfigure"))
3816 hacks_flags |= GST_OMX_HACK_NO_COMPONENT_RECONFIGURE;
3817 else if (g_str_equal (*hacks, "no-empty-eos-buffer"))
3818 hacks_flags |= GST_OMX_HACK_NO_EMPTY_EOS_BUFFER;
3819 else if (g_str_equal (*hacks, "drain-may-not-return"))
3820 hacks_flags |= GST_OMX_HACK_DRAIN_MAY_NOT_RETURN;
3821 else if (g_str_equal (*hacks, "no-component-role"))
3822 hacks_flags |= GST_OMX_HACK_NO_COMPONENT_ROLE;
3823 else if (g_str_equal (*hacks, "no-disable-outport"))
3824 hacks_flags |= GST_OMX_HACK_NO_DISABLE_OUTPORT;
3825 else if (g_str_equal (*hacks, "signals-premature-eos"))
3826 hacks_flags |= GST_OMX_HACK_SIGNALS_PREMATURE_EOS;
3827 else if (g_str_equal (*hacks, "height-multiple-16"))
3828 hacks_flags |= GST_OMX_HACK_HEIGHT_MULTIPLE_16;
3829 else if (g_str_equal (*hacks, "pass-profile-to-decoder"))
3830 hacks_flags |= GST_OMX_HACK_PASS_PROFILE_TO_DECODER;
3831 else if (g_str_equal (*hacks, "pass-color-format-to-decoder"))
3832 hacks_flags |= GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER;
3833 else if (g_str_equal (*hacks, "ensure-buffer-count-actual"))
3834 hacks_flags |= GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL;
3836 GST_WARNING ("Unknown hack: %s", *hacks);
3845 gst_omx_set_default_role (GstOMXClassData * class_data,
3846 const gchar * default_role)
3848 if (!class_data->component_role)
3849 class_data->component_role = default_role;
3853 _class_init (gpointer g_class, gpointer data)
3855 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
3856 GstOMXClassData *class_data = NULL;
3858 const gchar *element_name = data;
3860 gchar *core_name, *component_name, *component_role;
3861 gint in_port_index, out_port_index;
3862 gchar *template_caps;
3863 GstPadTemplate *templ;
3871 /* Find the GstOMXClassData for this class */
3872 for (i = 0; i < G_N_ELEMENTS (base_types); i++) {
3873 GType gtype = base_types[i].get_type ();
3875 if (G_TYPE_CHECK_CLASS_TYPE (g_class, gtype)) {
3876 class_data = (GstOMXClassData *)
3877 (((guint8 *) g_class) + base_types[i].offset);
3882 g_assert (class_data != NULL);
3884 config = gst_omx_get_configuration ();
3886 /* This will alwaxys succeed, see check in plugin_init */
3887 core_name = g_key_file_get_string (config, element_name, "core-name", NULL);
3888 g_assert (core_name != NULL);
3889 class_data->core_name = core_name;
3891 g_key_file_get_string (config, element_name, "component-name", NULL);
3892 g_assert (component_name != NULL);
3893 class_data->component_name = component_name;
3895 /* If this fails we simply don't set a role */
3896 if ((component_role =
3897 g_key_file_get_string (config, element_name, "component-role",
3899 GST_DEBUG ("Using component-role '%s' for element '%s'", component_role,
3901 class_data->component_role = component_role;
3905 /* Now set the inport/outport indizes and assume sane defaults */
3908 g_key_file_get_integer (config, element_name, "in-port-index", &err);
3910 GST_DEBUG ("No 'in-port-index' set for element '%s', auto-detecting: %s",
3911 element_name, err->message);
3915 class_data->in_port_index = in_port_index;
3919 g_key_file_get_integer (config, element_name, "out-port-index", &err);
3921 GST_DEBUG ("No 'out-port-index' set for element '%s', auto-detecting: %s",
3922 element_name, err->message);
3923 out_port_index = -1;
3926 class_data->out_port_index = out_port_index;
3928 /* Add pad templates */
3930 if (class_data->type != GST_OMX_COMPONENT_TYPE_SOURCE) {
3931 if (!(template_caps =
3932 g_key_file_get_string (config, element_name, "sink-template-caps",
3935 ("No sink template caps specified for element '%s', using default '%s'",
3936 element_name, class_data->default_sink_template_caps);
3937 caps = gst_caps_from_string (class_data->default_sink_template_caps);
3938 g_assert (caps != NULL);
3941 caps = gst_caps_from_string (template_caps);
3944 ("Could not parse sink template caps '%s' for element '%s', using default '%s'",
3945 template_caps, element_name,
3946 class_data->default_sink_template_caps);
3947 caps = gst_caps_from_string (class_data->default_sink_template_caps);
3948 g_assert (caps != NULL);
3951 templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
3952 g_free (template_caps);
3953 gst_element_class_add_pad_template (element_class, templ);
3954 gst_caps_unref (caps);
3958 if (class_data->type != GST_OMX_COMPONENT_TYPE_SINK) {
3959 if (!(template_caps =
3960 g_key_file_get_string (config, element_name, "src-template-caps",
3963 ("No src template caps specified for element '%s', using default '%s'",
3964 element_name, class_data->default_src_template_caps);
3965 caps = gst_caps_from_string (class_data->default_src_template_caps);
3966 g_assert (caps != NULL);
3969 caps = gst_caps_from_string (template_caps);
3972 ("Could not parse src template caps '%s' for element '%s', using default '%s'",
3973 template_caps, element_name, class_data->default_src_template_caps);
3974 caps = gst_caps_from_string (class_data->default_src_template_caps);
3975 g_assert (caps != NULL);
3978 templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
3979 g_free (template_caps);
3980 gst_element_class_add_pad_template (element_class, templ);
3981 gst_caps_unref (caps);
3985 g_key_file_get_string_list (config, element_name, "hacks", NULL,
3987 #ifndef GST_DISABLE_GST_DEBUG
3988 gchar **walk = hacks;
3991 GST_DEBUG ("Using hack: %s", *walk);
3996 class_data->hacks = gst_omx_parse_hacks (hacks);
4002 plugin_init (GstPlugin * plugin)
4005 gchar **config_dirs;
4007 gchar *env_config_dir;
4008 const gchar *user_config_dir;
4009 const gchar *const *system_config_dirs;
4012 static const gchar *config_name[] = { "gstomx.conf", NULL };
4013 static const gchar *env_config_name[] = { "GST_OMX_CONFIG_DIR", NULL };
4014 static const gchar *gst_omx_config_dir = GST_OMX_CONFIG_DIR;
4016 GST_DEBUG_CATEGORY_INIT (gstomx_debug, "omx", 0, "gst-omx");
4017 GST_DEBUG_CATEGORY_INIT (gst_omx_video_debug_category, "omxvideo", 0,
4019 GST_DEBUG_CATEGORY_INIT (OMX_API_TRACE, "OMX_API_TRACE", 0,
4020 "gst-omx performace");
4022 /* Read configuration file gstomx.conf from the preferred
4023 * configuration directories */
4024 env_config_dir = g_strdup (g_getenv (*env_config_name));
4025 user_config_dir = g_get_user_config_dir ();
4026 system_config_dirs = g_get_system_config_dirs ();
4028 g_new (gchar *, g_strv_length ((gchar **) system_config_dirs) + 4);
4033 config_dirs[i++] = (gchar *) env_config_dir;
4034 config_dirs[i++] = (gchar *) user_config_dir;
4035 while (system_config_dirs[j])
4036 config_dirs[i++] = (gchar *) system_config_dirs[j++];
4037 config_dirs[i++] = (gchar *) gst_omx_config_dir;
4038 config_dirs[i++] = NULL;
4040 gst_plugin_add_dependency (plugin, env_config_name,
4041 (const gchar **) (config_dirs + (env_config_dir ? 1 : 0)), config_name,
4042 GST_PLUGIN_DEPENDENCY_FLAG_NONE);
4044 config = g_key_file_new ();
4045 if (!g_key_file_load_from_dirs (config, *config_name,
4046 (const gchar **) config_dirs, NULL, G_KEY_FILE_NONE, &err)) {
4047 #ifdef USE_OMX_TARGET_GENERIC
4048 GST_INFO ("No configuration file found; "
4049 "ignore as gst-omx has been built with the generic target used only for testing");
4054 paths = g_strjoinv (":", config_dirs);
4056 ("Failed to load configuration file: %s (searched in: %s as per "
4057 "GST_OMX_CONFIG_DIR environment variable, the xdg user config "
4058 "directory (or XDG_CONFIG_HOME) and the system config directory "
4059 "(or XDG_CONFIG_DIRS)", err->message, paths);
4062 #endif /* USE_OMX_TARGET_GENERIC */
4068 /* Initialize all types */
4069 for (i = 0; i < G_N_ELEMENTS (types); i++)
4072 elements = g_key_file_get_groups (config, &n_elements);
4073 for (i = 0; i < n_elements; i++) {
4074 GTypeQuery type_query;
4075 GTypeInfo type_info = { 0, };
4076 GType type, subtype;
4077 gchar *type_name, *core_name, *component_name;
4080 GST_DEBUG ("Registering element '%s'", elements[i]);
4084 g_key_file_get_string (config, elements[i], "type-name", &err))) {
4086 ("Unable to read 'type-name' configuration for element '%s': %s",
4087 elements[i], err->message);
4092 type = g_type_from_name (type_name);
4093 if (type == G_TYPE_INVALID) {
4094 GST_ERROR ("Invalid type name '%s' for element '%s'", type_name,
4099 if (!g_type_is_a (type, GST_TYPE_ELEMENT)) {
4100 GST_ERROR ("Type '%s' is no GstElement subtype for element '%s'",
4101 type_name, elements[i]);
4107 /* And now some sanity checking */
4110 g_key_file_get_string (config, elements[i], "core-name", &err))) {
4112 ("Unable to read 'core-name' configuration for element '%s': %s",
4113 elements[i], err->message);
4117 if (!g_file_test (core_name, G_FILE_TEST_IS_REGULAR)) {
4118 GST_ERROR ("Core '%s' does not exist for element '%s'", core_name,
4126 if (!(component_name =
4127 g_key_file_get_string (config, elements[i], "component-name",
4130 ("Unable to read 'component-name' configuration for element '%s': %s",
4131 elements[i], err->message);
4135 g_free (component_name);
4138 rank = g_key_file_get_integer (config, elements[i], "rank", &err);
4140 GST_ERROR ("No rank set for element '%s': %s", elements[i], err->message);
4145 /* And now register the type, all other configuration will
4146 * be handled by the type itself */
4147 g_type_query (type, &type_query);
4148 memset (&type_info, 0, sizeof (type_info));
4149 type_info.class_size = type_query.class_size;
4150 type_info.instance_size = type_query.instance_size;
4151 type_info.class_init = _class_init;
4152 type_info.class_data = g_strdup (elements[i]);
4153 type_name = g_strdup_printf ("%s-%s", g_type_name (type), elements[i]);
4154 if (g_type_from_name (type_name) != G_TYPE_INVALID) {
4155 GST_ERROR ("Type '%s' already exists for element '%s'", type_name,
4160 subtype = g_type_register_static (type, type_name, &type_info, 0);
4162 gst_element_register (plugin, elements[i], rank, subtype);
4164 g_strfreev (elements);
4167 g_free (env_config_dir);
4168 g_free (config_dirs);
4173 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
4176 "GStreamer OpenMAX Plug-ins",
4178 PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)