mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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
This commit is contained in:
parent
64f7f781d8
commit
86d9a2c81c
2 changed files with 73 additions and 34 deletions
|
@ -37,8 +37,7 @@
|
||||||
#pragma GCC optimize ("gnu89-inline")
|
#pragma GCC optimize ("gnu89-inline")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
|
#if defined (HAVE_GST_GL)
|
||||||
#include <gst/gl/gl.h>
|
|
||||||
#include <gst/gl/egl/gstglmemoryegl.h>
|
#include <gst/gl/egl/gstglmemoryegl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -126,7 +125,7 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
|
||||||
|
|
||||||
klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
|
klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
|
||||||
klass->cdata.default_src_template_caps =
|
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,
|
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY,
|
||||||
"RGBA") "; "
|
"RGBA") "; "
|
||||||
#endif
|
#endif
|
||||||
|
@ -620,11 +619,10 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
||||||
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||||
gst_structure_free (config);
|
gst_structure_free (config);
|
||||||
|
|
||||||
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
|
#if defined (HAVE_GST_GL)
|
||||||
eglimage = self->eglimage
|
eglimage = self->eglimage
|
||||||
&& (allocator && GST_IS_GL_MEMORY_EGL_ALLOCATOR (allocator));
|
&& (allocator && GST_IS_GL_MEMORY_EGL_ALLOCATOR (allocator));
|
||||||
#else
|
#else
|
||||||
/* TODO: Implement something that works for other targets too */
|
|
||||||
eglimage = FALSE;
|
eglimage = FALSE;
|
||||||
#endif
|
#endif
|
||||||
caps = caps ? gst_caps_ref (caps) : NULL;
|
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");
|
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 */
|
/* Will retry without EGLImage */
|
||||||
if (self->eglimage && !eglimage) {
|
if (self->eglimage && !eglimage) {
|
||||||
GST_DEBUG_OBJECT (self,
|
GST_DEBUG_OBJECT (self,
|
||||||
|
@ -652,13 +650,14 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
||||||
self->out_port_pool =
|
self->out_port_pool =
|
||||||
gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port,
|
gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port,
|
||||||
self->dmabuf);
|
self->dmabuf);
|
||||||
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
|
|
||||||
|
#if defined (HAVE_GST_GL)
|
||||||
if (eglimage) {
|
if (eglimage) {
|
||||||
GList *buffers = NULL;
|
GList *buffers = NULL;
|
||||||
GList *images = NULL;
|
GList *images = NULL;
|
||||||
gint i;
|
gint i;
|
||||||
GstBufferPoolAcquireParams params = { 0, };
|
GstBufferPoolAcquireParams params = { 0, };
|
||||||
EGLDisplay egl_display = EGL_NO_DISPLAY;
|
EGLDisplay egl_display = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min);
|
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);
|
g_list_free (images);
|
||||||
buffers = NULL;
|
buffers = NULL;
|
||||||
images = NULL;
|
images = NULL;
|
||||||
/* TODO: For non-RPi targets we want to use the normal memory code below */
|
|
||||||
/* Retry without EGLImage */
|
|
||||||
err = OMX_ErrorUndefined;
|
err = OMX_ErrorUndefined;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
gl_mem = (GstGLMemoryEGL *) mem;
|
gl_mem = (GstGLMemoryEGL *) mem;
|
||||||
buffers = g_list_append (buffers, buffer);
|
buffers = g_list_append (buffers, buffer);
|
||||||
images = g_list_append (images, gst_gl_memory_egl_get_image (gl_mem));
|
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);
|
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? */
|
/* Everything went fine? */
|
||||||
if (eglimage) {
|
if (eglimage) {
|
||||||
GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
|
GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
|
||||||
self->egl_out_port->port_def.format.video.pNativeWindow = egl_display;
|
port->port_def.format.video.pNativeWindow = egl_display;
|
||||||
err =
|
err = gst_omx_port_update_port_definition (port, &port->port_def);
|
||||||
gst_omx_port_update_port_definition (self->egl_out_port,
|
|
||||||
&self->egl_out_port->port_def);
|
|
||||||
if (err != OMX_ErrorNone) {
|
if (err != OMX_ErrorNone) {
|
||||||
GST_INFO_OBJECT (self,
|
GST_INFO_OBJECT (self,
|
||||||
"Failed to set EGLDisplay on port: %s (0x%08x)",
|
"Failed to set EGLDisplay on port: %s (0x%08x)",
|
||||||
gst_omx_error_to_string (err), err);
|
gst_omx_error_to_string (err), err);
|
||||||
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
||||||
g_list_free (images);
|
g_list_free (images);
|
||||||
/* TODO: For non-RPi targets we want to use the normal memory code below */
|
|
||||||
/* Retry without EGLImage */
|
|
||||||
goto done;
|
goto done;
|
||||||
} else {
|
} else {
|
||||||
GList *l;
|
GList *l;
|
||||||
|
@ -723,11 +716,28 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
||||||
gst_omx_error_to_string (err), err);
|
gst_omx_error_to_string (err), err);
|
||||||
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
||||||
g_list_free (images);
|
g_list_free (images);
|
||||||
/* TODO: For non-RPi targets we want to use the normal memory code below */
|
|
||||||
/* Retry without EGLImage */
|
|
||||||
|
|
||||||
goto done;
|
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)) {
|
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);
|
gst_omx_error_to_string (err), err);
|
||||||
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
||||||
g_list_free (images);
|
g_list_free (images);
|
||||||
/* TODO: For non-RPi targets we want to use the normal memory code below */
|
|
||||||
/* Retry without EGLImage */
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -752,8 +760,6 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
||||||
"Failed to pass EGLImages to port: %s (0x%08x)",
|
"Failed to pass EGLImages to port: %s (0x%08x)",
|
||||||
gst_omx_error_to_string (err), err);
|
gst_omx_error_to_string (err), err);
|
||||||
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
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;
|
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)",
|
"Failed to wait until port is enabled: %s (0x%08x)",
|
||||||
gst_omx_error_to_string (err), err);
|
gst_omx_error_to_string (err), err);
|
||||||
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
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;
|
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 not using EGLImage or trying to use EGLImage failed */
|
||||||
if (!eglimage) {
|
if (!eglimage) {
|
||||||
|
@ -1062,13 +1066,19 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
|
||||||
|
|
||||||
/* At this point the decoder output port is disabled */
|
/* 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;
|
OMX_STATETYPE egl_state;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (self->eglimage) {
|
if (self->eglimage) {
|
||||||
/* Nothing to do here, we could however fall back to non-EGLImage in theory */
|
/* 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;
|
port = self->egl_out_port;
|
||||||
|
#else
|
||||||
|
port = self->dec_out_port;
|
||||||
|
#endif
|
||||||
err = OMX_ErrorNone;
|
err = OMX_ErrorNone;
|
||||||
goto enable_port;
|
goto enable_port;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1099,6 +1109,7 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
|
||||||
if (state->caps)
|
if (state->caps)
|
||||||
gst_caps_replace (&state->caps, NULL);
|
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 */
|
/* fallback: try to use EGLImage even if it is not in the caps feature */
|
||||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||||
gst_video_codec_state_unref (state);
|
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);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||||
goto no_egl;
|
goto no_egl;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||||
|
goto no_egl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_video_codec_state_unref (state);
|
gst_video_codec_state_unref (state);
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||||
|
|
||||||
|
#if defined (USE_OMX_TARGET_RPI)
|
||||||
/* Now link it all together */
|
/* Now link it all together */
|
||||||
|
|
||||||
err = gst_omx_port_set_enabled (self->egl_in_port, FALSE);
|
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 no_egl;
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
|
#else
|
||||||
|
port = self->dec_out_port;
|
||||||
|
err = OMX_ErrorNone;
|
||||||
|
goto enable_port;
|
||||||
|
#endif /* defined (USE_OMX_TARGET_RPI) */
|
||||||
}
|
}
|
||||||
|
|
||||||
no_egl:
|
no_egl:
|
||||||
|
|
||||||
|
#if defined (USE_OMX_TARGET_RPI)
|
||||||
gst_omx_port_set_enabled (self->dec_out_port, FALSE);
|
gst_omx_port_set_enabled (self->dec_out_port, FALSE);
|
||||||
gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
|
gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
|
||||||
egl_state = gst_omx_component_get_state (self->egl_render, 0);
|
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);
|
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* After this egl_render should be deactivated
|
/* After this egl_render should be deactivated
|
||||||
* and the decoder's output port disabled */
|
* and the decoder's output port disabled */
|
||||||
self->eglimage = FALSE;
|
self->eglimage = FALSE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* defined (HAVE_GST_GL) */
|
||||||
|
|
||||||
port = self->dec_out_port;
|
port = self->dec_out_port;
|
||||||
|
|
||||||
/* Update caps */
|
/* Update caps */
|
||||||
|
@ -1282,12 +1306,23 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
|
||||||
|
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||||
|
|
||||||
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
|
#if defined (HAVE_GST_GL)
|
||||||
enable_port:
|
enable_port:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = gst_omx_video_dec_allocate_output_buffers (self);
|
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;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
err = gst_omx_port_populate (port);
|
err = gst_omx_port_populate (port);
|
||||||
if (err != OMX_ErrorNone)
|
if (err != OMX_ErrorNone)
|
||||||
|
@ -2689,7 +2724,7 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (bdec);
|
GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (bdec);
|
||||||
|
|
||||||
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
|
#if defined (HAVE_GST_GL)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
gint i, n;
|
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;
|
self->use_buffers = FALSE;
|
||||||
if (gst_query_get_n_allocation_pools (query) > 0) {
|
if (gst_query_get_n_allocation_pools (query) > 0) {
|
||||||
|
|
|
@ -80,9 +80,13 @@ struct _GstOMXVideoDec
|
||||||
* Switched to FALSE if this trial fails so that the decoder
|
* Switched to FALSE if this trial fails so that the decoder
|
||||||
* can fallback to OMX_AllocateBuffer. */
|
* can fallback to OMX_AllocateBuffer. */
|
||||||
gboolean use_buffers;
|
gboolean use_buffers;
|
||||||
#ifdef USE_OMX_TARGET_RPI
|
|
||||||
|
#if defined (USE_OMX_TARGET_RPI)
|
||||||
GstOMXComponent *egl_render;
|
GstOMXComponent *egl_render;
|
||||||
GstOMXPort *egl_in_port, *egl_out_port;
|
GstOMXPort *egl_in_port, *egl_out_port;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (HAVE_GST_GL)
|
||||||
gboolean eglimage;
|
gboolean eglimage;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue