Remove core_finish, use core_unload
[gstreamer-omap:gst-openmax.git] / omx / gstomx_util.c
1 /*
2  * Copyright (C) 2006-2007 Texas Instruments, Incorporated
3  * Copyright (C) 2007-2009 Nokia Corporation.
4  *
5  * Author: Felipe Contreras <felipe.contreras@nokia.com>
6  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 #include "gstomx_util.h"
24 #include <dlfcn.h>
25
26 #include "gstomx.h"
27
28 GST_DEBUG_CATEGORY (gstomx_util_debug);
29
30 /*
31  * Forward declarations
32  */
33
34 static inline void
35 change_state (GOmxCore *core,
36               OMX_STATETYPE state);
37
38 static inline void
39 wait_for_state (GOmxCore *core,
40                 OMX_STATETYPE state);
41
42 static inline void
43 in_port_cb (GOmxPort *port,
44             OMX_BUFFERHEADERTYPE *omx_buffer);
45
46 static inline void
47 out_port_cb (GOmxPort *port,
48              OMX_BUFFERHEADERTYPE *omx_buffer);
49
50 static inline void
51 got_buffer (GOmxCore *core,
52             GOmxPort *port,
53             OMX_BUFFERHEADERTYPE *omx_buffer);
54
55 static OMX_ERRORTYPE
56 EventHandler (OMX_HANDLETYPE omx_handle,
57               OMX_PTR app_data,
58               OMX_EVENTTYPE event,
59               OMX_U32 data_1,
60               OMX_U32 data_2,
61               OMX_PTR event_data);
62
63 static OMX_ERRORTYPE
64 EmptyBufferDone (OMX_HANDLETYPE omx_handle,
65                  OMX_PTR app_data,
66                  OMX_BUFFERHEADERTYPE *omx_buffer);
67
68 static OMX_ERRORTYPE
69 FillBufferDone (OMX_HANDLETYPE omx_handle,
70                 OMX_PTR app_data,
71                 OMX_BUFFERHEADERTYPE *omx_buffer);
72
73 static inline const char *
74 omx_error_to_str (OMX_ERRORTYPE omx_error);
75
76 static inline GOmxPort *
77 g_omx_core_get_port (GOmxCore *core,
78                      guint index);
79
80 static inline void
81 port_free_buffers (GOmxPort *port);
82
83 static inline void
84 port_allocate_buffers (GOmxPort *port);
85
86 static inline void
87 port_start_buffers (GOmxPort *port);
88
89 static OMX_CALLBACKTYPE callbacks = { EventHandler, EmptyBufferDone, FillBufferDone };
90
91 /* protect implementations hash_table */
92 static GMutex *imp_mutex;
93 static GHashTable *implementations;
94 static gboolean initialized;
95
96 /*
97  * Util
98  */
99
100 static void
101 g_ptr_array_clear (GPtrArray *array)
102 {
103     guint index;
104     for (index = 0; index < array->len; index++)
105         array->pdata[index] = NULL;
106 }
107
108 static void
109 g_ptr_array_insert (GPtrArray *array,
110                     guint index,
111                     gpointer data)
112 {
113     if (index + 1 > array->len)
114     {
115         g_ptr_array_set_size (array, index + 1);
116     }
117
118     array->pdata[index] = data;
119 }
120
121 typedef void (*GOmxPortFunc) (GOmxPort *port);
122
123 static void inline
124 core_for_each_port (GOmxCore *core,
125                     GOmxPortFunc func)
126 {
127     guint index;
128
129     for (index = 0; index < core->ports->len; index++)
130     {
131         GOmxPort *port;
132
133         port = g_omx_core_get_port (core, index);
134
135         if (port)
136             func (port);
137     }
138 }
139
140 /*
141  * Main
142  */
143
144 static GOmxImp *imp_new (const gchar *name);
145 static void imp_free (GOmxImp *imp);
146
147 static GOmxImp *
148 imp_new (const gchar *name)
149 {
150     GOmxImp *imp;
151
152     imp = g_new0 (GOmxImp, 1);
153
154     /* Load the OpenMAX IL symbols */
155     {
156         void *handle;
157
158         imp->dl_handle = handle = dlopen (name, RTLD_LAZY);
159         if (!handle)
160         {
161             g_warning ("%s\n", dlerror ());
162             g_free (imp);
163             return NULL;
164         }
165
166         imp->mutex = g_mutex_new ();
167         imp->sym_table.init = dlsym (handle, "OMX_Init");
168         imp->sym_table.deinit = dlsym (handle, "OMX_Deinit");
169         imp->sym_table.get_handle = dlsym (handle, "OMX_GetHandle");
170         imp->sym_table.free_handle = dlsym (handle, "OMX_FreeHandle");
171     }
172
173     return imp;
174 }
175
176 static void
177 imp_free (GOmxImp *imp)
178 {
179     if (imp->dl_handle)
180     {
181         dlclose (imp->dl_handle);
182     }
183     g_mutex_free (imp->mutex);
184     g_free (imp);
185 }
186
187 static inline GOmxImp *
188 request_imp (const gchar *name)
189 {
190     GOmxImp *imp = NULL;
191
192     g_mutex_lock (imp_mutex);
193     imp = g_hash_table_lookup (implementations, name);
194     if (!imp)
195     {
196         imp = imp_new (name);
197         if (imp)
198             g_hash_table_insert (implementations, g_strdup (name), imp);
199     }
200     g_mutex_unlock (imp_mutex);
201
202     if (!imp)
203         return NULL;
204
205     g_mutex_lock (imp->mutex);
206     if (imp->client_count == 0)
207     {
208         OMX_ERRORTYPE omx_error;
209         omx_error = imp->sym_table.init ();
210         if (omx_error)
211         {
212             g_mutex_unlock (imp->mutex);
213             return NULL;
214         }
215     }
216     imp->client_count++;
217     g_mutex_unlock (imp->mutex);
218
219     return imp;
220 }
221
222 static inline void
223 release_imp (GOmxImp *imp)
224 {
225     g_mutex_lock (imp->mutex);
226     imp->client_count--;
227     if (imp->client_count == 0)
228     {
229         imp->sym_table.deinit ();
230     }
231     g_mutex_unlock (imp->mutex);
232 }
233
234 void
235 g_omx_init (void)
236 {
237     if (!initialized)
238     {
239         /* safe as plugin_init is safe */
240         imp_mutex = g_mutex_new ();
241         implementations = g_hash_table_new_full (g_str_hash,
242                                                  g_str_equal,
243                                                  g_free,
244                                                  (GDestroyNotify) imp_free);
245         initialized = TRUE;
246     }
247 }
248
249 void
250 g_omx_deinit (void)
251 {
252     if (initialized)
253     {
254         g_hash_table_destroy (implementations);
255         g_mutex_free (imp_mutex);
256         initialized = FALSE;
257     }
258 }
259
260 /*
261  * Core
262  */
263
264 GOmxCore *
265 g_omx_core_new (void)
266 {
267     GOmxCore *core;
268
269     core = g_new0 (GOmxCore, 1);
270
271     core->ports = g_ptr_array_new ();
272
273     core->omx_state_condition = g_cond_new ();
274     core->omx_state_mutex = g_mutex_new ();
275
276     core->done_sem = g_sem_new ();
277     core->flush_sem = g_sem_new ();
278     core->port_sem = g_sem_new ();
279
280     core->omx_state = OMX_StateInvalid;
281
282     return core;
283 }
284
285 void
286 g_omx_core_free (GOmxCore *core)
287 {
288     g_sem_free (core->port_sem);
289     g_sem_free (core->flush_sem);
290     g_sem_free (core->done_sem);
291
292     g_mutex_free (core->omx_state_mutex);
293     g_cond_free (core->omx_state_condition);
294
295     g_ptr_array_free (core->ports, TRUE);
296
297     g_free (core);
298 }
299
300 void
301 g_omx_core_init (GOmxCore *core,
302                  const gchar *library_name,
303                  const gchar *component_name)
304 {
305     core->imp = request_imp (library_name);
306
307     if (!core->imp)
308         return;
309
310     core->omx_error = core->imp->sym_table.get_handle (&core->omx_handle,
311                                                        (char *) component_name,
312                                                        core,
313                                                        &callbacks);
314     if (!core->omx_error)
315         core->omx_state = OMX_StateLoaded;
316 }
317
318 void
319 g_omx_core_deinit (GOmxCore *core)
320 {
321     if (!core->imp)
322         return;
323
324     core_for_each_port (core, g_omx_port_free);
325     g_ptr_array_clear (core->ports);
326
327     if (core->omx_state == OMX_StateLoaded ||
328         core->omx_state == OMX_StateInvalid)
329     {
330         if (core->omx_handle)
331             core->omx_error = core->imp->sym_table.free_handle (core->omx_handle);
332     }
333
334     release_imp (core->imp);
335     core->imp = NULL;
336 }
337
338 void
339 g_omx_core_prepare (GOmxCore *core)
340 {
341     change_state (core, OMX_StateIdle);
342
343     /* Allocate buffers. */
344     core_for_each_port (core, port_allocate_buffers);
345
346     wait_for_state (core, OMX_StateIdle);
347 }
348
349 void
350 g_omx_core_start (GOmxCore *core)
351 {
352     change_state (core, OMX_StateExecuting);
353     wait_for_state (core, OMX_StateExecuting);
354
355     if (core->omx_state == OMX_StateExecuting)
356         core_for_each_port (core, port_start_buffers);
357 }
358
359 void
360 g_omx_core_stop (GOmxCore *core)
361 {
362     if (core->omx_state == OMX_StateExecuting ||
363         core->omx_state == OMX_StatePause)
364     {
365         change_state (core, OMX_StateIdle);
366         wait_for_state (core, OMX_StateIdle);
367     }
368 }
369
370 void
371 g_omx_core_pause (GOmxCore *core)
372 {
373     change_state (core, OMX_StatePause);
374     wait_for_state (core, OMX_StatePause);
375 }
376
377 void
378 g_omx_core_unload (GOmxCore *core)
379 {
380     if (core->omx_state == OMX_StateIdle ||
381         core->omx_state == OMX_StateWaitForResources ||
382         core->omx_state == OMX_StateInvalid)
383     {
384         if (core->omx_state != OMX_StateInvalid)
385             change_state (core, OMX_StateLoaded);
386
387         core_for_each_port (core, port_free_buffers);
388
389         if (core->omx_state != OMX_StateInvalid)
390             wait_for_state (core, OMX_StateLoaded);
391     }
392 }
393
394 GOmxPort *
395 g_omx_core_setup_port (GOmxCore *core,
396                        OMX_PARAM_PORTDEFINITIONTYPE *omx_port)
397 {
398     GOmxPort *port;
399     guint index;
400
401     index = omx_port->nPortIndex;
402     port = g_omx_core_get_port (core, index);
403
404     if (!port)
405     {
406         port = g_omx_port_new (core);
407         g_ptr_array_insert (core->ports, index, port);
408     }
409
410     g_omx_port_setup (port, omx_port);
411
412     return port;
413 }
414
415 static inline GOmxPort *
416 g_omx_core_get_port (GOmxCore *core,
417                      guint index)
418 {
419     if (G_LIKELY (index < core->ports->len))
420     {
421         return g_ptr_array_index (core->ports, index);
422     }
423
424     return NULL;
425 }
426
427 void
428 g_omx_core_set_done (GOmxCore *core)
429 {
430     g_sem_up (core->done_sem);
431 }
432
433 void
434 g_omx_core_wait_for_done (GOmxCore *core)
435 {
436     g_sem_down (core->done_sem);
437 }
438
439 void
440 g_omx_core_flush_start (GOmxCore *core)
441 {
442     core_for_each_port (core, g_omx_port_pause);
443 }
444
445 void
446 g_omx_core_flush_stop (GOmxCore *core)
447 {
448     core_for_each_port (core, g_omx_port_flush);
449     core_for_each_port (core, g_omx_port_resume);
450 }
451
452 /*
453  * Port
454  */
455
456 GOmxPort *
457 g_omx_port_new (GOmxCore *core)
458 {
459     GOmxPort *port;
460     port = g_new0 (GOmxPort, 1);
461
462     port->core = core;
463     port->num_buffers = 0;
464     port->buffer_size = 0;
465     port->buffers = NULL;
466
467     port->enabled = TRUE;
468     port->queue = async_queue_new ();
469     port->mutex = g_mutex_new ();
470
471     return port;
472 }
473
474 void
475 g_omx_port_free (GOmxPort *port)
476 {
477     g_mutex_free (port->mutex);
478     async_queue_free (port->queue);
479
480     g_free (port->buffers);
481     g_free (port);
482 }
483
484 void
485 g_omx_port_setup (GOmxPort *port,
486                   OMX_PARAM_PORTDEFINITIONTYPE *omx_port)
487 {
488     GOmxPortType type = -1;
489
490     switch (omx_port->eDir)
491     {
492         case OMX_DirInput:
493             type = GOMX_PORT_INPUT;
494             break;
495         case OMX_DirOutput:
496             type = GOMX_PORT_OUTPUT;
497             break;
498         default:
499             break;
500     }
501
502     port->type = type;
503     /** @todo should it be nBufferCountMin? */
504     port->num_buffers = omx_port->nBufferCountActual;
505     port->buffer_size = omx_port->nBufferSize;
506     port->port_index = omx_port->nPortIndex;
507
508     g_free (port->buffers);
509     port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers);
510 }
511
512 static void
513 port_allocate_buffers (GOmxPort *port)
514 {
515     guint i;
516
517     for (i = 0; i < port->num_buffers; i++)
518     {
519         guint size;
520
521         size = port->buffer_size;
522
523         if (port->omx_allocate)
524         {
525             OMX_AllocateBuffer (port->core->omx_handle,
526                                 &port->buffers[i],
527                                 port->port_index,
528                                 NULL,
529                                 size);
530         }
531         else
532         {
533             gpointer buffer_data;
534             buffer_data = g_malloc (size);
535             OMX_UseBuffer (port->core->omx_handle,
536                            &port->buffers[i],
537                            port->port_index,
538                            NULL,
539                            size,
540                            buffer_data);
541         }
542     }
543 }
544
545 static void
546 port_free_buffers (GOmxPort *port)
547 {
548     guint i;
549
550     for (i = 0; i < port->num_buffers; i++)
551     {
552         OMX_BUFFERHEADERTYPE *omx_buffer;
553
554         omx_buffer = port->buffers[i];
555
556         if (omx_buffer)
557         {
558 #if 0
559             /** @todo how shall we free that buffer? */
560             if (!port->omx_allocate)
561             {
562                 g_free (omx_buffer->pBuffer);
563                 omx_buffer->pBuffer = NULL;
564             }
565 #endif
566
567             OMX_FreeBuffer (port->core->omx_handle, port->port_index, omx_buffer);
568             port->buffers[i] = NULL;
569         }
570     }
571 }
572
573 static void
574 port_start_buffers (GOmxPort *port)
575 {
576     guint i;
577
578     for (i = 0; i < port->num_buffers; i++)
579     {
580         OMX_BUFFERHEADERTYPE *omx_buffer;
581
582         omx_buffer = port->buffers[i];
583
584         /* If it's an input port we will need to fill the buffer, so put it in
585          * the queue, otherwise send to omx for processing (fill it up). */
586         if (port->type == GOMX_PORT_INPUT)
587             got_buffer (port->core, port, omx_buffer);
588         else
589             g_omx_port_release_buffer (port, omx_buffer);
590     }
591 }
592
593 void
594 g_omx_port_push_buffer (GOmxPort *port,
595                         OMX_BUFFERHEADERTYPE *omx_buffer)
596 {
597     async_queue_push (port->queue, omx_buffer);
598 }
599
600 OMX_BUFFERHEADERTYPE *
601 g_omx_port_request_buffer (GOmxPort *port)
602 {
603     return async_queue_pop (port->queue);
604 }
605
606 void
607 g_omx_port_release_buffer (GOmxPort *port,
608                            OMX_BUFFERHEADERTYPE *omx_buffer)
609 {
610     switch (port->type)
611     {
612         case GOMX_PORT_INPUT:
613             OMX_EmptyThisBuffer (port->core->omx_handle, omx_buffer);
614             break;
615         case GOMX_PORT_OUTPUT:
616             OMX_FillThisBuffer (port->core->omx_handle, omx_buffer);
617             break;
618         default:
619             break;
620     }
621 }
622
623 void
624 g_omx_port_resume (GOmxPort *port)
625 {
626     async_queue_enable (port->queue);
627 }
628
629 void
630 g_omx_port_pause (GOmxPort *port)
631 {
632     async_queue_disable (port->queue);
633 }
634
635 void
636 g_omx_port_flush (GOmxPort *port)
637 {
638     if (port->type == GOMX_PORT_OUTPUT)
639     {
640         OMX_BUFFERHEADERTYPE *omx_buffer;
641         while ((omx_buffer = async_queue_pop_forced (port->queue)))
642         {
643             omx_buffer->nFilledLen = 0;
644             g_omx_port_release_buffer (port, omx_buffer);
645         }
646     }
647     else
648     {
649         OMX_SendCommand (port->core->omx_handle, OMX_CommandFlush, port->port_index, NULL);
650         g_sem_down (port->core->flush_sem);
651     }
652 }
653
654 void
655 g_omx_port_enable (GOmxPort *port)
656 {
657     GOmxCore *core;
658
659     core = port->core;
660
661     OMX_SendCommand (core->omx_handle, OMX_CommandPortEnable, port->port_index, NULL);
662     port_allocate_buffers (port);
663     if (core->omx_state != OMX_StateLoaded)
664         port_start_buffers (port);
665     g_omx_port_resume (port);
666
667     g_sem_down (core->port_sem);
668 }
669
670 void
671 g_omx_port_disable (GOmxPort *port)
672 {
673     GOmxCore *core;
674
675     core = port->core;
676
677     OMX_SendCommand (core->omx_handle, OMX_CommandPortDisable, port->port_index, NULL);
678     g_omx_port_pause (port);
679     g_omx_port_flush (port);
680     port_free_buffers (port);
681
682     g_sem_down (core->port_sem);
683 }
684
685 void
686 g_omx_port_finish (GOmxPort *port)
687 {
688     port->enabled = FALSE;
689     async_queue_disable (port->queue);
690 }
691
692 /*
693  * Helper functions.
694  */
695
696 static inline void
697 change_state (GOmxCore *core,
698               OMX_STATETYPE state)
699 {
700     GST_DEBUG_OBJECT (core->object, "state=%d", state);
701     OMX_SendCommand (core->omx_handle, OMX_CommandStateSet, state, NULL);
702 }
703
704 static inline void
705 complete_change_state (GOmxCore *core,
706                        OMX_STATETYPE state)
707 {
708     g_mutex_lock (core->omx_state_mutex);
709
710     core->omx_state = state;
711     g_cond_signal (core->omx_state_condition);
712     GST_DEBUG_OBJECT (core->object, "state=%d", state);
713
714     g_mutex_unlock (core->omx_state_mutex);
715 }
716
717 static inline void
718 wait_for_state (GOmxCore *core,
719                 OMX_STATETYPE state)
720 {
721     GTimeVal tv;
722     gboolean signaled;
723
724     g_mutex_lock (core->omx_state_mutex);
725
726     if (core->omx_error != OMX_ErrorNone)
727         goto leave;
728
729     g_get_current_time (&tv);
730     g_time_val_add (&tv, 1000000);
731
732     /* try once */
733     if (core->omx_state != state)
734     {
735         signaled = g_cond_timed_wait (core->omx_state_condition, core->omx_state_mutex, &tv);
736
737         if (!signaled)
738         {
739             GST_ERROR_OBJECT (core->object, "timed out");
740         }
741     }
742
743     if (core->omx_error != OMX_ErrorNone)
744         goto leave;
745
746     if (core->omx_state != state)
747     {
748         GST_ERROR_OBJECT (core->object, "wrong state received: state=%d, expected=%d",
749                           core->omx_state, state);
750     }
751
752 leave:
753     g_mutex_unlock (core->omx_state_mutex);
754 }
755
756 /*
757  * Callbacks
758  */
759
760 static inline void
761 in_port_cb (GOmxPort *port,
762             OMX_BUFFERHEADERTYPE *omx_buffer)
763 {
764     /** @todo remove this */
765
766     if (!port->enabled)
767         return;
768 }
769
770 static inline void
771 out_port_cb (GOmxPort *port,
772              OMX_BUFFERHEADERTYPE *omx_buffer)
773 {
774     /** @todo remove this */
775
776     if (!port->enabled)
777         return;
778
779 #if 0
780     if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS)
781     {
782         g_omx_port_set_done (port);
783         return;
784     }
785 #endif
786 }
787
788 static inline void
789 got_buffer (GOmxCore *core,
790             GOmxPort *port,
791             OMX_BUFFERHEADERTYPE *omx_buffer)
792 {
793     if (G_UNLIKELY (!omx_buffer))
794     {
795         return;
796     }
797
798     if (G_LIKELY (port))
799     {
800         g_omx_port_push_buffer (port, omx_buffer);
801
802         switch (port->type)
803         {
804             case GOMX_PORT_INPUT:
805                 in_port_cb (port, omx_buffer);
806                 break;
807             case GOMX_PORT_OUTPUT:
808                 out_port_cb (port, omx_buffer);
809                 break;
810             default:
811                 break;
812         }
813     }
814 }
815
816 /*
817  * OpenMAX IL callbacks.
818  */
819
820 static OMX_ERRORTYPE
821 EventHandler (OMX_HANDLETYPE omx_handle,
822               OMX_PTR app_data,
823               OMX_EVENTTYPE event,
824               OMX_U32 data_1,
825               OMX_U32 data_2,
826               OMX_PTR event_data)
827 {
828     GOmxCore *core;
829
830     core = (GOmxCore *) app_data;
831
832     switch (event)
833     {
834         case OMX_EventCmdComplete:
835             {
836                 OMX_COMMANDTYPE cmd;
837
838                 cmd = (OMX_COMMANDTYPE) data_1;
839
840                 switch (cmd)
841                 {
842                     case OMX_CommandStateSet:
843                         complete_change_state (core, data_2);
844                         break;
845                     case OMX_CommandFlush:
846                         g_sem_up (core->flush_sem);
847                         break;
848                     case OMX_CommandPortDisable:
849                     case OMX_CommandPortEnable:
850                         g_sem_up (core->port_sem);
851                     default:
852                         break;
853                 }
854                 break;
855             }
856         case OMX_EventBufferFlag:
857             {
858                 if (data_2 & OMX_BUFFERFLAG_EOS)
859                 {
860                     g_omx_core_set_done (core);
861                 }
862                 break;
863             }
864         case OMX_EventPortSettingsChanged:
865             {
866                 /** @todo only on the relevant port. */
867                 if (core->settings_changed_cb)
868                 {
869                     core->settings_changed_cb (core);
870                 }
871                 break;
872             }
873         case OMX_EventError:
874             {
875                 core->omx_error = data_1;
876                 GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
877                                   omx_error_to_str (data_1), data_1);
878                 /* component might leave us waiting for buffers, unblock */
879                 g_omx_core_flush_start (core);
880                 /* unlock wait_for_state */
881                 g_mutex_lock (core->omx_state_mutex);
882                 g_cond_signal (core->omx_state_condition);
883                 g_mutex_unlock (core->omx_state_mutex);
884                 break;
885             }
886         default:
887             break;
888     }
889
890     return OMX_ErrorNone;
891 }
892
893 static OMX_ERRORTYPE
894 EmptyBufferDone (OMX_HANDLETYPE omx_handle,
895                  OMX_PTR app_data,
896                  OMX_BUFFERHEADERTYPE *omx_buffer)
897 {
898     GOmxCore *core;
899     GOmxPort *port;
900
901     core = (GOmxCore*) app_data;
902     port = g_omx_core_get_port (core, omx_buffer->nInputPortIndex);
903
904     GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer=%p", omx_buffer);
905     got_buffer (core, port, omx_buffer);
906
907     return OMX_ErrorNone;
908 }
909
910 static OMX_ERRORTYPE
911 FillBufferDone (OMX_HANDLETYPE omx_handle,
912                 OMX_PTR app_data,
913                 OMX_BUFFERHEADERTYPE *omx_buffer)
914 {
915     GOmxCore *core;
916     GOmxPort *port;
917
918     core = (GOmxCore *) app_data;
919     port = g_omx_core_get_port (core, omx_buffer->nOutputPortIndex);
920
921     GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer=%p", omx_buffer);
922     got_buffer (core, port, omx_buffer);
923
924     return OMX_ErrorNone;
925 }
926
927 static inline const char *
928 omx_error_to_str (OMX_ERRORTYPE omx_error)
929 {
930     switch (omx_error)
931     {
932         case OMX_ErrorNone:
933             return "None";
934
935         case OMX_ErrorInsufficientResources:
936             return "There were insufficient resources to perform the requested operation";
937
938         case OMX_ErrorUndefined:
939             return "The cause of the error could not be determined";
940
941         case OMX_ErrorInvalidComponentName:
942             return "The component name string was not valid";
943
944         case OMX_ErrorComponentNotFound:
945             return "No component with the specified name string was found";
946
947         case OMX_ErrorInvalidComponent:
948             return "The component specified did not have an entry point";
949
950         case OMX_ErrorBadParameter:
951             return "One or more parameters were not valid";
952
953         case OMX_ErrorNotImplemented:
954             return "The requested function is not implemented";
955
956         case OMX_ErrorUnderflow:
957             return "The buffer was emptied before the next buffer was ready";
958
959         case OMX_ErrorOverflow:
960             return "The buffer was not available when it was needed";
961
962         case OMX_ErrorHardware:
963             return "The hardware failed to respond as expected";
964
965         case OMX_ErrorInvalidState:
966             return "The component is in invalid state";
967
968         case OMX_ErrorStreamCorrupt:
969             return "Stream is found to be corrupt";
970
971         case OMX_ErrorPortsNotCompatible:
972             return "Ports being connected are not compatible";
973
974         case OMX_ErrorResourcesLost:
975             return "Resources allocated to an idle component have been lost";
976
977         case OMX_ErrorNoMore:
978             return "No more indices can be enumerated";
979
980         case OMX_ErrorVersionMismatch:
981             return "The component detected a version mismatch";
982
983         case OMX_ErrorNotReady:
984             return "The component is not ready to return data at this time";
985
986         case OMX_ErrorTimeout:
987             return "There was a timeout that occurred";
988
989         case OMX_ErrorSameState:
990             return "This error occurs when trying to transition into the state you are already in";
991
992         case OMX_ErrorResourcesPreempted:
993             return "Resources allocated to an executing or paused component have been preempted";
994
995         case OMX_ErrorPortUnresponsiveDuringAllocation:
996             return "Waited an unusually long time for the supplier to allocate buffers";
997
998         case OMX_ErrorPortUnresponsiveDuringDeallocation:
999             return "Waited an unusually long time for the supplier to de-allocate buffers";
1000
1001         case OMX_ErrorPortUnresponsiveDuringStop:
1002             return "Waited an unusually long time for the non-supplier to return a buffer during stop";
1003
1004         case OMX_ErrorIncorrectStateTransition:
1005             return "Attempting a state transition that is not allowed";
1006
1007         case OMX_ErrorIncorrectStateOperation:
1008             return "Attempting a command that is not allowed during the present state";
1009
1010         case OMX_ErrorUnsupportedSetting:
1011             return "The values encapsulated in the parameter or config structure are not supported";
1012
1013         case OMX_ErrorUnsupportedIndex:
1014             return "The parameter or config indicated by the given index is not supported";
1015
1016         case OMX_ErrorBadPortIndex:
1017             return "The port index supplied is incorrect";
1018
1019         case OMX_ErrorPortUnpopulated:
1020             return "The port has lost one or more of its buffers and it thus unpopulated";
1021
1022         case OMX_ErrorComponentSuspended:
1023             return "Component suspended due to temporary loss of resources";
1024
1025         case OMX_ErrorDynamicResourcesUnavailable:
1026             return "Component suspended due to an inability to acquire dynamic resources";
1027
1028         case OMX_ErrorMbErrorsInFrame:
1029             return "Frame generated macroblock error";
1030
1031         case OMX_ErrorFormatNotDetected:
1032             return "Cannot parse or determine the format of an input stream";
1033
1034         case OMX_ErrorContentPipeOpenFailed:
1035             return "The content open operation failed";
1036
1037         case OMX_ErrorContentPipeCreationFailed:
1038             return "The content creation operation failed";
1039
1040         case OMX_ErrorSeperateTablesUsed:
1041             return "Separate table information is being used";
1042
1043         case OMX_ErrorTunnelingUnsupported:
1044             return "Tunneling is unsupported by the component";
1045
1046         default:
1047             return "Unknown error";
1048     }
1049 }