2 * Copyright (C) 2006-2007 Texas Instruments, Incorporated
3 * Copyright (C) 2007-2009 Nokia Corporation.
5 * Author: Felipe Contreras <felipe.contreras@nokia.com>
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
23 #include "gstomx_util.h"
28 GST_DEBUG_CATEGORY (gstomx_util_debug);
31 * Forward declarations
34 static inline void change_state (GOmxCore * core, OMX_STATETYPE state);
36 static inline void wait_for_state (GOmxCore * core, OMX_STATETYPE state);
39 in_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer);
42 out_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer);
45 got_buffer (GOmxCore * core,
46 GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer);
49 EventHandler (OMX_HANDLETYPE omx_handle,
51 OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data);
54 EmptyBufferDone (OMX_HANDLETYPE omx_handle,
55 OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer);
58 FillBufferDone (OMX_HANDLETYPE omx_handle,
59 OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer);
61 static inline const char *omx_state_to_str (OMX_STATETYPE omx_state);
63 static inline const char *omx_error_to_str (OMX_ERRORTYPE omx_error);
65 static inline GOmxPort *get_port (GOmxCore * core, guint index);
67 static void core_deinit (GOmxCore * core);
69 static inline void port_free_buffers (GOmxPort * port);
71 static inline void port_allocate_buffers (GOmxPort * port);
73 static inline void port_start_buffers (GOmxPort * port);
75 static OMX_CALLBACKTYPE callbacks =
76 { EventHandler, EmptyBufferDone, FillBufferDone };
78 /* protect implementations hash_table */
79 static GMutex *imp_mutex;
80 static GHashTable *implementations;
81 static gboolean initialized;
88 g_ptr_array_clear (GPtrArray * array)
91 for (index = 0; index < array->len; index++)
92 array->pdata[index] = NULL;
96 g_ptr_array_insert (GPtrArray * array, guint index, gpointer data)
98 if (index + 1 > array->len) {
99 g_ptr_array_set_size (array, index + 1);
102 array->pdata[index] = data;
105 typedef void (*GOmxPortFunc) (GOmxPort * port);
108 core_for_each_port (GOmxCore * core, GOmxPortFunc func)
112 for (index = 0; index < core->ports->len; index++) {
115 port = get_port (core, index);
126 static GOmxImp *imp_new (const gchar * name);
127 static void imp_free (GOmxImp * imp);
130 imp_new (const gchar * name)
134 imp = g_new0 (GOmxImp, 1);
136 /* Load the OpenMAX IL symbols */
140 GST_DEBUG ("loading: %s", name);
142 imp->dl_handle = handle = dlopen (name, RTLD_LAZY);
144 GST_DEBUG ("dlopen(%s) -> %p", name, handle);
147 g_warning ("%s\n", dlerror ());
152 imp->mutex = g_mutex_new ();
153 imp->sym_table.init = dlsym (handle, "OMX_Init");
154 imp->sym_table.deinit = dlsym (handle, "OMX_Deinit");
155 imp->sym_table.get_handle = dlsym (handle, "OMX_GetHandle");
156 imp->sym_table.free_handle = dlsym (handle, "OMX_FreeHandle");
163 imp_free (GOmxImp * imp)
165 if (imp->dl_handle) {
166 dlclose (imp->dl_handle);
168 g_mutex_free (imp->mutex);
172 static inline GOmxImp *
173 request_imp (const gchar * name)
177 g_mutex_lock (imp_mutex);
178 imp = g_hash_table_lookup (implementations, name);
180 imp = imp_new (name);
182 g_hash_table_insert (implementations, g_strdup (name), imp);
184 g_mutex_unlock (imp_mutex);
189 g_mutex_lock (imp->mutex);
190 if (imp->client_count == 0) {
191 OMX_ERRORTYPE omx_error;
192 omx_error = imp->sym_table.init ();
194 g_mutex_unlock (imp->mutex);
199 g_mutex_unlock (imp->mutex);
205 release_imp (GOmxImp * imp)
207 g_mutex_lock (imp->mutex);
209 if (imp->client_count == 0) {
210 imp->sym_table.deinit ();
212 g_mutex_unlock (imp->mutex);
219 /* safe as plugin_init is safe */
220 imp_mutex = g_mutex_new ();
221 implementations = g_hash_table_new_full (g_str_hash,
222 g_str_equal, g_free, (GDestroyNotify) imp_free);
231 g_hash_table_destroy (implementations);
232 g_mutex_free (imp_mutex);
242 g_omx_core_new (void *object)
246 core = g_new0 (GOmxCore, 1);
248 core->object = object;
249 core->ports = g_ptr_array_new ();
251 core->omx_state_condition = g_cond_new ();
252 core->omx_state_mutex = g_mutex_new ();
254 core->done_sem = g_sem_new ();
255 core->flush_sem = g_sem_new ();
256 core->port_sem = g_sem_new ();
258 core->omx_state = OMX_StateInvalid;
264 g_omx_core_free (GOmxCore * core)
268 g_sem_free (core->port_sem);
269 g_sem_free (core->flush_sem);
270 g_sem_free (core->done_sem);
272 g_mutex_free (core->omx_state_mutex);
273 g_cond_free (core->omx_state_condition);
275 g_ptr_array_free (core->ports, TRUE);
281 g_omx_core_init (GOmxCore * core)
283 GST_DEBUG_OBJECT (core->object, "loading: %s %s (%s)",
284 core->component_name,
285 core->component_role ? core->component_role : "", core->library_name);
287 core->imp = request_imp (core->library_name);
292 core->omx_error = core->imp->sym_table.get_handle (&core->omx_handle,
293 (char *) core->component_name, core, &callbacks);
295 GST_DEBUG_OBJECT (core->object, "OMX_GetHandle(&%p) -> %d",
296 core->omx_handle, core->omx_error);
298 if (!core->omx_error) {
299 core->omx_state = OMX_StateLoaded;
301 if (core->component_role) {
302 OMX_PARAM_COMPONENTROLETYPE param;
304 GST_DEBUG_OBJECT (core->object, "setting component role: %s",
305 core->component_role);
307 G_OMX_INIT_PARAM (param);
309 strncpy ((char *) param.cRole, core->component_role,
310 OMX_MAX_STRINGNAME_SIZE);
312 OMX_SetParameter (core->omx_handle, OMX_IndexParamStandardComponentRole,
316 /* Add_component_vendor */
317 if (strncmp(core->component_name+4, "SEC", 3) == 0)
319 core->component_vendor = GOMX_VENDOR_SLSI;
323 core->component_vendor = GOMX_VENDOR_DEFAULT;
329 core_deinit (GOmxCore * core)
334 if (core->omx_state == OMX_StateLoaded || core->omx_state == OMX_StateInvalid) {
335 if (core->omx_handle) {
336 core->omx_error = core->imp->sym_table.free_handle (core->omx_handle);
337 GST_DEBUG_OBJECT (core->object, "OMX_FreeHandle(%p) -> %d",
338 core->omx_handle, core->omx_error);
341 GST_WARNING_OBJECT (core->object, "Incorrect state: %s",
342 omx_state_to_str (core->omx_state));
345 g_free (core->library_name);
346 g_free (core->component_name);
347 g_free (core->component_role);
349 release_imp (core->imp);
354 g_omx_core_prepare (GOmxCore * core)
356 change_state (core, OMX_StateIdle);
358 /* Allocate buffers. */
359 core_for_each_port (core, port_allocate_buffers);
361 wait_for_state (core, OMX_StateIdle);
365 g_omx_core_start (GOmxCore * core)
367 change_state (core, OMX_StateExecuting);
368 wait_for_state (core, OMX_StateExecuting);
370 if (core->omx_state == OMX_StateExecuting)
371 core_for_each_port (core, port_start_buffers);
375 g_omx_core_stop (GOmxCore * core)
377 if (core->omx_state == OMX_StateExecuting ||
378 core->omx_state == OMX_StatePause) {
379 change_state (core, OMX_StateIdle);
380 wait_for_state (core, OMX_StateIdle);
385 g_omx_core_pause (GOmxCore * core)
387 change_state (core, OMX_StatePause);
388 wait_for_state (core, OMX_StatePause);
392 g_omx_core_unload (GOmxCore * core)
394 if (core->omx_state == OMX_StateIdle ||
395 core->omx_state == OMX_StateWaitForResources ||
396 core->omx_state == OMX_StateInvalid) {
397 if (core->omx_state != OMX_StateInvalid)
398 change_state (core, OMX_StateLoaded);
400 core_for_each_port (core, port_free_buffers);
402 if (core->omx_state != OMX_StateInvalid)
403 wait_for_state (core, OMX_StateLoaded);
406 core_for_each_port (core, g_omx_port_free);
407 g_ptr_array_clear (core->ports);
410 static inline GOmxPort *
411 get_port (GOmxCore * core, guint index)
413 if (G_LIKELY (index < core->ports->len)) {
414 return g_ptr_array_index (core->ports, index);
421 g_omx_core_new_port (GOmxCore * core, guint index)
423 GOmxPort *port = get_port (core, index);
426 GST_WARNING_OBJECT (core->object, "port %d already exists", index);
430 port = g_omx_port_new (core, index);
431 g_ptr_array_insert (core->ports, index, port);
437 g_omx_core_set_done (GOmxCore * core)
439 g_sem_up (core->done_sem);
443 g_omx_core_wait_for_done (GOmxCore * core)
445 g_sem_down (core->done_sem);
449 g_omx_core_flush_start (GOmxCore * core)
451 core_for_each_port (core, g_omx_port_pause);
455 g_omx_core_flush_stop (GOmxCore * core)
457 core_for_each_port (core, g_omx_port_flush);
458 core_for_each_port (core, g_omx_port_resume);
466 * note: this is not intended to be called directly by elements (which should
467 * instead use g_omx_core_new_port())
470 g_omx_port_new (GOmxCore * core, guint index)
473 port = g_new0 (GOmxPort, 1);
476 port->port_index = index;
477 port->num_buffers = 0;
478 port->buffer_size = 0;
479 port->buffers = NULL;
481 port->enabled = TRUE;
482 port->queue = async_queue_new ();
483 port->mutex = g_mutex_new ();
489 g_omx_port_free (GOmxPort * port)
491 g_mutex_free (port->mutex);
492 async_queue_free (port->queue);
494 g_free (port->buffers);
499 g_omx_port_setup (GOmxPort * port)
501 GOmxPortType type = -1;
502 OMX_PARAM_PORTDEFINITIONTYPE param;
504 G_OMX_INIT_PARAM (param);
506 param.nPortIndex = port->port_index;
507 OMX_GetParameter (port->core->omx_handle, OMX_IndexParamPortDefinition,
510 switch (param.eDir) {
512 type = GOMX_PORT_INPUT;
515 type = GOMX_PORT_OUTPUT;
522 /** @todo should it be nBufferCountMin? */
523 port->num_buffers = param.nBufferCountActual;
524 port->buffer_size = param.nBufferSize;
526 GST_DEBUG_OBJECT (port->core->object,
527 "type=%d, num_buffers=%d, buffer_size=%ld, port_index=%d",
528 port->type, port->num_buffers, port->buffer_size, port->port_index);
530 g_free (port->buffers);
531 port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers);
535 port_allocate_buffers (GOmxPort * port)
540 size = port->buffer_size;
542 for (i = 0; i < port->num_buffers; i++) {
543 if (port->omx_allocate) {
544 GST_DEBUG_OBJECT (port->core->object,
545 "%d: OMX_AllocateBuffer(), size=%" G_GSIZE_FORMAT, i, size);
546 OMX_AllocateBuffer (port->core->omx_handle, &port->buffers[i],
547 port->port_index, NULL, size);
549 gpointer buffer_data;
550 buffer_data = g_malloc (size);
551 GST_DEBUG_OBJECT (port->core->object,
552 "%d: OMX_UseBuffer(), size=%" G_GSIZE_FORMAT, i, size);
553 OMX_UseBuffer (port->core->omx_handle, &port->buffers[i],
554 port->port_index, NULL, size, buffer_data);
560 port_free_buffers (GOmxPort * port)
564 for (i = 0; i < port->num_buffers; i++) {
565 OMX_BUFFERHEADERTYPE *omx_buffer;
567 omx_buffer = port->buffers[i];
571 /** @todo how shall we free that buffer? */
572 if (!port->omx_allocate) {
573 g_free (omx_buffer->pBuffer);
574 omx_buffer->pBuffer = NULL;
578 OMX_FreeBuffer (port->core->omx_handle, port->port_index, omx_buffer);
579 port->buffers[i] = NULL;
585 port_start_buffers (GOmxPort * port)
589 for (i = 0; i < port->num_buffers; i++) {
590 OMX_BUFFERHEADERTYPE *omx_buffer;
592 omx_buffer = port->buffers[i];
594 /* If it's an input port we will need to fill the buffer, so put it in
595 * the queue, otherwise send to omx for processing (fill it up). */
596 if (port->type == GOMX_PORT_INPUT)
597 got_buffer (port->core, port, omx_buffer);
599 g_omx_port_release_buffer (port, omx_buffer);
604 g_omx_port_push_buffer (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
606 async_queue_push (port->queue, omx_buffer);
609 OMX_BUFFERHEADERTYPE *
610 g_omx_port_request_buffer (GOmxPort * port)
612 return async_queue_pop (port->queue);
616 g_omx_port_release_buffer (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
618 switch (port->type) {
619 case GOMX_PORT_INPUT:
620 OMX_EmptyThisBuffer (port->core->omx_handle, omx_buffer);
622 case GOMX_PORT_OUTPUT:
623 OMX_FillThisBuffer (port->core->omx_handle, omx_buffer);
631 g_omx_port_resume (GOmxPort * port)
633 async_queue_enable (port->queue);
637 g_omx_port_pause (GOmxPort * port)
639 async_queue_disable (port->queue);
643 g_omx_port_flush (GOmxPort * port)
645 if (port->type == GOMX_PORT_OUTPUT) {
646 OMX_BUFFERHEADERTYPE *omx_buffer;
647 while ((omx_buffer = async_queue_pop_forced (port->queue))) {
648 omx_buffer->nFilledLen = 0;
649 g_omx_port_release_buffer (port, omx_buffer);
652 OMX_SendCommand (port->core->omx_handle, OMX_CommandFlush, port->port_index,
654 g_sem_down (port->core->flush_sem);
659 g_omx_port_enable (GOmxPort * port)
665 OMX_SendCommand (core->omx_handle, OMX_CommandPortEnable, port->port_index,
667 port_allocate_buffers (port);
668 if (core->omx_state != OMX_StateLoaded)
669 port_start_buffers (port);
670 g_omx_port_resume (port);
672 g_sem_down (core->port_sem);
676 g_omx_port_disable (GOmxPort * port)
682 OMX_SendCommand (core->omx_handle, OMX_CommandPortDisable, port->port_index,
684 g_omx_port_pause (port);
685 g_omx_port_flush (port);
686 port_free_buffers (port);
688 g_sem_down (core->port_sem);
692 g_omx_port_finish (GOmxPort * port)
694 port->enabled = FALSE;
695 async_queue_disable (port->queue);
703 change_state (GOmxCore * core, OMX_STATETYPE state)
705 GST_DEBUG_OBJECT (core->object, "state=%d", state);
706 OMX_SendCommand (core->omx_handle, OMX_CommandStateSet, state, NULL);
710 complete_change_state (GOmxCore * core, OMX_STATETYPE state)
712 g_mutex_lock (core->omx_state_mutex);
714 core->omx_state = state;
715 g_cond_signal (core->omx_state_condition);
716 GST_DEBUG_OBJECT (core->object, "state=%d", state);
718 g_mutex_unlock (core->omx_state_mutex);
722 wait_for_state (GOmxCore * core, OMX_STATETYPE state)
727 g_mutex_lock (core->omx_state_mutex);
729 if (core->omx_error != OMX_ErrorNone)
732 g_get_current_time (&tv);
733 g_time_val_add (&tv, 15 * G_USEC_PER_SEC);
736 if (core->omx_state != state) {
738 g_cond_timed_wait (core->omx_state_condition, core->omx_state_mutex,
742 GST_ERROR_OBJECT (core->object, "timed out switching from '%s' to '%s'",
743 omx_state_to_str (core->omx_state), omx_state_to_str (state));
747 if (core->omx_error != OMX_ErrorNone)
750 if (core->omx_state != state) {
751 GST_ERROR_OBJECT (core->object,
752 "wrong state received: state=%d, expected=%d", core->omx_state, state);
756 g_mutex_unlock (core->omx_state_mutex);
764 in_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
766 /** @todo remove this */
773 out_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
775 /** @todo remove this */
781 if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) {
782 g_omx_port_set_done (port);
789 got_buffer (GOmxCore * core, GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
791 if (G_UNLIKELY (!omx_buffer)) {
795 if (G_LIKELY (port)) {
796 g_omx_port_push_buffer (port, omx_buffer);
798 switch (port->type) {
799 case GOMX_PORT_INPUT:
800 in_port_cb (port, omx_buffer);
802 case GOMX_PORT_OUTPUT:
803 out_port_cb (port, omx_buffer);
812 * OpenMAX IL callbacks.
816 EventHandler (OMX_HANDLETYPE omx_handle,
818 OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
822 core = (GOmxCore *) app_data;
825 case OMX_EventCmdComplete:
829 cmd = (OMX_COMMANDTYPE) data_1;
831 GST_DEBUG_OBJECT (core->object, "OMX_EventCmdComplete: %d", cmd);
834 case OMX_CommandStateSet:
835 complete_change_state (core, data_2);
837 case OMX_CommandFlush:
838 g_sem_up (core->flush_sem);
840 case OMX_CommandPortDisable:
841 case OMX_CommandPortEnable:
842 g_sem_up (core->port_sem);
848 case OMX_EventBufferFlag:
850 GST_DEBUG_OBJECT (core->object, "OMX_EventBufferFlag");
851 if (data_2 & OMX_BUFFERFLAG_EOS) {
852 g_omx_core_set_done (core);
856 case OMX_EventPortSettingsChanged:
858 GST_DEBUG_OBJECT (core->object, "OMX_EventPortSettingsChanged");
859 /** @todo only on the relevant port. */
860 if (core->settings_changed_cb) {
861 core->settings_changed_cb (core);
867 core->omx_error = data_1;
868 GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
869 omx_error_to_str (data_1), data_1);
870 /* component might leave us waiting for buffers, unblock */
871 g_omx_core_flush_start (core);
872 /* unlock wait_for_state */
873 g_mutex_lock (core->omx_state_mutex);
874 g_cond_signal (core->omx_state_condition);
875 g_mutex_unlock (core->omx_state_mutex);
882 return OMX_ErrorNone;
886 EmptyBufferDone (OMX_HANDLETYPE omx_handle,
887 OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer)
892 core = (GOmxCore *) app_data;
893 port = get_port (core, omx_buffer->nInputPortIndex);
895 GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer=%p",
897 omx_buffer->nFlags = 0x00000000;
898 got_buffer (core, port, omx_buffer);
900 return OMX_ErrorNone;
904 FillBufferDone (OMX_HANDLETYPE omx_handle,
905 OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer)
910 core = (GOmxCore *) app_data;
911 port = get_port (core, omx_buffer->nOutputPortIndex);
913 GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer=%p",
915 got_buffer (core, port, omx_buffer);
917 return OMX_ErrorNone;
920 static inline const char *
921 omx_state_to_str (OMX_STATETYPE omx_state)
924 case OMX_StateInvalid:
926 case OMX_StateLoaded:
930 case OMX_StateExecuting:
934 case OMX_StateWaitForResources:
935 return "wait for resources";
941 static inline const char *
942 omx_error_to_str (OMX_ERRORTYPE omx_error)
948 case OMX_ErrorInsufficientResources:
950 "There were insufficient resources to perform the requested operation";
952 case OMX_ErrorUndefined:
953 return "The cause of the error could not be determined";
955 case OMX_ErrorInvalidComponentName:
956 return "The component name string was not valid";
958 case OMX_ErrorComponentNotFound:
959 return "No component with the specified name string was found";
961 case OMX_ErrorInvalidComponent:
962 return "The component specified did not have an entry point";
964 case OMX_ErrorBadParameter:
965 return "One or more parameters were not valid";
967 case OMX_ErrorNotImplemented:
968 return "The requested function is not implemented";
970 case OMX_ErrorUnderflow:
971 return "The buffer was emptied before the next buffer was ready";
973 case OMX_ErrorOverflow:
974 return "The buffer was not available when it was needed";
976 case OMX_ErrorHardware:
977 return "The hardware failed to respond as expected";
979 case OMX_ErrorInvalidState:
980 return "The component is in invalid state";
982 case OMX_ErrorStreamCorrupt:
983 return "Stream is found to be corrupt";
985 case OMX_ErrorPortsNotCompatible:
986 return "Ports being connected are not compatible";
988 case OMX_ErrorResourcesLost:
989 return "Resources allocated to an idle component have been lost";
991 case OMX_ErrorNoMore:
992 return "No more indices can be enumerated";
994 case OMX_ErrorVersionMismatch:
995 return "The component detected a version mismatch";
997 case OMX_ErrorNotReady:
998 return "The component is not ready to return data at this time";
1000 case OMX_ErrorTimeout:
1001 return "There was a timeout that occurred";
1003 case OMX_ErrorSameState:
1005 "This error occurs when trying to transition into the state you are already in";
1007 case OMX_ErrorResourcesPreempted:
1009 "Resources allocated to an executing or paused component have been preempted";
1011 case OMX_ErrorPortUnresponsiveDuringAllocation:
1013 "Waited an unusually long time for the supplier to allocate buffers";
1015 case OMX_ErrorPortUnresponsiveDuringDeallocation:
1017 "Waited an unusually long time for the supplier to de-allocate buffers";
1019 case OMX_ErrorPortUnresponsiveDuringStop:
1021 "Waited an unusually long time for the non-supplier to return a buffer during stop";
1023 case OMX_ErrorIncorrectStateTransition:
1024 return "Attempting a state transition that is not allowed";
1026 case OMX_ErrorIncorrectStateOperation:
1028 "Attempting a command that is not allowed during the present state";
1030 case OMX_ErrorUnsupportedSetting:
1032 "The values encapsulated in the parameter or config structure are not supported";
1034 case OMX_ErrorUnsupportedIndex:
1036 "The parameter or config indicated by the given index is not supported";
1038 case OMX_ErrorBadPortIndex:
1039 return "The port index supplied is incorrect";
1041 case OMX_ErrorPortUnpopulated:
1043 "The port has lost one or more of its buffers and it thus unpopulated";
1045 case OMX_ErrorComponentSuspended:
1046 return "Component suspended due to temporary loss of resources";
1048 case OMX_ErrorDynamicResourcesUnavailable:
1050 "Component suspended due to an inability to acquire dynamic resources";
1052 case OMX_ErrorMbErrorsInFrame:
1053 return "Frame generated macroblock error";
1055 case OMX_ErrorFormatNotDetected:
1056 return "Cannot parse or determine the format of an input stream";
1058 case OMX_ErrorContentPipeOpenFailed:
1059 return "The content open operation failed";
1061 case OMX_ErrorContentPipeCreationFailed:
1062 return "The content creation operation failed";
1064 case OMX_ErrorSeperateTablesUsed:
1065 return "Separate table information is being used";
1067 case OMX_ErrorTunnelingUnsupported:
1068 return "Tunneling is unsupported by the component";
1071 return "Unknown error";