From 86d9a2c81c60a3a246c7052e70e9d50b8a12b156 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Mon, 17 Jul 2017 21:06:47 +0100 Subject: [PATCH] omxvideodec: make generic the OMX_UseEGLImage code path Will be easier to maintain and to make enhancements. Tested with Tizonia on Desktop. Also tested with Bellagio to make sure it does not crash when calling OMX_UseEGLImage and indeed it returns NotImplemented. Then gst-omx fallback to OMX_UseBuffer if it can and so on. Also tested on rpi to make sure there is no regression. https://bugzilla.gnome.org/show_bug.cgi?id=784365 --- omx/gstomxvideodec.c | 101 +++++++++++++++++++++++++++++-------------- omx/gstomxvideodec.h | 6 ++- 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index 97e7ee8769..d90913ce53 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -37,8 +37,7 @@ #pragma GCC optimize ("gnu89-inline") #endif -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) -#include +#if defined (HAVE_GST_GL) #include #endif @@ -126,7 +125,7 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass) klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER; klass->cdata.default_src_template_caps = -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) +#if defined (HAVE_GST_GL) GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, "RGBA") "; " #endif @@ -620,11 +619,10 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) GST_BUFFER_POOL_OPTION_VIDEO_META); gst_structure_free (config); -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) +#if defined (HAVE_GST_GL) eglimage = self->eglimage && (allocator && GST_IS_GL_MEMORY_EGL_ALLOCATOR (allocator)); #else - /* TODO: Implement something that works for other targets too */ eglimage = FALSE; #endif caps = caps ? gst_caps_ref (caps) : NULL; @@ -638,7 +636,7 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) GST_DEBUG_OBJECT (self, "No pool available, not negotiated yet"); } -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) +#if defined (HAVE_GST_GL) /* Will retry without EGLImage */ if (self->eglimage && !eglimage) { GST_DEBUG_OBJECT (self, @@ -652,13 +650,14 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) self->out_port_pool = gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port, self->dmabuf); -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) + +#if defined (HAVE_GST_GL) if (eglimage) { GList *buffers = NULL; GList *images = NULL; gint i; GstBufferPoolAcquireParams params = { 0, }; - EGLDisplay egl_display = EGL_NO_DISPLAY; + EGLDisplay egl_display = 0; GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min); @@ -677,15 +676,13 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) g_list_free (images); buffers = NULL; images = NULL; - /* TODO: For non-RPi targets we want to use the normal memory code below */ - /* Retry without EGLImage */ err = OMX_ErrorUndefined; goto done; } gl_mem = (GstGLMemoryEGL *) mem; buffers = g_list_append (buffers, buffer); images = g_list_append (images, gst_gl_memory_egl_get_image (gl_mem)); - if (egl_display == EGL_NO_DISPLAY) + if (!egl_display) egl_display = gst_gl_memory_egl_get_display (gl_mem); } @@ -694,18 +691,14 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) /* Everything went fine? */ if (eglimage) { GST_DEBUG_OBJECT (self, "Setting EGLDisplay"); - self->egl_out_port->port_def.format.video.pNativeWindow = egl_display; - err = - gst_omx_port_update_port_definition (self->egl_out_port, - &self->egl_out_port->port_def); + port->port_def.format.video.pNativeWindow = egl_display; + err = gst_omx_port_update_port_definition (port, &port->port_def); if (err != OMX_ErrorNone) { GST_INFO_OBJECT (self, "Failed to set EGLDisplay on port: %s (0x%08x)", gst_omx_error_to_string (err), err); g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); g_list_free (images); - /* TODO: For non-RPi targets we want to use the normal memory code below */ - /* Retry without EGLImage */ goto done; } else { GList *l; @@ -723,11 +716,28 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) gst_omx_error_to_string (err), err); g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); g_list_free (images); - /* TODO: For non-RPi targets we want to use the normal memory code below */ - /* Retry without EGLImage */ - goto done; } +#if OMX_VERSION_MINOR == 2 + /* In OMX-IL 1.2.0, the nBufferCountActual change is propagated to the + * the input port upon call to the SetParameter on out port above. This + * propagation triggers a SettingsChanged event. It is up to the client + * to decide if this event should lead to reconfigure the port. Here + * this is clearly informal so lets just acknowledge the event to avoid + * input port reconfiguration. Note that the SettingsChanged event will + * be sent in-context of the SetParameter call above. So the event is + * garantie to be proceeded in the handle_message call below. */ + err = gst_omx_port_mark_reconfigured (self->dec_in_port); + + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (self, + "Failed to acknowledge port settings changed: %s (0x%08x)", + gst_omx_error_to_string (err), err); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + g_list_free (images); + goto done; + } +#endif } if (!gst_omx_port_is_enabled (port)) { @@ -738,8 +748,6 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) gst_omx_error_to_string (err), err); g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); g_list_free (images); - /* TODO: For non-RPi targets we want to use the normal memory code below */ - /* Retry without EGLImage */ goto done; } } @@ -752,8 +760,6 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) "Failed to pass EGLImages to port: %s (0x%08x)", gst_omx_error_to_string (err), err); g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); - /* TODO: For non-RPi targets we want to use the normal memory code below */ - /* Retry without EGLImage */ goto done; } @@ -763,8 +769,6 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) "Failed to wait until port is enabled: %s (0x%08x)", gst_omx_error_to_string (err), err); g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); - /* TODO: For non-RPi targets we want to use the normal memory code below */ - /* Retry without EGLImage */ goto done; } @@ -780,7 +784,7 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self) } } } -#endif +#endif /* defined (HAVE_GST_GL) */ /* If not using EGLImage or trying to use EGLImage failed */ if (!eglimage) { @@ -1062,13 +1066,19 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self) /* At this point the decoder output port is disabled */ -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) +#if defined (HAVE_GST_GL) { +#if defined (USE_OMX_TARGET_RPI) OMX_STATETYPE egl_state; +#endif if (self->eglimage) { /* Nothing to do here, we could however fall back to non-EGLImage in theory */ +#if defined (USE_OMX_TARGET_RPI) port = self->egl_out_port; +#else + port = self->dec_out_port; +#endif err = OMX_ErrorNone; goto enable_port; } else { @@ -1099,6 +1109,7 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self) if (state->caps) gst_caps_replace (&state->caps, NULL); +#if defined (USE_OMX_TARGET_RPI) /* fallback: try to use EGLImage even if it is not in the caps feature */ if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { gst_video_codec_state_unref (state); @@ -1106,11 +1117,16 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self) GST_VIDEO_DECODER_STREAM_UNLOCK (self); goto no_egl; } +#else + GST_VIDEO_DECODER_STREAM_UNLOCK (self); + goto no_egl; +#endif } gst_video_codec_state_unref (state); GST_VIDEO_DECODER_STREAM_UNLOCK (self); +#if defined (USE_OMX_TARGET_RPI) /* Now link it all together */ err = gst_omx_port_set_enabled (self->egl_in_port, FALSE); @@ -1213,10 +1229,16 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self) goto no_egl; goto done; +#else + port = self->dec_out_port; + err = OMX_ErrorNone; + goto enable_port; +#endif /* defined (USE_OMX_TARGET_RPI) */ } no_egl: +#if defined (USE_OMX_TARGET_RPI) gst_omx_port_set_enabled (self->dec_out_port, FALSE); gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND); egl_state = gst_omx_component_get_state (self->egl_render, 0); @@ -1234,12 +1256,14 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self) gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND); } } +#endif /* After this egl_render should be deactivated * and the decoder's output port disabled */ self->eglimage = FALSE; } -#endif +#endif /* defined (HAVE_GST_GL) */ + port = self->dec_out_port; /* Update caps */ @@ -1282,12 +1306,23 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self) GST_VIDEO_DECODER_STREAM_UNLOCK (self); -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) +#if defined (HAVE_GST_GL) enable_port: #endif + err = gst_omx_video_dec_allocate_output_buffers (self); - if (err != OMX_ErrorNone) + if (err != OMX_ErrorNone) { +#if defined (HAVE_GST_GL) + /* TODO: works on desktop but need to try on RPI. */ +#if !defined (USE_OMX_TARGET_RPI) + if (self->eglimage) { + GST_INFO_OBJECT (self, "Fallback to non eglimage"); + goto no_egl; + } +#endif +#endif goto done; + } err = gst_omx_port_populate (port); if (err != OMX_ErrorNone) @@ -2689,7 +2724,7 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) GstStructure *config; GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (bdec); -#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL) +#if defined (HAVE_GST_GL) { GstCaps *caps; gint i, n; @@ -2731,7 +2766,7 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) } } } -#endif +#endif /* defined (HAVE_GST_GL) */ self->use_buffers = FALSE; if (gst_query_get_n_allocation_pools (query) > 0) { diff --git a/omx/gstomxvideodec.h b/omx/gstomxvideodec.h index 9aee266c48..cc7bd15e07 100644 --- a/omx/gstomxvideodec.h +++ b/omx/gstomxvideodec.h @@ -80,9 +80,13 @@ struct _GstOMXVideoDec * Switched to FALSE if this trial fails so that the decoder * can fallback to OMX_AllocateBuffer. */ gboolean use_buffers; -#ifdef USE_OMX_TARGET_RPI + +#if defined (USE_OMX_TARGET_RPI) GstOMXComponent *egl_render; GstOMXPort *egl_in_port, *egl_out_port; +#endif + +#if defined (HAVE_GST_GL) gboolean eglimage; #endif