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 void PostCommand (gpointer data);
77 static OMX_CALLBACKTYPE callbacks =
78 { EventHandler, EmptyBufferDone, FillBufferDone };
80 /* protect implementations hash_table */
81 static GMutex *imp_mutex;
82 static GHashTable *implementations;
83 static gboolean initialized;
85 /* Modification: calculate plane */
86 /* this is for S.LSI */
87 static int calc_plane(int width, int height) /* for h.264 */
91 mbX = ALIGN(width, S5P_FIMV_NV12MT_HALIGN);
92 mbY = ALIGN(height, S5P_FIMV_NV12MT_VALIGN);
94 return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN);
98 static int calc_yplane(int width, int height)
102 mbX = ALIGN(width + 24, S5P_FIMV_NV12MT_HALIGN);
103 mbY = ALIGN(height + 16, S5P_FIMV_NV12MT_VALIGN);
105 return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN);
108 static int calc_uvplane(int width, int height)
112 mbX = ALIGN(width + 16, S5P_FIMV_NV12MT_HALIGN);
113 mbY = ALIGN(height + 4, S5P_FIMV_NV12MT_VALIGN);
115 return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN);
118 static void calc_align_size(GOmxPort * port, int width, int height, guint* y_size, guint* uv_size)
120 if (port->core->compression_format == OMX_VIDEO_CodingAVC) {
121 *y_size = calc_plane(width, height);
122 *uv_size = calc_plane(width, height /2);
124 *y_size = calc_yplane(width, height);
125 *uv_size = calc_uvplane(width, height /2);
134 g_ptr_array_clear (GPtrArray * array)
137 for (index = 0; index < array->len; index++)
138 array->pdata[index] = NULL;
142 g_ptr_array_insert (GPtrArray * array, guint index, gpointer data)
144 if (index + 1 > array->len) {
145 g_ptr_array_set_size (array, index + 1);
148 array->pdata[index] = data;
151 typedef void (*GOmxPortFunc) (GOmxPort * port);
154 core_for_each_port (GOmxCore * core, GOmxPortFunc func)
158 for (index = 0; index < core->ports->len; index++) {
161 port = get_port (core, index);
172 static GOmxImp *imp_new (const gchar * name);
173 static void imp_free (GOmxImp * imp);
176 imp_new (const gchar * name)
180 imp = g_new0 (GOmxImp, 1);
182 /* Load the OpenMAX IL symbols */
186 GST_DEBUG ("loading: %s", name);
188 imp->dl_handle = handle = dlopen (name, RTLD_LAZY);
190 GST_DEBUG ("dlopen(%s) -> %p", name, handle);
193 g_warning ("%s\n", dlerror ());
198 imp->mutex = g_mutex_new ();
199 imp->sym_table.init = dlsym (handle, "OMX_Init");
200 imp->sym_table.deinit = dlsym (handle, "OMX_Deinit");
201 imp->sym_table.get_handle = dlsym (handle, "OMX_GetHandle");
202 imp->sym_table.free_handle = dlsym (handle, "OMX_FreeHandle");
209 imp_free (GOmxImp * imp)
211 if (imp->dl_handle) {
212 dlclose (imp->dl_handle);
214 g_mutex_free (imp->mutex);
218 static inline GOmxImp *
219 request_imp (const gchar * name)
223 g_mutex_lock (imp_mutex);
224 imp = g_hash_table_lookup (implementations, name);
226 imp = imp_new (name);
228 g_hash_table_insert (implementations, g_strdup (name), imp);
230 g_mutex_unlock (imp_mutex);
235 g_mutex_lock (imp->mutex);
236 if (imp->client_count == 0) {
237 OMX_ERRORTYPE omx_error;
238 omx_error = imp->sym_table.init ();
240 g_mutex_unlock (imp->mutex);
245 g_mutex_unlock (imp->mutex);
251 release_imp (GOmxImp * imp)
253 g_mutex_lock (imp->mutex);
255 if (imp->client_count == 0) {
256 imp->sym_table.deinit ();
258 g_mutex_unlock (imp->mutex);
265 /* safe as plugin_init is safe */
266 imp_mutex = g_mutex_new ();
267 implementations = g_hash_table_new_full (g_str_hash,
268 g_str_equal, g_free, (GDestroyNotify) imp_free);
277 g_hash_table_destroy (implementations);
278 g_mutex_free (imp_mutex);
288 g_omx_core_new (void *object)
292 core = g_new0 (GOmxCore, 1);
294 core->object = object;
295 core->ports = g_ptr_array_new ();
297 core->omx_state_condition = g_cond_new ();
298 core->omx_state_mutex = g_mutex_new ();
300 core->done_sem = g_sem_new ();
301 core->flush_sem = g_sem_new ();
302 core->port_sem = g_sem_new ();
304 core->cmd.cmd_queue = async_queue_new ();
305 core->cmd.cmd_queue_enabled = TRUE;
307 g_static_rec_mutex_init (&core->cmd.cmd_mutex);
309 GST_WARNING ("gst_task_create for PostCommand");
310 core->cmd.cmd_task = gst_task_create (PostCommand, core);
311 gst_task_set_lock (core->cmd.cmd_task, &core->cmd.cmd_mutex);
313 core->omx_state = OMX_StateInvalid;
319 g_omx_core_free (GOmxCore * core)
321 GST_WARNING ("g_omx_core_free enter");
324 g_sem_free (core->port_sem);
325 g_sem_free (core->flush_sem);
326 g_sem_free (core->done_sem);
328 g_mutex_free (core->omx_state_mutex);
329 g_cond_free (core->omx_state_condition);
331 g_mutex_free (core->drc_lock);
332 g_cond_free (core->drc_cond);
334 gst_task_stop (core->cmd.cmd_task);
335 gst_task_join(core->cmd.cmd_task);
336 gst_object_unref(core->cmd.cmd_task);
338 g_ptr_array_free (core->ports, TRUE);
342 GST_WARNING ("g_omx_core_free leave");
346 g_omx_core_init (GOmxCore * core)
348 GST_DEBUG_OBJECT (core->object, "loading: %s %s (%s)",
349 core->component_name,
350 core->component_role ? core->component_role : "", core->library_name);
352 core->imp = request_imp (core->library_name);
357 core->omx_error = core->imp->sym_table.get_handle (&core->omx_handle,
358 (char *) core->component_name, core, &callbacks);
360 GST_DEBUG_OBJECT (core->object, "OMX_GetHandle(&%p) -> %d",
361 core->omx_handle, core->omx_error);
363 if (!core->omx_error) {
364 core->omx_state = OMX_StateLoaded;
366 if (core->component_role) {
367 OMX_PARAM_COMPONENTROLETYPE param;
369 GST_DEBUG_OBJECT (core->object, "setting component role: %s",
370 core->component_role);
372 G_OMX_INIT_PARAM (param);
374 strncpy ((char *) param.cRole, core->component_role,
375 OMX_MAX_STRINGNAME_SIZE - 1);
377 OMX_SetParameter (core->omx_handle, OMX_IndexParamStandardComponentRole,
381 /* MODIFICATION: Add_component_vendor */
382 if (strncmp(core->component_name+4, "SEC", 3) == 0)
384 core->component_vendor = GOMX_VENDOR_SLSI_SEC;
386 else if (strncmp(core->component_name+4, "Exynos", 6) == 0)
388 core->component_vendor = GOMX_VENDOR_SLSI_EXYNOS;
392 core->component_vendor = GOMX_VENDOR_DEFAULT;
398 core_deinit (GOmxCore * core)
403 if (core->omx_state == OMX_StateLoaded || core->omx_state == OMX_StateInvalid) {
404 if (core->omx_handle) {
405 core->omx_error = core->imp->sym_table.free_handle (core->omx_handle);
406 GST_DEBUG_OBJECT (core->object, "OMX_FreeHandle(%p) -> %d",
407 core->omx_handle, core->omx_error);
410 GST_WARNING_OBJECT (core->object, "Incorrect state: %s",
411 omx_state_to_str (core->omx_state));
414 g_free (core->library_name);
415 g_free (core->component_name);
416 g_free (core->component_role);
417 core->library_name = NULL;
418 core->component_name = NULL;
419 core->component_role = NULL;
421 release_imp (core->imp);
426 g_omx_core_prepare (GOmxCore * core)
428 change_state (core, OMX_StateIdle);
430 /* Allocate buffers. */
431 core_for_each_port (core, port_allocate_buffers);
433 wait_for_state (core, OMX_StateIdle);
437 g_omx_core_start (GOmxCore * core)
439 change_state (core, OMX_StateExecuting);
440 wait_for_state (core, OMX_StateExecuting);
442 if (gst_task_start (core->cmd.cmd_task) == FALSE) {
443 GST_ERROR ("Could not start PostCommand task");
446 if (core->omx_state == OMX_StateExecuting)
447 core_for_each_port (core, port_start_buffers);
451 g_omx_core_stop (GOmxCore * core)
453 if (core->omx_state == OMX_StateExecuting ||
454 core->omx_state == OMX_StatePause) {
455 change_state (core, OMX_StateIdle);
456 wait_for_state (core, OMX_StateIdle);
461 g_omx_core_pause (GOmxCore * core)
463 change_state (core, OMX_StatePause);
464 wait_for_state (core, OMX_StatePause);
468 g_omx_core_unload (GOmxCore * core)
470 if (core->omx_state == OMX_StateIdle ||
471 core->omx_state == OMX_StateWaitForResources ||
472 core->omx_state == OMX_StateInvalid) {
473 if (core->omx_state != OMX_StateInvalid)
474 change_state (core, OMX_StateLoaded);
476 core_for_each_port (core, port_free_buffers);
478 if (core->omx_state != OMX_StateInvalid)
479 wait_for_state (core, OMX_StateLoaded);
484 g_omx_port_clear (GOmxCore * core)
486 core_for_each_port (core, g_omx_port_free);
487 g_ptr_array_clear (core->ports);
489 GST_WARNING_OBJECT (core->object, "free command queue");
490 async_queue_free (core->cmd.cmd_queue);
493 static inline GOmxPort *
494 get_port (GOmxCore * core, guint index)
496 if (G_LIKELY (index < core->ports->len)) {
497 return g_ptr_array_index (core->ports, index);
504 g_omx_core_new_port (GOmxCore * core, guint index)
506 GOmxPort *port = get_port (core, index);
509 GST_WARNING_OBJECT (core->object, "port %d already exists", index);
513 port = g_omx_port_new (core, index);
514 g_ptr_array_insert (core->ports, index, port);
520 g_omx_core_set_done (GOmxCore * core)
522 g_sem_up (core->done_sem);
526 g_omx_core_wait_for_done (GOmxCore * core)
528 g_sem_down (core->done_sem);
532 g_omx_core_flush_start (GOmxCore * core)
534 core_for_each_port (core, g_omx_port_pause);
538 g_omx_core_flush_stop (GOmxCore * core)
540 core_for_each_port (core, g_omx_port_flush);
541 core_for_each_port (core, g_omx_port_resume);
549 gst_omx_drm_init(GOmxPort * port)
556 char *driverName = NULL;
557 char *deviceName = NULL;
558 struct drm_auth auth_arg = {0};
562 GST_INFO_OBJECT (port->core->object, "gst_omx_drm_init enter");
564 dpy = XOpenDisplay(0);
567 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
568 GST_ERROR_OBJECT (port->core->object, "failed to DRI2QueryExtension()");
572 if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
573 GST_ERROR_OBJECT (port->core->object, "failed to DRI2QueryVersion");
577 if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
578 GST_ERROR_OBJECT(port->core->object,"failed to DRI2Connect");
582 /* get the drm_fd though opening the deviceName */
583 port->drm_fd = open(deviceName, O_RDWR);
584 if (port->drm_fd < 0) {
585 GST_ERROR_OBJECT(port->core->object,"cannot open drm device (%s)", deviceName);
588 GST_INFO("Open drm device : %s, fd(%d)", deviceName, port->drm_fd);
590 /* get magic from drm to authentication */
591 if (ioctl(port->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
592 GST_ERROR_OBJECT(port->core->object,"cannot get drm auth magic");
598 if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
599 GST_ERROR_OBJECT(port->core->object,"cannot get drm authentication from X");
605 /* drm slp buffer manager init */
606 port->bufmgr = tbm_bufmgr_init (port->drm_fd);
609 GST_ERROR_OBJECT (port->core->object, "fail to init buffer manager");
610 close (port->drm_fd);
619 GST_INFO_OBJECT(port->core->object, "gst_omx_drm_init leave");
636 gst_omx_drm_close(GOmxPort * port)
639 GST_LOG_OBJECT (port->core->object, "drm_slp_bufmgr_destroy");
640 tbm_bufmgr_deinit (port->bufmgr);
644 if (port->drm_fd != -1) {
645 GST_LOG_OBJECT (port->core->object, "close drm fd");
646 close (port->drm_fd);
652 gst_omx_drm_alloc_buffer(GOmxPort * port, guint width, guint height, guint buffer_index)
655 guint y_size = 0, uv_size = 0;
656 tbm_bo_handle handle_vaddr;
657 tbm_bo_handle handle_fd;
660 GST_ERROR("drm_fd is NULL");
664 if (port->core->component_vendor == GOMX_VENDOR_SLSI_EXYNOS) {
665 calc_align_size(port, width, height, &y_size, &uv_size);
670 port->bo[buffer_index].bo_y = tbm_bo_alloc (port->bufmgr, y_size, flag);
671 if (!port->bo[buffer_index].bo_y) {
672 GST_ERROR("failed to tbm_bo_alloc (y plane) size = %d", y_size);
676 GST_INFO_OBJECT (port->core->object, "buf[%d] Y plane - bo: %p", buffer_index, port->bo[buffer_index].bo_y);
678 /* for sending BO to XvImgSink(QC)*/
679 port->scmn_out[buffer_index].bo[0] = port->bo[buffer_index].bo_y;
681 handle_fd = tbm_bo_get_handle (port->bo[buffer_index].bo_y, TBM_DEVICE_MM);
682 port->scmn_out[buffer_index].fd[0] = handle_fd.u32;
684 GST_DEBUG_OBJECT (port->core->object, " buf[%d] Y plane - fd[0]: %d", buffer_index, port->scmn_out[buffer_index].fd[0]);
685 handle_vaddr= tbm_bo_get_handle (port->bo[buffer_index].bo_y, TBM_DEVICE_CPU);
687 if (port->buffer_type==GOMX_BUFFER_GEM_VDEC_OUTPUT)
688 port->scmn_out[buffer_index].a[0] = handle_vaddr.ptr;
690 GST_DEBUG_OBJECT (port->core->object, " buf[%d] Y plane - a[0]: %p", buffer_index, port->scmn_out[buffer_index].a[0]);
692 /* alloc CbCr plane*/
693 port->bo[buffer_index].bo_uv = tbm_bo_alloc (port->bufmgr, uv_size, flag);
695 if (!port->bo[buffer_index].bo_uv) {
696 GST_ERROR("failed to tbm_bo_alloc (cbcr plane), size = %d", uv_size);
700 GST_INFO_OBJECT (port->core->object, "buf[%d] CbCr plane - bo: %p", buffer_index, port->bo[buffer_index].bo_uv);
702 /* for sending BO to XvImgSink(S.LSI)*/
703 port->scmn_out[buffer_index].bo[1] = port->bo[buffer_index].bo_uv;
705 handle_fd = tbm_bo_get_handle (port->bo[buffer_index].bo_uv, TBM_DEVICE_MM);
706 port->scmn_out[buffer_index].fd[1] = handle_fd.u32;
707 GST_DEBUG_OBJECT (port->core->object, " buf[%d] CbCr plane - fd[1]: %d", buffer_index, port->scmn_out[buffer_index].fd[1]);
709 handle_vaddr= tbm_bo_get_handle (port->bo[buffer_index].bo_uv, TBM_DEVICE_CPU);
710 port->scmn_out[buffer_index].a[1] = handle_vaddr.ptr;
711 GST_DEBUG_OBJECT (port->core->object, " buf[%d] CbCr plane - a[1]: %p\n", buffer_index, port->scmn_out[buffer_index].a[1]);
717 * note: this is not intended to be called directly by elements (which should
718 * instead use g_omx_core_new_port())
721 g_omx_port_new (GOmxCore * core, guint index)
724 port = g_new0 (GOmxPort, 1);
727 port->port_index = index;
728 port->num_buffers = 0;
729 port->buffer_size = 0;
730 port->buffers = NULL;
731 port->shared_buffer = FALSE;
733 port->enabled = TRUE;
734 port->flushing = FALSE;
735 port->queue = async_queue_new ();
736 port->mutex = g_mutex_new ();
740 port->buffer_type = GOMX_BUFFER_DEFAULT;
742 port->output_color_format = OMX_VIDEO_CodingUnused;
748 g_omx_port_free (GOmxPort * port)
750 g_mutex_free (port->mutex);
751 async_queue_free (port->queue);
753 g_free (port->buffers);
754 port->buffers = NULL;
760 g_omx_port_setup (GOmxPort * port)
762 GOmxPortType type = -1;
763 OMX_PARAM_PORTDEFINITIONTYPE param;
765 G_OMX_INIT_PARAM (param);
767 param.nPortIndex = port->port_index;
768 OMX_GetParameter (port->core->omx_handle, OMX_IndexParamPortDefinition,
771 switch (param.eDir) {
773 type = GOMX_PORT_INPUT;
776 type = GOMX_PORT_OUTPUT;
783 /** @todo should it be nBufferCountMin? */
784 port->num_buffers = param.nBufferCountActual;
785 port->buffer_size = param.nBufferSize;
787 GST_DEBUG_OBJECT(port->core->object, "width:%d, height:%d, buffer size:%d", param.format.video.nFrameWidth, param.format.video.nFrameHeight, port->buffer_size);
788 if (port->type == GOMX_PORT_OUTPUT) {
789 if (port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
790 GST_DEBUG_OBJECT (port->core->object, "gst_omx_drm_init");
791 gst_omx_drm_init(port);
795 GST_DEBUG_OBJECT (port->core->object,
796 "type=%d, num_buffers=%d, buffer_size=%ld, port_index=%d",
797 port->type, port->num_buffers, port->buffer_size, port->port_index);
799 g_free (port->buffers);
800 port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers);
804 port_allocate_buffers (GOmxPort * port)
808 OMX_PARAM_PORTDEFINITIONTYPE param;
811 G_OMX_INIT_PARAM (param);
812 param.nPortIndex = port->port_index;
813 OMX_GetParameter (port->core->omx_handle, OMX_IndexParamPortDefinition, ¶m);
815 width = param.format.video.nFrameWidth;
816 height = param.format.video.nFrameHeight;
818 port->num_buffers = param.nBufferCountActual;
819 port->buffer_size = param.nBufferSize;
820 size = port->buffer_size;
822 GST_DEBUG_OBJECT (port->core->object,"port index: %d, num_buffer:%d, buffer_size :%d",
823 port->port_index, port->num_buffers, port->buffer_size);
825 if(port->buffers != NULL) {
826 g_free (port->buffers);
827 port->buffers = NULL;
829 GST_DEBUG_OBJECT (port->core->object,"make new OMX_BUFFERHEADERTYPE.");
830 port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers);
832 /* MODIFICATION: allocate buffer for SLSI Exynos components*/
833 if (port->core->component_vendor == GOMX_VENDOR_SLSI_EXYNOS) {
835 for (buf_idx = 0; buf_idx < port->num_buffers; buf_idx++) {
836 if (port->omx_allocate) {
837 /* OMX_AllocateBuffer with normal buffer */
838 GST_DEBUG_OBJECT (port->core->object, "%d: OMX_AllocateBuffer(), size=%" G_GSIZE_FORMAT, buf_idx, size);
840 OMX_AllocateBuffer (port->core->omx_handle, &port->buffers[buf_idx], port->port_index, NULL, size);
842 /* OMX_UseBuffer with gem or TZ*/
843 if (port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
844 gpointer buffer_data = NULL;
845 gpointer pAppPrivate = NULL;
847 if(!gst_omx_drm_alloc_buffer(port, width, height, buf_idx))
848 GST_ERROR_OBJECT (port->core->object,"gst_omx_drm_alloc_buffer failed");
850 buffer_data = &(port->scmn_out[buf_idx]);
851 size = sizeof(SCMN_IMGB);
853 GST_DEBUG_OBJECT (port->core->object, "%d: OMX_UseBuffer(), (GEM) size=%" G_GSIZE_FORMAT" (%p)",
854 buf_idx, size, buffer_data);
856 OMX_UseBuffer (port->core->omx_handle, &port->buffers[buf_idx], port->port_index, pAppPrivate, size, buffer_data);
858 /* OMX_UseBuffer with normal buffer */
859 gpointer buffer_data;
860 buffer_data = g_malloc (size);
861 GST_DEBUG_OBJECT (port->core->object, "%d: OMX_UseBuffer(), size=%" G_GSIZE_FORMAT" (%p)", buf_idx, size, buffer_data);
862 OMX_UseBuffer (port->core->omx_handle, &port->buffers[buf_idx], port->port_index, NULL, size, buffer_data);
864 if (port->type == GOMX_PORT_INPUT && port->shared_buffer == TRUE) {
865 port->initial_pbuffer[buf_idx] = buffer_data;
866 GST_DEBUG_OBJECT (port->core->object, "alloc initial pbuffer. (%d): p= %p", buf_idx, port->initial_pbuffer[buf_idx]);
874 /* allocate buffer for other components */
875 for (buf_idx = 0; buf_idx < port->num_buffers; buf_idx++) {
876 if (port->omx_allocate) {
877 GST_DEBUG_OBJECT (port->core->object,
878 "%d: OMX_AllocateBuffer(), size=%" G_GSIZE_FORMAT, buf_idx, size);
879 OMX_AllocateBuffer (port->core->omx_handle, &port->buffers[buf_idx],
880 port->port_index, NULL, size);
882 gpointer buffer_data;
883 buffer_data = g_malloc (size);
884 GST_DEBUG_OBJECT (port->core->object,
885 "%d: OMX_UseBuffer(), size=%" G_GSIZE_FORMAT" (%p)", buf_idx, size, buffer_data);
886 OMX_UseBuffer (port->core->omx_handle, &port->buffers[buf_idx],
887 port->port_index, NULL, size, buffer_data);
889 if (port->type == GOMX_PORT_INPUT && port->shared_buffer == TRUE) {
890 port->initial_pbuffer[buf_idx] = buffer_data;
891 GST_DEBUG_OBJECT (port->core->object,
892 " alloc initial pbuffer. (%d): p= %p", buf_idx, port->initial_pbuffer[buf_idx]);
900 port_free_buffers (GOmxPort * port)
904 if (port->type == GOMX_PORT_INPUT) {
905 GST_WARNING_OBJECT(port->core->object, "Input port free buffers.port->num_buffers = %d", port->num_buffers);
907 GST_WARNING_OBJECT(port->core->object, "Output port free buffers. port->num_buffers = %d", port->num_buffers);
910 for (i = 0; i < port->num_buffers; i++) {
911 OMX_BUFFERHEADERTYPE *omx_buffer;
912 omx_buffer = port->buffers[i];
914 if (port->core->component_vendor == GOMX_VENDOR_SLSI_EXYNOS) {
915 if(port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
916 GST_WARNING_OBJECT(port->core->object, "gem buffer free. port %d: bo[%d] Y: %p, UV: %p",port->type, i, port->bo[i].bo_y, port->bo[i].bo_uv);
917 tbm_bo_unref(port->bo[i].bo_y);
918 port->bo[i].bo_y = NULL;
919 tbm_bo_unref(port->bo[i].bo_uv);
920 port->bo[i].bo_uv = NULL;
923 /* this is for input buffer share case. we need to free initial buffers (decoder input) */
924 if (port->shared_buffer && port->type == GOMX_PORT_INPUT && port->initial_pbuffer[i] != NULL) {
925 GST_DEBUG_OBJECT(port->core->object, " %d: g_free shared input initial buffer (pBuffer) %p", i, port->initial_pbuffer[i]);
926 g_free (port->initial_pbuffer[i]);
927 port->initial_pbuffer[i] = NULL;
930 /* other vendor case */
933 if (port->shared_buffer) {
934 /* Modification: free pAppPrivate when input/output buffer is shared */
935 if (port->type == GOMX_PORT_INPUT && port->initial_pbuffer[i] != NULL) {
936 GST_DEBUG_OBJECT(port->core->object,
937 " %d: g_free shared input initial buffer (pBuffer) %p", i, port->initial_pbuffer[i]);
938 g_free (port->initial_pbuffer[i]);
939 port->initial_pbuffer[i] = NULL;
942 if (!omx_buffer->pAppPrivate && port->type == GOMX_PORT_OUTPUT && omx_buffer->pBuffer) {
943 GST_DEBUG_OBJECT(port->core->object,
944 " %d: g_free shared buffer (pBuffer) %p", i, omx_buffer->pBuffer);
945 g_free (omx_buffer->pBuffer);
946 omx_buffer->pBuffer = NULL;
949 if (omx_buffer->pAppPrivate) {
950 GST_DEBUG_OBJECT(port->core->object,
951 " %d: unref shared buffer (pAppPrivate) %p", i, omx_buffer->pAppPrivate);
952 gst_buffer_unref(omx_buffer->pAppPrivate);
953 omx_buffer->pAppPrivate = NULL;
956 /* this is not shared buffer */
957 if (!port->omx_allocate) {
958 /* Modification: free pBuffer allocated in plugin when OMX_UseBuffer.
959 * the component shall free only buffer header if it allocated only buffer header.*/
960 GST_DEBUG_OBJECT(port->core->object,
961 " %d: free buffer (pBuffer) %p", i, omx_buffer->pBuffer);
962 if (omx_buffer->pBuffer) {
963 g_free (omx_buffer->pBuffer);
964 omx_buffer->pBuffer = NULL;
969 GST_ERROR_OBJECT(port->core->object, "omx_buffer is NULL. port->buffers[%d]", i);
974 GST_DEBUG_OBJECT(port->core->object, "OMX_FreeBuffer");
975 OMX_FreeBuffer (port->core->omx_handle, port->port_index, omx_buffer);
976 port->buffers[i] = NULL;
981 if(port->buffers != NULL) {
982 g_free (port->buffers); /* need to check */
983 port->buffers = NULL;
986 if (port->type == GOMX_PORT_OUTPUT) {
987 if (port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
988 GST_DEBUG_OBJECT (port->core->object, "gst_omx_drm_close");
989 gst_omx_drm_close(port);
995 port_start_buffers (GOmxPort * port)
999 for (i = 0; i < port->num_buffers; i++) {
1000 OMX_BUFFERHEADERTYPE *omx_buffer;
1002 omx_buffer = port->buffers[i];
1004 /* If it's an input port we will need to fill the buffer, so put it in
1005 * the queue, otherwise send to omx for processing (fill it up). */
1006 if (port->type == GOMX_PORT_INPUT){
1007 got_buffer (port->core, port, omx_buffer);
1009 GST_DEBUG_OBJECT(port->core->object, "index %d FillThisBuffer. omx_buffer= %p",i, omx_buffer);
1010 g_omx_port_release_buffer (port, omx_buffer);
1016 g_omx_port_push_buffer (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
1018 async_queue_push (port->queue, omx_buffer);
1021 OMX_BUFFERHEADERTYPE *
1022 g_omx_port_request_buffer (GOmxPort * port)
1024 return async_queue_pop (port->queue);
1028 g_omx_port_release_buffer (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
1030 switch (port->type) {
1031 case GOMX_PORT_INPUT:
1032 if (port->core->input_log_count < MAX_DEBUG_FRAME_CNT) {
1033 GST_WARNING_OBJECT(port->core->object, "[EmptyThisBuffer] omx_buf=%p pBuf= %p, nFill= %d",
1034 omx_buffer, omx_buffer->pBuffer, omx_buffer->nFilledLen);
1036 GST_LOG_OBJECT(port->core->object, "[EmptyThisBuffer] omx_buf=%p pBuf= %p, nFill= %d",
1037 omx_buffer, omx_buffer->pBuffer, omx_buffer->nFilledLen);
1039 OMX_EmptyThisBuffer (port->core->omx_handle, omx_buffer);
1041 case GOMX_PORT_OUTPUT:
1042 if (port->core->output_log_count < MAX_DEBUG_FRAME_CNT) {
1043 GST_WARNING_OBJECT(port->core->object, "[FillThisBuffer] omx_buf=%p pBuf= %p, nAlloc= %d, nFill= %d",
1044 omx_buffer, omx_buffer->pBuffer, omx_buffer->nAllocLen, omx_buffer->nFilledLen);
1046 GST_LOG_OBJECT(port->core->object, "[FillThisBuffer] omx_buf=%p pBuf= %p, nAlloc= %d, nFill= %d",
1047 omx_buffer, omx_buffer->pBuffer, omx_buffer->nAllocLen, omx_buffer->nFilledLen);
1049 OMX_FillThisBuffer (port->core->omx_handle, omx_buffer);
1057 g_omx_port_resume (GOmxPort * port)
1059 async_queue_enable (port->queue);
1063 g_omx_port_pause (GOmxPort * port)
1065 async_queue_disable (port->queue);
1068 /* MODIFICATION: clean queue for DRC */
1070 g_omx_port_clean (GOmxPort * port)
1072 OMX_BUFFERHEADERTYPE *omx_buffer;
1074 if (port->type != GOMX_PORT_OUTPUT) {
1075 GST_ERROR("g_omx_port_clean is only for output port");
1079 while ((omx_buffer = async_queue_pop_forced (port->queue))) {
1080 omx_buffer->nFilledLen = 0;
1081 GST_LOG_OBJECT(port->core->object, "pop and free buffers from the client queue. omx_buffer= %p", omx_buffer);
1083 if ((port->core->reconfiguring == GOMX_RECONF_STATE_START||
1084 port->core->reconfiguring == GOMX_RECONF_STATE_PENDING)&&
1085 (port->enabled == FALSE)) {
1086 SCMN_IMGB * buffer = NULL;
1088 if (port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
1090 buffer = (SCMN_IMGB*)omx_buffer->pBuffer;
1093 if (buffer != NULL) {
1095 for(i = 0; i < port->num_buffers ; i ++) {
1097 if (buffer->fd[0] == port->scmn_out[i].fd[0]) {
1098 GST_INFO_OBJECT(port->core->object, "tbm_bo_unref: bo[%d] Y plane: %p", i, port->bo[i].bo_y);
1099 tbm_bo_unref(port->bo[i].bo_y);
1100 port->bo[i].bo_y = NULL;
1102 GST_INFO_OBJECT(port->core->object, "tbm_bo_unref: bo[%d] UV plane: %p", i, port->bo[i].bo_uv);
1103 tbm_bo_unref(port->bo[i].bo_uv);
1104 port->bo[i].bo_uv = NULL;
1109 GST_ERROR("pBuffer is NULL!! at omx_buffer= %p", omx_buffer);
1112 GST_INFO_OBJECT (port->core->object, "send OMX_FreeBuffer");
1113 OMX_FreeBuffer (port->core->omx_handle, port->port_index, omx_buffer);
1119 g_omx_port_flush (GOmxPort * port)
1121 if (port->type == GOMX_PORT_OUTPUT) {
1122 port->flushing = TRUE; /* to modify seek issue */
1125 GST_WARNING ("send OMX_CommandFlush. port: %d", port->type);
1126 OMX_SendCommand (port->core->omx_handle, OMX_CommandFlush, port->port_index, NULL);
1127 g_sem_down (port->core->flush_sem);
1131 g_omx_port_enable (GOmxPort * port)
1137 OMX_SendCommand (core->omx_handle, OMX_CommandPortEnable, port->port_index,
1139 port_allocate_buffers (port);
1140 if (core->omx_state != OMX_StateLoaded)
1141 port_start_buffers (port);
1142 g_omx_port_resume (port);
1144 g_sem_down (core->port_sem);
1148 g_omx_port_disable (GOmxPort * port)
1154 OMX_SendCommand (core->omx_handle, OMX_CommandPortDisable, port->port_index,
1156 g_omx_port_pause (port);
1157 g_omx_port_flush (port);
1158 port_free_buffers (port);
1160 g_sem_down (core->port_sem);
1164 g_omx_port_finish (GOmxPort * port)
1166 port->enabled = FALSE;
1167 async_queue_disable (port->queue);
1171 g_omx_cmd_queue_finish (GOmxCore * core)
1173 GST_WARNING ("disable command queue");
1174 core->cmd.cmd_queue_enabled = FALSE;
1175 async_queue_disable (core->cmd.cmd_queue);
1183 change_state (GOmxCore * core, OMX_STATETYPE state)
1185 GST_DEBUG_OBJECT (core->object, "state=%d", state);
1186 OMX_SendCommand (core->omx_handle, OMX_CommandStateSet, state, NULL);
1190 complete_change_state (GOmxCore * core, OMX_STATETYPE state)
1192 g_mutex_lock (core->omx_state_mutex);
1194 core->omx_state = state;
1195 g_cond_signal (core->omx_state_condition);
1196 GST_DEBUG_OBJECT (core->object, "state=%d", state);
1198 g_mutex_unlock (core->omx_state_mutex);
1202 wait_for_state (GOmxCore * core, OMX_STATETYPE state)
1207 g_mutex_lock (core->omx_state_mutex);
1208 if (core->omx_error != OMX_ErrorNone) {
1209 /* MODIFICATION: ignore init fail to stop. */
1210 if ((core->component_vendor == GOMX_VENDOR_SLSI_EXYNOS ||
1211 core->component_vendor == GOMX_VENDOR_SLSI_SEC) &&
1212 core->omx_error == OMX_ErrorMFCInit) {
1213 GST_LOG_OBJECT (core->object, "ignore init fail when going to stop");
1215 GST_ERROR_OBJECT (core->object, "there is error %s (0x%lx). but we will wait state change", omx_error_to_str (core->omx_error), core->omx_error);
1219 g_get_current_time (&tv);
1220 g_time_val_add (&tv, OMX_STATE_CHANGE_TIMEOUT * G_USEC_PER_SEC);
1223 if (core->omx_state != state) {
1225 g_cond_timed_wait (core->omx_state_condition, core->omx_state_mutex,
1229 GST_ERROR_OBJECT (core->object, "timed out switching from '%s' to '%s'",
1230 omx_state_to_str (core->omx_state), omx_state_to_str (state));
1234 if (core->omx_error != OMX_ErrorNone)
1237 if (core->omx_state != state) {
1238 GST_ERROR_OBJECT (core->object,
1239 "wrong state received: state=%d, expected=%d", core->omx_state, state);
1243 g_mutex_unlock (core->omx_state_mutex);
1251 in_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
1253 /** @todo remove this */
1260 out_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
1262 /** @todo remove this */
1268 if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) {
1269 g_omx_port_set_done (port);
1276 got_buffer (GOmxCore * core, GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
1278 if (G_UNLIKELY (!omx_buffer)) {
1282 if (G_LIKELY (port)) {
1283 g_omx_port_push_buffer (port, omx_buffer);
1285 switch (port->type) {
1286 case GOMX_PORT_INPUT:
1287 in_port_cb (port, omx_buffer);
1289 case GOMX_PORT_OUTPUT:
1290 out_port_cb (port, omx_buffer);
1298 /* MODIFICATION: Port setting changed */
1300 PortSettingsChanged(GOmxCore * core, OMX_U32 port_index)
1303 GstOmxSendCmdQueue *gomx_cmd = NULL;
1305 GST_LOG_OBJECT (core->object, "PortSettingsChanged enter");
1307 if (core->component_vendor == GOMX_VENDOR_SLSI_SEC) {
1308 GST_WARNING_OBJECT (core->object, "sec omx component does not handle PortSettingChanged Event. return");
1312 if (core->omx_state != OMX_StateExecuting) {
1313 GST_WARNING_OBJECT (core->object, "we got PortSettingsChanged Event not in Executing state. state = %d", core->omx_state);
1317 if (core->reconfiguring == GOMX_RECONF_STATE_PENDING) {
1318 GST_WARNING_OBJECT (core->object, "output_port_settingchanged_pending is true. return");
1322 port = get_port (core, port_index);
1324 GST_ERROR_OBJECT (core->object, "get_port (output port) returned NULL");
1328 if (port->enabled != TRUE) { /* FIX ME: need to change port enable checking sequence */
1329 core->reconfiguring = GOMX_RECONF_STATE_PENDING;
1330 GST_WARNING_OBJECT (core->object, "output port is not enabled. set output_port_settingchanged_pending and return");
1334 core->reconfiguring = GOMX_RECONF_STATE_START;
1335 port->enabled = FALSE;
1336 g_omx_port_pause(port);
1338 /* post OMX_CommandPortDisable */
1339 gomx_cmd = g_malloc(sizeof(GstOmxSendCmdQueue));
1340 gomx_cmd->type = GSTOMX_COMMAND_PORT_DISABLE;
1341 gomx_cmd->port = port->port_index;
1342 async_queue_push (core->cmd.cmd_queue, gomx_cmd);
1344 GST_LOG_OBJECT (core->object, "PortSettingsChanged leave.");
1349 PostCommand (gpointer data)
1351 GOmxCore *core = (GOmxCore *) data;
1353 GstOmxSendCmdQueue *gomx_cmd = NULL;
1356 GST_ERROR ("core is NULL!");
1360 gomx_cmd = (GstOmxSendCmdQueue*)async_queue_pop (core->cmd.cmd_queue);
1361 if (core->cmd.cmd_queue_enabled == FALSE) {
1362 GST_WARNING ("command queue is disable. goto leave.");
1366 if (gomx_cmd == NULL) {
1367 GST_ERROR ("gomx_cmd is NULL.");
1371 GST_INFO_OBJECT (core->object, "we got SendCommand. cmd: %d, port: %d", gomx_cmd->type, gomx_cmd->port);
1372 port = get_port (core, gomx_cmd->port);
1375 GST_ERROR ("port is NULL!");
1379 switch (gomx_cmd->type) {
1380 case GSTOMX_COMMAND_PORT_DISABLE:
1381 GST_WARNING_OBJECT (core->object, "send OMX_CommandPortDisable (port: %d)", port->port_index);
1382 OMX_SendCommand (core->omx_handle, OMX_CommandPortDisable, port->port_index, NULL);
1384 /* MODIFICATION: for DRC */
1385 if (port->type == GOMX_PORT_OUTPUT) {
1386 g_omx_port_clean (port);
1390 case GSTOMX_COMMAND_PORT_ENABLE:
1391 GST_WARNING_OBJECT (core->object, "send OMX_CommandPortEnable (port: %d)", port->port_index);
1392 OMX_SendCommand (core->omx_handle, OMX_CommandPortEnable, port->port_index, NULL);
1394 GST_INFO_OBJECT (core->object, "port_allocate_buffers (port idx: %d)", port->port_index);
1395 port_allocate_buffers (port);
1398 case GSTOMX_COMMAND_FREE_BUFFER: /* this case comes from fillbufferdone */
1399 GST_WARNING_OBJECT (core->object, "OMX_FreeBuffer (port: %d, omx_buffer = %p)", port->port_index, gomx_cmd->omx_buffer);
1400 if (gomx_cmd->omx_buffer) {
1401 OMX_FreeBuffer (core->omx_handle, port->port_index, gomx_cmd->omx_buffer);
1403 GST_ERROR_OBJECT (core->object, "GSTOMX_COMMAND_FREE_BUFFER fail. omx_buffer is NULL");
1418 GST_LOG_OBJECT (core->object, "SendCommand leave");
1422 gst_task_pause(core->cmd.cmd_task);
1423 GST_WARNING_OBJECT (core->object, "SendCommand leave. paused command task.");
1428 * OpenMAX IL callbacks.
1431 static OMX_ERRORTYPE
1432 EventHandler (OMX_HANDLETYPE omx_handle,
1434 OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
1437 GstOmxSendCmdQueue *gomx_cmd = NULL;
1439 core = (GOmxCore *) app_data;
1442 case OMX_EventCmdComplete:
1444 OMX_COMMANDTYPE cmd;
1446 cmd = (OMX_COMMANDTYPE) data_1;
1448 GST_DEBUG_OBJECT (core->object, "OMX_EventCmdComplete: %d", cmd);
1451 case OMX_CommandStateSet:
1452 complete_change_state (core, data_2);
1454 case OMX_CommandFlush:
1455 { /* MODIFICATION */
1456 OMX_U32 port_index = (OMX_U32)data_2;
1457 GOmxPort *port = get_port (core, port_index);
1459 GST_WARNING_OBJECT (core->object, "we got OMX_CommandFlush complete event (port idx: %d)", port_index);
1461 port->enabled = TRUE;
1463 if (port->type == GOMX_PORT_OUTPUT && core->reconfiguring == GOMX_RECONF_STATE_PENDING) {
1464 GST_INFO_OBJECT (core->object, "we already have outport port settingchanged pending. do it now");
1465 PortSettingsChanged(core, port_index);
1467 if (port->type == GOMX_PORT_OUTPUT) {
1468 OMX_BUFFERHEADERTYPE *omx_buffer;
1470 GST_WARNING_OBJECT (core->object, "before async_queue_pop_forced. queue_len= %d", port->queue->length);
1471 while ((omx_buffer = async_queue_pop_forced (port->queue))) {
1472 omx_buffer->nFilledLen = 0;
1473 g_omx_port_release_buffer (port, omx_buffer);
1474 GST_INFO_OBJECT (core->object, "send FIllThisBuffer (%d) omx_buffer = %p", cnt, omx_buffer);
1477 port->flushing = FALSE;
1479 g_sem_up (core->flush_sem);
1483 case OMX_CommandPortDisable:
1484 { /* MODIFICATION */
1485 OMX_U32 port_index = (OMX_U32)data_2;
1486 GOmxPort *port = get_port (core, port_index);
1488 GST_WARNING_OBJECT (core->object, "we got OMX_CommandPortDisable complete event (port idx: %d)", port_index);
1490 port->enabled = FALSE;
1492 if (port->type == GOMX_PORT_OUTPUT && core->reconfiguring == GOMX_RECONF_STATE_START) {
1493 gomx_cmd = g_malloc(sizeof(GstOmxSendCmdQueue));
1494 gomx_cmd->type = GSTOMX_COMMAND_PORT_ENABLE;
1495 gomx_cmd->port = port->port_index;
1496 async_queue_push (core->cmd.cmd_queue, gomx_cmd);
1498 g_sem_up (core->port_sem);
1502 case OMX_CommandPortEnable:
1503 { /* MODIFICATION */
1504 OMX_U32 port_index = (OMX_U32)data_2;
1505 GOmxPort *port = get_port (core, port_index);
1507 port->enabled = TRUE;
1509 GST_WARNING_OBJECT (core->object, "we got OMX_CommandPortEnable complete event (port idx: %d)", port_index);
1511 if (port->type == GOMX_PORT_OUTPUT && core->reconfiguring == GOMX_RECONF_STATE_START) {
1512 GST_INFO_OBJECT (core->object, "Reconfiguring is done. resume all port");
1513 if (core->omx_state == OMX_StateExecuting) {
1514 port_start_buffers (port);
1516 /* First flush the queue and then enable it. This will ensure queue variables are reset */
1517 async_queue_flush (port->queue);
1518 g_omx_port_resume(port);
1520 core->reconfiguring = GOMX_RECONF_STATE_DONE;
1521 GST_WARNING_OBJECT (core->object, "after drc port enable, send signal DRC done to output_loop task.");
1522 g_cond_signal(core->drc_cond);
1524 g_sem_up (core->port_sem);
1533 case OMX_EventBufferFlag:
1535 GST_DEBUG_OBJECT (core->object, "OMX_EventBufferFlag");
1536 if (data_2 & OMX_BUFFERFLAG_EOS) {
1537 g_omx_core_set_done (core);
1541 case OMX_EventPortSettingsChanged:
1543 GST_WARNING_OBJECT (core->object, "we got OMX_EventPortSettingsChanged. (in state = %d)", core->omx_state);
1544 /** @todo only on the relevant port. */
1546 if (data_2 == 0 || data_2 == OMX_IndexParamPortDefinition) {
1547 OMX_U32 port_index = (OMX_U32)data_1;
1548 GOmxPort *port = get_port (core, port_index);
1550 GST_WARNING_OBJECT (core->object, "start reconfiguring for output port");
1552 if (port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
1553 PortSettingsChanged(core, port_index);
1555 } else if (data_2 == OMX_IndexConfigCommonOutputCrop) {
1556 core->crop_changed = TRUE;
1557 GST_WARNING_OBJECT (core->object, "we got only OMX_IndexConfigCommonOutputCrop");
1560 if (core->settings_changed_cb) {
1561 core->settings_changed_cb (core);
1565 case OMX_EventError:
1567 core->omx_error = data_1;
1568 GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
1569 omx_error_to_str (data_1), data_1);
1570 /* component might leave us waiting for buffers, unblock */
1571 g_omx_core_flush_start (core);
1572 /* unlock wait_for_state */
1573 g_mutex_lock (core->omx_state_mutex);
1574 /* MODIFICATION: set to ignore condition signal to stop. */
1575 if ((core->component_vendor == GOMX_VENDOR_SLSI_EXYNOS ||
1576 core->component_vendor == GOMX_VENDOR_SLSI_SEC) &&
1577 core->omx_error == OMX_ErrorMFCInit) {
1578 GST_WARNING_OBJECT (core->object, "do not send g_cond_signal when MFC init fail. (%d)",
1579 core->omx_unrecover_err_cnt);
1580 if (core->omx_unrecover_err_cnt == 0) {
1581 if (core->post_gst_element_error == FALSE) {
1582 GST_ERROR_OBJECT (core->object, "post GST_ELEMENT_ERROR as Error from OpenMAX component");
1583 GST_ELEMENT_ERROR (core->object, STREAM, FAILED, (NULL), ("%s", "Error from OpenMAX component"));
1584 core->post_gst_element_error = TRUE;
1586 GST_ERROR_OBJECT (core->object, "GST_ELEMENT_ERROR is already posted. skip this (Error from OpenMAX component)");
1589 core->omx_unrecover_err_cnt++;
1591 g_cond_signal (core->omx_state_condition);
1593 g_mutex_unlock (core->omx_state_mutex);
1594 if (core->omx_unrecover_err_cnt >= OMX_UNRECOVERABLE_ERROR_MAX_COUNT) {
1595 GST_WARNING_OBJECT (core->object, "got unrecoverable error too much. go to omx pause state");
1596 g_omx_core_pause(core);
1597 core->omx_unrecover_err_cnt = 0;
1605 return OMX_ErrorNone;
1608 static OMX_ERRORTYPE
1609 EmptyBufferDone (OMX_HANDLETYPE omx_handle,
1610 OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer)
1614 private_data *pAppPrivate;
1616 core = (GOmxCore *) app_data;
1617 port = get_port (core, omx_buffer->nInputPortIndex);
1618 pAppPrivate = (private_data*)omx_buffer->pAppPrivate;
1620 GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer = %p",
1624 if (core->input_log_count < MAX_DEBUG_FRAME_CNT) {
1625 GST_CAT_WARNING_OBJECT (gstomx_util_debug, core->object, "unref pAppPrivate. gst_buf= %p", pAppPrivate);
1627 GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "unref pAppPrivate. gst_buf= %p", pAppPrivate);
1629 gst_buffer_unref ((GstBuffer *)pAppPrivate);
1634 /* MODIFICATION: enc input buffer unref after EBD. */
1635 if (omx_buffer->nFlags == OMX_BUFFERFLAG_EOS && core->codec_type == GSTOMX_CODECTYPE_VIDEO_ENC) {
1636 if (omx_buffer->pBuffer != NULL) {
1637 GST_CAT_WARNING_OBJECT (gstomx_util_debug, core->object, "g_free eos omx_buffer->pBuffer. p = %p", omx_buffer->pBuffer);
1638 g_free(omx_buffer->pBuffer);
1639 omx_buffer->pBuffer = NULL;
1643 omx_buffer->nFlags = 0x00000000;
1644 got_buffer (core, port, omx_buffer);
1646 return OMX_ErrorNone;
1649 static OMX_ERRORTYPE
1650 FillBufferDone (OMX_HANDLETYPE omx_handle,
1651 OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer)
1655 OMX_PARAM_PORTDEFINITIONTYPE param;
1657 G_OMX_INIT_PARAM (param);
1659 core = (GOmxCore *) app_data;
1660 port = get_port (core, omx_buffer->nOutputPortIndex);
1662 if (core->output_log_count < MAX_DEBUG_FRAME_CNT) {
1663 GST_CAT_WARNING_OBJECT (gstomx_util_debug, core->object, "omx_buffer= %p pBuf= %p nFill= %d state= %d",
1664 omx_buffer, omx_buffer->pBuffer, omx_buffer->nFilledLen, core->omx_state);
1668 GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer= %p pBuf= %p nFill= %d state= %d",
1669 omx_buffer, omx_buffer->pBuffer, omx_buffer->nFilledLen, core->omx_state);
1673 /* MODIFICATION: for DRC */
1674 if ((core->reconfiguring == GOMX_RECONF_STATE_START||
1675 core->reconfiguring == GOMX_RECONF_STATE_PENDING)&&
1676 (port->enabled == FALSE)) {
1677 GstOmxSendCmdQueue *gomx_cmd = NULL;
1678 SCMN_IMGB * buffer = NULL;
1680 buffer = (SCMN_IMGB*)omx_buffer->pBuffer;
1682 GST_WARNING_OBJECT (core->object, "this FBD is flush response. do not queue.");
1684 if (core->omx_state != OMX_StateExecuting) {
1685 GST_ERROR_OBJECT (core->object, "OMX_EventPortSettingsChanged but not executing. do not free buffer now.");
1689 /* send OMX_FreeBuffer */
1690 gomx_cmd = g_malloc(sizeof(GstOmxSendCmdQueue));
1691 gomx_cmd->type = GSTOMX_COMMAND_FREE_BUFFER;
1692 gomx_cmd->port = port->port_index;
1693 gomx_cmd->omx_buffer = omx_buffer;
1694 async_queue_push (core->cmd.cmd_queue, gomx_cmd);
1696 if (port->buffer_type == GOMX_BUFFER_GEM_VDEC_OUTPUT) {
1698 for(i = 0; i < port->num_buffers ; i ++) {
1699 if (buffer->fd[0] == port->scmn_out[i].fd[0]) {
1700 GST_INFO_OBJECT(port->core->object, "tbm_bo_unref: bo[%d] Y plane: %p", i, port->bo[i].bo_y);
1701 tbm_bo_unref(port->bo[i].bo_y);
1702 port->bo[i].bo_y = NULL;
1704 GST_INFO_OBJECT(port->core->object, "tbm_bo_unref: bo[%d] UV plane: %p", i, port->bo[i].bo_uv);
1705 tbm_bo_unref(port->bo[i].bo_uv);
1706 port->bo[i].bo_uv = NULL;
1716 got_buffer (core, port, omx_buffer);
1719 return OMX_ErrorNone;
1722 static inline const char *
1723 omx_state_to_str (OMX_STATETYPE omx_state)
1725 switch (omx_state) {
1726 case OMX_StateInvalid:
1728 case OMX_StateLoaded:
1732 case OMX_StateExecuting:
1734 case OMX_StatePause:
1736 case OMX_StateWaitForResources:
1737 return "wait for resources";
1743 static inline const char *
1744 omx_error_to_str (OMX_ERRORTYPE omx_error)
1746 switch (omx_error) {
1750 case OMX_ErrorInsufficientResources:
1752 "There were insufficient resources to perform the requested operation";
1754 case OMX_ErrorUndefined:
1755 return "The cause of the error could not be determined";
1757 case OMX_ErrorInvalidComponentName:
1758 return "The component name string was not valid";
1760 case OMX_ErrorComponentNotFound:
1761 return "No component with the specified name string was found";
1763 case OMX_ErrorInvalidComponent:
1764 return "The component specified did not have an entry point";
1766 case OMX_ErrorBadParameter:
1767 return "One or more parameters were not valid";
1769 case OMX_ErrorNotImplemented:
1770 return "The requested function is not implemented";
1772 case OMX_ErrorUnderflow:
1773 return "The buffer was emptied before the next buffer was ready";
1775 case OMX_ErrorOverflow:
1776 return "The buffer was not available when it was needed";
1778 case OMX_ErrorHardware:
1779 return "The hardware failed to respond as expected";
1781 case OMX_ErrorInvalidState:
1782 return "The component is in invalid state";
1784 case OMX_ErrorStreamCorrupt:
1785 return "Stream is found to be corrupt";
1787 case OMX_ErrorPortsNotCompatible:
1788 return "Ports being connected are not compatible";
1790 case OMX_ErrorResourcesLost:
1791 return "Resources allocated to an idle component have been lost";
1793 case OMX_ErrorNoMore:
1794 return "No more indices can be enumerated";
1796 case OMX_ErrorVersionMismatch:
1797 return "The component detected a version mismatch";
1799 case OMX_ErrorNotReady:
1800 return "The component is not ready to return data at this time";
1802 case OMX_ErrorTimeout:
1803 return "There was a timeout that occurred";
1805 case OMX_ErrorSameState:
1807 "This error occurs when trying to transition into the state you are already in";
1809 case OMX_ErrorResourcesPreempted:
1811 "Resources allocated to an executing or paused component have been preempted";
1813 case OMX_ErrorPortUnresponsiveDuringAllocation:
1815 "Waited an unusually long time for the supplier to allocate buffers";
1817 case OMX_ErrorPortUnresponsiveDuringDeallocation:
1819 "Waited an unusually long time for the supplier to de-allocate buffers";
1821 case OMX_ErrorPortUnresponsiveDuringStop:
1823 "Waited an unusually long time for the non-supplier to return a buffer during stop";
1825 case OMX_ErrorIncorrectStateTransition:
1826 return "Attempting a state transition that is not allowed";
1828 case OMX_ErrorIncorrectStateOperation:
1830 "Attempting a command that is not allowed during the present state";
1832 case OMX_ErrorUnsupportedSetting:
1834 "The values encapsulated in the parameter or config structure are not supported";
1836 case OMX_ErrorUnsupportedIndex:
1838 "The parameter or config indicated by the given index is not supported";
1840 case OMX_ErrorBadPortIndex:
1841 return "The port index supplied is incorrect";
1843 case OMX_ErrorPortUnpopulated:
1845 "The port has lost one or more of its buffers and it thus unpopulated";
1847 case OMX_ErrorComponentSuspended:
1848 return "Component suspended due to temporary loss of resources";
1850 case OMX_ErrorDynamicResourcesUnavailable:
1852 "Component suspended due to an inability to acquire dynamic resources";
1854 case OMX_ErrorMbErrorsInFrame:
1855 return "Frame generated macroblock error";
1857 case OMX_ErrorFormatNotDetected:
1858 return "Cannot parse or determine the format of an input stream";
1860 case OMX_ErrorContentPipeOpenFailed:
1861 return "The content open operation failed";
1863 case OMX_ErrorContentPipeCreationFailed:
1864 return "The content creation operation failed";
1866 case OMX_ErrorSeperateTablesUsed:
1867 return "Separate table information is being used";
1869 case OMX_ErrorTunnelingUnsupported:
1870 return "Tunneling is unsupported by the component";
1873 return "Unknown error";