mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
omxvideodec: Add support for egl_render on RPi
This commit is contained in:
parent
d0a5a9a9bf
commit
8a1bb1b4a3
6 changed files with 714 additions and 99 deletions
|
@ -145,6 +145,7 @@ AG_GST_CHECK_GST_CONTROLLER($GST_API_VERSION, [$GST_REQ], yes)
|
|||
AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no)
|
||||
AG_GST_CHECK_GST_PLUGINS_BASE($GST_API_VERSION, [$GST_REQ], yes)
|
||||
AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes")
|
||||
PKG_CHECK_MODULES([GST_PLUGINS_BAD], [gstreamer-plugins-bad-1.0])
|
||||
|
||||
dnl Check for documentation xrefs
|
||||
GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
|
||||
|
|
|
@ -53,10 +53,13 @@ endif
|
|||
libgstomx_la_CFLAGS = \
|
||||
-DGST_USE_UNSTABLE_API=1 \
|
||||
$(OMX_INCLUDEPATH) \
|
||||
$(GST_PLUGINS_BAD_CFLAGS) \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(GST_BASE_CFLAGS) \
|
||||
$(GST_CFLAGS)
|
||||
libgstomx_la_LIBADD = \
|
||||
$(GST_PLUGINS_BAD_LIBS) \
|
||||
-lgstegl-@GST_API_VERSION@ \
|
||||
$(GST_PLUGINS_BASE_LIBS) \
|
||||
-lgstaudio-@GST_API_VERSION@ \
|
||||
-lgstpbutils-@GST_API_VERSION@ \
|
||||
|
|
|
@ -1066,14 +1066,10 @@ gst_omx_component_setup_tunnel (GstOMXComponent * comp1, GstOMXPort * port1,
|
|||
OMX_ERRORTYPE err;
|
||||
|
||||
g_return_val_if_fail (comp1 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (comp1->state == OMX_StateLoaded
|
||||
|| !port1->port_def.bEnabled, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
|
||||
OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (comp2 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (comp2->state == OMX_StateLoaded
|
||||
|| !port2->port_def.bEnabled, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
|
||||
OMX_ErrorUndefined);
|
||||
|
@ -1111,14 +1107,10 @@ gst_omx_component_close_tunnel (GstOMXComponent * comp1, GstOMXPort * port1,
|
|||
OMX_ERRORTYPE err;
|
||||
|
||||
g_return_val_if_fail (comp1 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (comp1->state == OMX_StateLoaded
|
||||
|| !port1->port_def.bEnabled, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
|
||||
OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (comp2 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (comp2->state == OMX_StateLoaded
|
||||
|| !port2->port_def.bEnabled, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
|
||||
g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
|
||||
OMX_ErrorUndefined);
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
#include <OMX_Core.h>
|
||||
#include <OMX_Component.h>
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
#include <OMX_Broadcom.h>
|
||||
#endif
|
||||
|
||||
#ifdef GST_OMX_STRUCT_PACKING
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/video/gstvideometa.h>
|
||||
#include <gst/video/gstvideopool.h>
|
||||
#include <gst/egl/egl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gstomxvideodec.h"
|
||||
|
@ -776,6 +777,53 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
|
|||
|
||||
GST_DEBUG_OBJECT (self, "Opened decoder");
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
GST_DEBUG_OBJECT (self, "Opening EGL renderer");
|
||||
self->egl_render =
|
||||
gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
|
||||
"OMX.broadcom.egl_render", NULL, klass->cdata.hacks);
|
||||
|
||||
if (!self->egl_render)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_component_get_state (self->egl_render,
|
||||
GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
OMX_PORT_PARAM_TYPE param;
|
||||
OMX_ERRORTYPE err;
|
||||
|
||||
GST_OMX_INIT_STRUCT (¶m);
|
||||
|
||||
err =
|
||||
gst_omx_component_get_parameter (self->egl_render,
|
||||
OMX_IndexParamVideoInit, ¶m);
|
||||
if (err != OMX_ErrorNone) {
|
||||
GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
|
||||
gst_omx_error_to_string (err), err);
|
||||
/* Fallback */
|
||||
in_port_index = 0;
|
||||
out_port_index = 1;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
|
||||
param.nStartPortNumber);
|
||||
in_port_index = param.nStartPortNumber + 0;
|
||||
out_port_index = param.nStartPortNumber + 1;
|
||||
}
|
||||
}
|
||||
|
||||
self->egl_in_port =
|
||||
gst_omx_component_add_port (self->egl_render, in_port_index);
|
||||
self->egl_out_port =
|
||||
gst_omx_component_add_port (self->egl_render, out_port_index);
|
||||
|
||||
if (!self->egl_in_port || !self->egl_out_port)
|
||||
return FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Opened EGL renderer");
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -786,6 +834,32 @@ gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
|
|||
|
||||
GST_DEBUG_OBJECT (self, "Shutting down decoder");
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
state = gst_omx_component_get_state (self->egl_render, 0);
|
||||
if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
|
||||
if (state > OMX_StateIdle) {
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
|
||||
gst_omx_component_set_state (self->dec, OMX_StateIdle);
|
||||
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||
gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
|
||||
}
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
|
||||
gst_omx_component_set_state (self->dec, OMX_StateLoaded);
|
||||
|
||||
gst_omx_port_deallocate_buffers (self->dec_in_port);
|
||||
gst_omx_video_dec_deallocate_output_buffers (self);
|
||||
gst_omx_component_close_tunnel (self->dec, self->dec_out_port,
|
||||
self->egl_render, self->egl_in_port);
|
||||
if (state > OMX_StateLoaded) {
|
||||
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||
gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise we didn't use EGL and just fall back to
|
||||
* shutting down the decoder */
|
||||
#endif
|
||||
|
||||
state = gst_omx_component_get_state (self->dec, 0);
|
||||
if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
|
||||
if (state > OMX_StateIdle) {
|
||||
|
@ -818,6 +892,14 @@ gst_omx_video_dec_close (GstVideoDecoder * decoder)
|
|||
gst_omx_component_free (self->dec);
|
||||
self->dec = NULL;
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
self->egl_in_port = NULL;
|
||||
self->egl_out_port = NULL;
|
||||
if (self->egl_render)
|
||||
gst_omx_component_free (self->egl_render);
|
||||
self->egl_render = NULL;
|
||||
#endif
|
||||
|
||||
self->started = FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Closed decoder");
|
||||
|
@ -861,6 +943,12 @@ gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
|
|||
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
|
||||
if (self->dec_out_port)
|
||||
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
if (self->egl_in_port)
|
||||
gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
|
||||
if (self->egl_out_port)
|
||||
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
|
||||
#endif
|
||||
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = FALSE;
|
||||
|
@ -948,7 +1036,7 @@ _find_nearest_frame (GstOMXVideoDec * self, GstOMXBuffer * buf)
|
|||
}
|
||||
}
|
||||
|
||||
if (best_id) {
|
||||
if (FALSE && best_id) {
|
||||
for (l = frames; l && l != best_l; l = l->next) {
|
||||
GstVideoCodecFrame *tmp = l->data;
|
||||
BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
|
||||
|
@ -978,7 +1066,7 @@ _find_nearest_frame (GstOMXVideoDec * self, GstOMXBuffer * buf)
|
|||
}
|
||||
}
|
||||
|
||||
if (finish_frames) {
|
||||
if (FALSE && finish_frames) {
|
||||
g_warning ("Too old frames, bug in decoder -- please file a bug");
|
||||
for (l = finish_frames; l; l = l->next) {
|
||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), l->data);
|
||||
|
@ -1155,13 +1243,14 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
|||
GstVideoCodecState *state =
|
||||
gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
port = self->eglimage ? self->egl_out_port : self->dec_out_port;
|
||||
#else
|
||||
port = self->dec_out_port;
|
||||
#endif
|
||||
|
||||
pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self));
|
||||
/* FIXME: Enable this once there's a way to request downstream to
|
||||
* release all our buffers, e.g.
|
||||
* http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=release-pool */
|
||||
if (FALSE && pool) {
|
||||
if (pool) {
|
||||
GstAllocator *allocator;
|
||||
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
|
@ -1182,8 +1271,13 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
|||
add_videometa = gst_buffer_pool_config_has_option (config,
|
||||
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
/* TODO: Implement something here */
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
eglimage = self->eglimage && (allocator
|
||||
&& g_strcmp0 (allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0);
|
||||
#else
|
||||
/* TODO: Implement something that works for other targets too */
|
||||
eglimage = FALSE;
|
||||
#endif
|
||||
caps = caps ? gst_caps_ref (caps) : NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Trying to use pool %p with caps %" GST_PTR_FORMAT
|
||||
|
@ -1195,11 +1289,157 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
|||
GST_DEBUG_OBJECT (self, "No pool available, not negotiated yet");
|
||||
}
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
/* Will retry without EGLImage */
|
||||
if (self->eglimage && !eglimage) {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Wanted to use EGLImage but downstream doesn't support it");
|
||||
err = OMX_ErrorUndefined;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (caps)
|
||||
self->out_port_pool =
|
||||
gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port);
|
||||
|
||||
/* TODO: Implement EGLImage handling and usage of other downstream buffers */
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
if (eglimage) {
|
||||
GList *buffers = NULL;
|
||||
GList *images = NULL;
|
||||
gint i;
|
||||
GstBufferPoolAcquireParams params = { 0, };
|
||||
GstEGLDisplay *display = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min);
|
||||
|
||||
for (i = 0; i < min; i++) {
|
||||
GstBuffer *buffer;
|
||||
GstMemory *mem;
|
||||
|
||||
if (gst_buffer_pool_acquire_buffer (pool, &buffer, ¶ms) != GST_FLOW_OK
|
||||
|| gst_buffer_n_memory (buffer) != 1
|
||||
|| !(mem = gst_buffer_peek_memory (buffer, 0))
|
||||
|| g_strcmp0 (mem->allocator->mem_type,
|
||||
GST_EGL_IMAGE_MEMORY_TYPE) != 0) {
|
||||
GST_INFO_OBJECT (self, "Failed to allocated %d-th EGLImage", i);
|
||||
g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
|
||||
g_list_free (images);
|
||||
buffers = NULL;
|
||||
images = NULL;
|
||||
if (display)
|
||||
gst_egl_display_unref (display);
|
||||
display = NULL;
|
||||
/* TODO: For non-RPi targets we want to use the normal memory code below */
|
||||
/* Retry without EGLImage */
|
||||
err = OMX_ErrorUndefined;
|
||||
goto done;
|
||||
}
|
||||
|
||||
buffers = g_list_append (buffers, buffer);
|
||||
gst_egl_image_memory_set_orientation (mem,
|
||||
GST_EGL_IMAGE_ORIENTATION_X_NORMAL_Y_FLIP);
|
||||
images = g_list_append (images, gst_egl_image_memory_get_image (mem));
|
||||
if (!display)
|
||||
display = gst_egl_image_memory_get_display (mem);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Allocated %d EGLImages successfully", min);
|
||||
|
||||
/* Everything went fine? */
|
||||
if (eglimage) {
|
||||
GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
|
||||
self->egl_out_port->port_def.format.video.pNativeWindow =
|
||||
gst_egl_display_get (display);
|
||||
err =
|
||||
gst_omx_port_update_port_definition (self->egl_out_port,
|
||||
&self->egl_out_port->port_def);
|
||||
if (display)
|
||||
gst_egl_display_unref (display);
|
||||
display = NULL;
|
||||
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;
|
||||
|
||||
if (min != port->port_def.nBufferCountActual) {
|
||||
err = gst_omx_port_update_port_definition (port, NULL);
|
||||
if (err == OMX_ErrorNone) {
|
||||
port->port_def.nBufferCountActual = min;
|
||||
err = gst_omx_port_update_port_definition (port, &port->port_def);
|
||||
}
|
||||
|
||||
if (err != OMX_ErrorNone) {
|
||||
GST_INFO_OBJECT (self,
|
||||
"Failed to configure %n output buffers: %s (0x%08x)", min,
|
||||
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 (!gst_omx_port_is_enabled (port)) {
|
||||
err = gst_omx_port_set_enabled (port, TRUE);
|
||||
if (err != OMX_ErrorNone) {
|
||||
GST_INFO_OBJECT (self,
|
||||
"Failed to enable 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;
|
||||
}
|
||||
}
|
||||
|
||||
err = gst_omx_port_use_eglimages (port, images);
|
||||
g_list_free (images);
|
||||
|
||||
if (err != OMX_ErrorNone) {
|
||||
GST_INFO_OBJECT (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;
|
||||
}
|
||||
|
||||
err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
|
||||
if (err != OMX_ErrorNone) {
|
||||
GST_INFO_OBJECT (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;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Populating internal buffer pool");
|
||||
GST_OMX_BUFFER_POOL (self->out_port_pool)->other_pool =
|
||||
GST_BUFFER_POOL (gst_object_ref (pool));
|
||||
for (l = buffers; l; l = l->next) {
|
||||
g_ptr_array_add (GST_OMX_BUFFER_POOL (self->out_port_pool)->buffers,
|
||||
l->data);
|
||||
}
|
||||
g_list_free (buffers);
|
||||
/* All good and done, set caps below */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If not using EGLImage or trying to use EGLImage failed */
|
||||
if (!eglimage) {
|
||||
|
@ -1336,11 +1576,259 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
|
|||
|
||||
if (self->out_port_pool) {
|
||||
gst_buffer_pool_set_active (self->out_port_pool, FALSE);
|
||||
gst_buffer_pool_wait_released (self->out_port_pool);
|
||||
GST_OMX_BUFFER_POOL (self->out_port_pool)->deactivated = TRUE;
|
||||
gst_object_unref (self->out_port_pool);
|
||||
self->out_port_pool = NULL;
|
||||
}
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
err =
|
||||
gst_omx_port_deallocate_buffers (self->
|
||||
eglimage ? self->egl_out_port : self->dec_out_port);
|
||||
#else
|
||||
err = gst_omx_port_deallocate_buffers (self->dec_out_port);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static OMX_ERRORTYPE
|
||||
gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
|
||||
{
|
||||
GstOMXPort *port;
|
||||
OMX_ERRORTYPE err;
|
||||
GstVideoCodecState *state;
|
||||
OMX_PARAM_PORTDEFINITIONTYPE port_def;
|
||||
GstVideoFormat format;
|
||||
|
||||
/* At this point the decoder output port is disabled */
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
{
|
||||
OMX_STATETYPE egl_state;
|
||||
|
||||
if (self->eglimage) {
|
||||
/* Nothing to do here, we could however fall back to non-EGLImage in theory */
|
||||
err = OMX_ErrorNone;
|
||||
goto enable_port;
|
||||
} else {
|
||||
/* Set up egl_render */
|
||||
|
||||
self->eglimage = TRUE;
|
||||
|
||||
gst_omx_port_get_port_definition (self->dec_out_port, &port_def);
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
|
||||
GST_VIDEO_FORMAT_RGBA, port_def.format.video.nFrameWidth,
|
||||
port_def.format.video.nFrameHeight, self->input_state);
|
||||
|
||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||
gst_video_codec_state_unref (state);
|
||||
GST_ERROR_OBJECT (self, "Failed to negotiate RGBA for EGLImage");
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
goto no_egl;
|
||||
}
|
||||
|
||||
gst_video_codec_state_unref (state);
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
|
||||
/* Now link it all together */
|
||||
|
||||
err = gst_omx_port_set_enabled (self->egl_in_port, FALSE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_set_enabled (self->egl_out_port, FALSE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_wait_enabled (self->egl_out_port, 1 * GST_SECOND);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
{
|
||||
#define OMX_IndexParamBrcmVideoEGLRenderDiscardMode 0x7f0000dc
|
||||
OMX_CONFIG_PORTBOOLEANTYPE discardMode;
|
||||
memset (&discardMode, 0, sizeof (discardMode));
|
||||
discardMode.nSize = sizeof (discardMode);
|
||||
discardMode.nPortIndex = 220;
|
||||
discardMode.nVersion.nVersion = OMX_VERSION;
|
||||
discardMode.bEnabled = OMX_FALSE;
|
||||
if (gst_omx_component_set_parameter (self->egl_render,
|
||||
OMX_IndexParamBrcmVideoEGLRenderDiscardMode,
|
||||
&discardMode) != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
#undef OMX_IndexParamBrcmVideoEGLRenderDiscardMode
|
||||
}
|
||||
|
||||
err =
|
||||
gst_omx_component_setup_tunnel (self->dec, self->dec_out_port,
|
||||
self->egl_render, self->egl_in_port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_set_enabled (self->egl_in_port, TRUE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
if (gst_omx_component_get_state (self->egl_render,
|
||||
GST_CLOCK_TIME_NONE) != OMX_StateIdle)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_video_dec_allocate_output_buffers (self);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
if (gst_omx_component_set_state (self->egl_render,
|
||||
OMX_StateExecuting) != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
if (gst_omx_component_get_state (self->egl_render,
|
||||
GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
|
||||
goto no_egl;
|
||||
|
||||
err =
|
||||
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err =
|
||||
gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err =
|
||||
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_populate (self->egl_out_port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_set_enabled (self->dec_out_port, TRUE);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
|
||||
err = gst_omx_port_mark_reconfigured (self->dec_out_port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
err = gst_omx_port_mark_reconfigured (self->egl_out_port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto no_egl;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
no_egl:
|
||||
|
||||
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);
|
||||
if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
|
||||
if (egl_state > OMX_StateIdle) {
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
|
||||
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||
}
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
|
||||
|
||||
gst_omx_video_dec_deallocate_output_buffers (self);
|
||||
gst_omx_component_close_tunnel (self->dec, self->dec_out_port,
|
||||
self->egl_render, self->egl_in_port);
|
||||
|
||||
if (egl_state > OMX_StateLoaded) {
|
||||
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
/* After this egl_render should be deactivated
|
||||
* and the decoder's output port disabled */
|
||||
self->eglimage = FALSE;
|
||||
}
|
||||
#endif
|
||||
port = self->dec_out_port;
|
||||
|
||||
/* Update caps */
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
|
||||
gst_omx_port_get_port_definition (port, &port_def);
|
||||
g_assert (port_def.format.video.eCompressionFormat == OMX_VIDEO_CodingUnused);
|
||||
|
||||
switch (port_def.format.video.eColorFormat) {
|
||||
case OMX_COLOR_FormatYUV420Planar:
|
||||
case OMX_COLOR_FormatYUV420PackedPlanar:
|
||||
GST_DEBUG_OBJECT (self, "Output is I420 (%d)",
|
||||
port_def.format.video.eColorFormat);
|
||||
format = GST_VIDEO_FORMAT_I420;
|
||||
break;
|
||||
case OMX_COLOR_FormatYUV420SemiPlanar:
|
||||
GST_DEBUG_OBJECT (self, "Output is NV12 (%d)",
|
||||
port_def.format.video.eColorFormat);
|
||||
format = GST_VIDEO_FORMAT_NV12;
|
||||
break;
|
||||
default:
|
||||
GST_ERROR_OBJECT (self, "Unsupported color format: %d",
|
||||
port_def.format.video.eColorFormat);
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
err = OMX_ErrorUndefined;
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Setting output state: format %s, width %d, height %d",
|
||||
gst_video_format_to_string (format),
|
||||
port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight);
|
||||
|
||||
state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
|
||||
format, port_def.format.video.nFrameWidth,
|
||||
port_def.format.video.nFrameHeight, self->input_state);
|
||||
|
||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||
gst_video_codec_state_unref (state);
|
||||
GST_ERROR_OBJECT (self, "Failed to negotiate");
|
||||
err = OMX_ErrorUndefined;
|
||||
goto done;
|
||||
}
|
||||
|
||||
gst_video_codec_state_unref (state);
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
enable_port:
|
||||
#endif
|
||||
err = gst_omx_video_dec_allocate_output_buffers (self);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto done;
|
||||
|
||||
err = gst_omx_port_populate (port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto done;
|
||||
|
||||
err = gst_omx_port_mark_reconfigured (port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto done;
|
||||
|
||||
done:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1348,7 +1836,7 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
|
|||
static void
|
||||
gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
||||
{
|
||||
GstOMXPort *port = self->dec_out_port;
|
||||
GstOMXPort *port;
|
||||
GstOMXBuffer *buf = NULL;
|
||||
GstVideoCodecFrame *frame;
|
||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||
|
@ -1356,6 +1844,12 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
|||
GstClockTimeDiff deadline;
|
||||
OMX_ERRORTYPE err;
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
port = self->eglimage ? self->egl_out_port : self->dec_out_port;
|
||||
#else
|
||||
port = self->dec_out_port;
|
||||
#endif
|
||||
|
||||
acq_return = gst_omx_port_acquire_buffer (port, &buf);
|
||||
if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
|
||||
goto component_error;
|
||||
|
@ -1393,68 +1887,63 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
|||
goto reconfigure_error;
|
||||
}
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
|
||||
/* We have the possibility to reconfigure everything now */
|
||||
err = gst_omx_video_dec_reconfigure_output_port (self);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto reconfigure_error;
|
||||
} else {
|
||||
/* Just update caps */
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
|
||||
gst_omx_port_get_port_definition (port, &port_def);
|
||||
g_assert (port_def.format.video.eCompressionFormat ==
|
||||
OMX_VIDEO_CodingUnused);
|
||||
gst_omx_port_get_port_definition (port, &port_def);
|
||||
g_assert (port_def.format.video.eCompressionFormat ==
|
||||
OMX_VIDEO_CodingUnused);
|
||||
|
||||
switch (port_def.format.video.eColorFormat) {
|
||||
case OMX_COLOR_FormatYUV420Planar:
|
||||
case OMX_COLOR_FormatYUV420PackedPlanar:
|
||||
GST_DEBUG_OBJECT (self, "Output is I420 (%d)",
|
||||
port_def.format.video.eColorFormat);
|
||||
format = GST_VIDEO_FORMAT_I420;
|
||||
break;
|
||||
case OMX_COLOR_FormatYUV420SemiPlanar:
|
||||
GST_DEBUG_OBJECT (self, "Output is NV12 (%d)",
|
||||
port_def.format.video.eColorFormat);
|
||||
format = GST_VIDEO_FORMAT_NV12;
|
||||
break;
|
||||
default:
|
||||
GST_ERROR_OBJECT (self, "Unsupported color format: %d",
|
||||
port_def.format.video.eColorFormat);
|
||||
switch (port_def.format.video.eColorFormat) {
|
||||
case OMX_COLOR_FormatYUV420Planar:
|
||||
case OMX_COLOR_FormatYUV420PackedPlanar:
|
||||
GST_DEBUG_OBJECT (self, "Output is I420 (%d)",
|
||||
port_def.format.video.eColorFormat);
|
||||
format = GST_VIDEO_FORMAT_I420;
|
||||
break;
|
||||
case OMX_COLOR_FormatYUV420SemiPlanar:
|
||||
GST_DEBUG_OBJECT (self, "Output is NV12 (%d)",
|
||||
port_def.format.video.eColorFormat);
|
||||
format = GST_VIDEO_FORMAT_NV12;
|
||||
break;
|
||||
default:
|
||||
GST_ERROR_OBJECT (self, "Unsupported color format: %d",
|
||||
port_def.format.video.eColorFormat);
|
||||
if (buf)
|
||||
gst_omx_port_release_buffer (self->dec_out_port, buf);
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
goto caps_failed;
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Setting output state: format %s, width %d, height %d",
|
||||
gst_video_format_to_string (format),
|
||||
port_def.format.video.nFrameWidth,
|
||||
port_def.format.video.nFrameHeight);
|
||||
|
||||
state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
|
||||
format, port_def.format.video.nFrameWidth,
|
||||
port_def.format.video.nFrameHeight, self->input_state);
|
||||
|
||||
/* Take framerate and pixel-aspect-ratio from sinkpad caps */
|
||||
|
||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||
if (buf)
|
||||
gst_omx_port_release_buffer (self->dec_out_port, buf);
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
gst_video_codec_state_unref (state);
|
||||
goto caps_failed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Setting output state: format %s, width %d, height %d",
|
||||
gst_video_format_to_string (format),
|
||||
port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight);
|
||||
|
||||
state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
|
||||
format, port_def.format.video.nFrameWidth,
|
||||
port_def.format.video.nFrameHeight, self->input_state);
|
||||
|
||||
/* Take framerate and pixel-aspect-ratio from sinkpad caps */
|
||||
|
||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||
if (buf)
|
||||
gst_omx_port_release_buffer (self->dec_out_port, buf);
|
||||
gst_video_codec_state_unref (state);
|
||||
goto caps_failed;
|
||||
}
|
||||
|
||||
gst_video_codec_state_unref (state);
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
|
||||
if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
|
||||
err = gst_omx_video_dec_allocate_output_buffers (self);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto reconfigure_error;
|
||||
|
||||
err = gst_omx_port_populate (port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto reconfigure_error;
|
||||
|
||||
err = gst_omx_port_mark_reconfigured (port);
|
||||
if (err != OMX_ErrorNone)
|
||||
goto reconfigure_error;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
}
|
||||
|
||||
/* Now get a buffer */
|
||||
|
@ -1489,7 +1978,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
|||
GST_TIME_ARGS (-deadline));
|
||||
flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||
frame = NULL;
|
||||
} else if (!frame && buf->omx_buf->nFilledLen > 0) {
|
||||
} else if (!frame && (buf->omx_buf->nFilledLen > 0 || buf->eglimage)) {
|
||||
GstBuffer *outbuf;
|
||||
|
||||
/* This sometimes happens at EOS or if the input is not properly framed,
|
||||
|
@ -1532,7 +2021,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
|||
}
|
||||
|
||||
flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
|
||||
} else if (buf->omx_buf->nFilledLen > 0) {
|
||||
} else if (buf->omx_buf->nFilledLen > 0 || buf->eglimage) {
|
||||
if (self->out_port_pool) {
|
||||
gint i, n;
|
||||
GstBufferPoolAcquireParams params = { 0, };
|
||||
|
@ -1748,10 +2237,19 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder)
|
|||
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
|
||||
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
|
||||
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
|
||||
#endif
|
||||
|
||||
gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
|
||||
|
||||
if (gst_omx_component_get_state (self->dec, 0) > OMX_StateIdle)
|
||||
gst_omx_component_set_state (self->dec, OMX_StateIdle);
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
if (gst_omx_component_get_state (self->egl_render, 0) > OMX_StateIdle)
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
|
||||
#endif
|
||||
|
||||
self->downstream_flow_ret = GST_FLOW_FLUSHING;
|
||||
self->started = FALSE;
|
||||
|
@ -1763,6 +2261,9 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder)
|
|||
g_mutex_unlock (&self->drain_lock);
|
||||
|
||||
gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
gst_omx_component_get_state (self->egl_render, 1 * GST_SECOND);
|
||||
#endif
|
||||
|
||||
gst_buffer_replace (&self->codec_data, NULL);
|
||||
|
||||
|
@ -1790,12 +2291,17 @@ video_negotiation_map_free (VideoNegotiationMap * m)
|
|||
static GList *
|
||||
gst_omx_video_dec_get_supported_colorformats (GstOMXVideoDec * self)
|
||||
{
|
||||
GstOMXPort *port = self->dec_out_port;
|
||||
GstOMXComponent *comp;
|
||||
GstOMXPort *port;
|
||||
GstVideoCodecState *state = self->input_state;
|
||||
OMX_VIDEO_PARAM_PORTFORMATTYPE param;
|
||||
OMX_ERRORTYPE err;
|
||||
GList *negotiation_map = NULL;
|
||||
gint old_index;
|
||||
VideoNegotiationMap *m;
|
||||
|
||||
port = self->dec_out_port;
|
||||
comp = self->dec;
|
||||
|
||||
GST_OMX_INIT_STRUCT (¶m);
|
||||
param.nPortIndex = port->index;
|
||||
|
@ -1807,10 +2313,8 @@ gst_omx_video_dec_get_supported_colorformats (GstOMXVideoDec * self)
|
|||
|
||||
old_index = -1;
|
||||
do {
|
||||
VideoNegotiationMap *m;
|
||||
|
||||
err =
|
||||
gst_omx_component_get_parameter (self->dec,
|
||||
gst_omx_component_get_parameter (comp,
|
||||
OMX_IndexParamVideoPortFormat, ¶m);
|
||||
|
||||
/* FIXME: Workaround for Bellagio that simply always
|
||||
|
@ -1997,10 +2501,17 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
|
|||
}
|
||||
|
||||
if (needs_disable && is_format_change) {
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
GstOMXPort *out_port =
|
||||
self->eglimage ? self->egl_out_port : self->dec_out_port;
|
||||
#else
|
||||
GstOMXPort *out_port = self->dec_out_port;
|
||||
#endif
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
|
||||
|
||||
gst_omx_video_dec_drain (self, FALSE);
|
||||
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
|
||||
gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
|
||||
|
||||
/* Wait until the srcpad loop is finished,
|
||||
* unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
|
||||
|
@ -2019,26 +2530,82 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
|
|||
return FALSE;
|
||||
needs_disable = FALSE;
|
||||
} else {
|
||||
if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_buffers_released (self->dec_in_port,
|
||||
5 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_buffers_released (self->dec_out_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_video_dec_deallocate_output_buffers (self) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_enabled (self->dec_in_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_enabled (self->dec_out_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
if (self->eglimage) {
|
||||
OMX_STATETYPE egl_state;
|
||||
|
||||
if (gst_omx_port_set_enabled (self->dec_in_port,
|
||||
FALSE) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_port_set_enabled (self->dec_out_port,
|
||||
FALSE) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_port_wait_buffers_released (self->dec_in_port,
|
||||
5 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_port_wait_buffers_released (self->dec_out_port,
|
||||
5 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_port_deallocate_buffers (self->dec_in_port) !=
|
||||
OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_port_wait_enabled (self->dec_in_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
if (gst_omx_port_wait_enabled (self->dec_out_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
|
||||
egl_state = gst_omx_component_get_state (self->egl_render, 0);
|
||||
if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
|
||||
if (egl_state > OMX_StateIdle) {
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
|
||||
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||
}
|
||||
gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
|
||||
|
||||
gst_omx_video_dec_deallocate_output_buffers (self);
|
||||
gst_omx_component_close_tunnel (self->dec, self->dec_out_port,
|
||||
self->egl_render, self->egl_in_port);
|
||||
|
||||
if (egl_state > OMX_StateLoaded) {
|
||||
gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
|
||||
}
|
||||
}
|
||||
self->eglimage = FALSE;
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
if (gst_omx_port_set_enabled (self->dec_in_port,
|
||||
FALSE) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_buffers_released (self->dec_in_port,
|
||||
5 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_buffers_released (out_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_deallocate_buffers (self->dec_in_port) !=
|
||||
OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_video_dec_deallocate_output_buffers (self) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_enabled (self->dec_in_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
if (gst_omx_port_wait_enabled (out_port,
|
||||
1 * GST_SECOND) != OMX_ErrorNone)
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
@ -2154,6 +2721,11 @@ gst_omx_video_dec_reset (GstVideoDecoder * decoder, gboolean hard)
|
|||
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
|
||||
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
|
||||
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
|
||||
#endif
|
||||
|
||||
/* Wait until the srcpad loop is finished,
|
||||
* unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
|
||||
* caused by using this lock from inside the loop function */
|
||||
|
@ -2166,6 +2738,11 @@ gst_omx_video_dec_reset (GstVideoDecoder * decoder, gboolean hard)
|
|||
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
|
||||
gst_omx_port_populate (self->dec_out_port);
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
|
||||
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
|
||||
#endif
|
||||
|
||||
/* Start the srcpad loop again */
|
||||
self->last_upstream_ts = 0;
|
||||
self->eos = FALSE;
|
||||
|
@ -2567,6 +3144,35 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
|
|||
GstBufferPool *pool;
|
||||
GstStructure *config;
|
||||
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
{
|
||||
GstCaps *caps;
|
||||
gint i, n;
|
||||
GstVideoInfo info;
|
||||
|
||||
gst_query_parse_allocation (query, &caps, NULL);
|
||||
if (caps && gst_video_info_from_caps (&info, caps)
|
||||
&& info.finfo->format == GST_VIDEO_FORMAT_RGBA) {
|
||||
/* Prefer an EGLImage allocator if available and we want to use it */
|
||||
n = gst_query_get_n_allocation_params (query);
|
||||
for (i = 0; i < n; i++) {
|
||||
GstAllocator *allocator;
|
||||
GstAllocationParams params;
|
||||
|
||||
gst_query_parse_nth_allocation_param (query, i, &allocator, ¶ms);
|
||||
if (allocator
|
||||
&& g_strcmp0 (allocator->mem_type,
|
||||
GST_EGL_IMAGE_MEMORY_TYPE) == 0) {
|
||||
gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
|
||||
while (gst_query_get_n_allocation_params (query) > 1)
|
||||
gst_query_remove_nth_allocation_param (query, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!GST_VIDEO_DECODER_CLASS
|
||||
(gst_omx_video_dec_parent_class)->decide_allocation (bdec, query))
|
||||
return FALSE;
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
#ifndef __GST_OMX_VIDEO_DEC_H__
|
||||
#define __GST_OMX_VIDEO_DEC_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/gstvideodecoder.h>
|
||||
|
@ -52,7 +56,7 @@ struct _GstOMXVideoDec
|
|||
/* < protected > */
|
||||
GstOMXComponent *dec;
|
||||
GstOMXPort *dec_in_port, *dec_out_port;
|
||||
|
||||
|
||||
GstBufferPool *in_port_pool, *out_port_pool;
|
||||
|
||||
/* < private > */
|
||||
|
@ -74,6 +78,11 @@ struct _GstOMXVideoDec
|
|||
gboolean eos;
|
||||
|
||||
GstFlowReturn downstream_flow_ret;
|
||||
#ifdef USE_OMX_TARGET_RPI
|
||||
GstOMXComponent *egl_render;
|
||||
GstOMXPort *egl_in_port, *egl_out_port;
|
||||
gboolean eglimage;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _GstOMXVideoDecClass
|
||||
|
|
Loading…
Reference in a new issue