aboutsummaryrefslogtreecommitdiffstats
path: root/meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch')
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch328
1 files changed, 328 insertions, 0 deletions
diff --git a/meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch b/meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch
new file mode 100644
index 00000000..aa3e403f
--- /dev/null
+++ b/meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch
@@ -0,0 +1,328 @@
+From 17e9d641799a075a085a64d0543c5a51b11fd73d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 13 Sep 2013 03:33:19 -0600
+Subject: [PATCH 06/11] omx: add tunneling support between decoder and
+ encoders v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Forward the frames through both the OMX tunnel as well as the gst pad, this
+way we can map OMX buffers to their frame counterpart when they left the
+tunnel on the other side.
+
+v2: fix tunnel close and buffer dealloc order
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ omx/gstomx.c | 6 +++-
+ omx/gstomx.h | 2 ++
+ omx/gstomxvideodec.c | 90 ++++++++++++++++++++++++++++++++++++++++++++------
+ omx/gstomxvideoenc.c | 29 +++++++++++++---
+ 4 files changed, 110 insertions(+), 17 deletions(-)
+
+diff --git a/omx/gstomx.c b/omx/gstomx.c
+index c8a8927..df3a8ff 100644
+--- a/omx/gstomx.c
++++ b/omx/gstomx.c
+@@ -1204,7 +1204,6 @@ gst_omx_port_acquire_buffer (GstOMXPort * port, GstOMXBuffer ** buf)
+ GstOMXBuffer *_buf = NULL;
+
+ g_return_val_if_fail (port != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
+- g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR);
+ g_return_val_if_fail (buf != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
+
+ *buf = NULL;
+@@ -1298,6 +1297,11 @@ retry:
+ goto done;
+ }
+
++ if (port->tunneled) {
++ ret = GST_OMX_ACQUIRE_BUFFER_TUNNELED;
++ goto done;
++ }
++
+ /*
+ * At this point we have no error or flushing/eos port
+ * and a properly configured port.
+diff --git a/omx/gstomx.h b/omx/gstomx.h
+index 3645b63..9b534bd 100644
+--- a/omx/gstomx.h
++++ b/omx/gstomx.h
+@@ -124,6 +124,8 @@ typedef enum {
+ GST_OMX_ACQUIRE_BUFFER_RECONFIGURE,
+ /* The port is EOS */
+ GST_OMX_ACQUIRE_BUFFER_EOS,
++ /* The port is tunneled */
++ GST_OMX_ACQUIRE_BUFFER_TUNNELED,
+ /* A fatal error happened */
+ GST_OMX_ACQUIRE_BUFFER_ERROR
+ } GstOMXAcquireBufferReturn;
+diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
+index 020b7d3..e8813fb 100644
+--- a/omx/gstomxvideodec.c
++++ b/omx/gstomxvideodec.c
+@@ -50,6 +50,7 @@
+ #include <string.h>
+
+ #include "gstomxvideodec.h"
++#include "gstomxvideoenc.h"
+
+ GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
+ #define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
+@@ -881,6 +882,11 @@ gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+ }
+
++ if (self->dec_out_port->tunneled) {
++ gst_omx_component_close_tunnel (self->dec, self->dec_out_port,
++ self->dec_out_port->tunneled->comp, self->dec_out_port->tunneled);
++ }
++
+ return TRUE;
+ }
+
+@@ -1527,7 +1533,7 @@ done:
+ static OMX_ERRORTYPE
+ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
+ {
+- OMX_ERRORTYPE err;
++ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ if (self->out_port_pool) {
+ gst_buffer_pool_set_active (self->out_port_pool, FALSE);
+@@ -1543,7 +1549,10 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
+ 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);
++ if (!self->dec_out_port->tunneled)
++ err = gst_omx_port_deallocate_buffers (self->dec_out_port);
++ else
++ err = gst_omx_port_set_enabled (self->dec_out_port, FALSE);
+ #endif
+
+ return err;
+@@ -1772,12 +1781,28 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
+
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
++ {
++ GstPad *peer = gst_pad_get_peer (GST_VIDEO_DECODER_SRC_PAD (self));
++ GstElement *element = peer ? gst_pad_get_parent_element (peer) : NULL;
++
++ if (element && GST_IS_OMX_VIDEO_ENC (element)) {
++ GstOMXVideoEnc *enc = GST_OMX_VIDEO_ENC (element);
++
++ gst_omx_component_setup_tunnel (self->dec, self->dec_out_port,
++ enc->enc, enc->enc_in_port);
++
++ }
++ }
++
+ #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_EGL)
+ enable_port:
+ #endif
+- err = gst_omx_video_dec_allocate_output_buffers (self);
+- if (err != OMX_ErrorNone)
+- goto done;
++
++ if (!self->dec_out_port->tunneled) {
++ 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)
+@@ -1816,6 +1841,9 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
+ goto flushing;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
+ goto eos;
++ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_TUNNELED) {
++ gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
++ return;
+ }
+
+ if (!gst_pad_has_current_caps (GST_VIDEO_DECODER_SRC_PAD (self)) ||
+@@ -2657,6 +2685,7 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
+ GST_DEBUG_OBJECT (self, "Starting task again");
+
+ self->downstream_flow_ret = GST_FLOW_OK;
++
+ gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
+
+@@ -2703,6 +2732,7 @@ gst_omx_video_dec_reset (GstVideoDecoder * decoder, gboolean hard)
+ self->last_upstream_ts = 0;
+ self->eos = FALSE;
+ self->downstream_flow_ret = GST_FLOW_OK;
++
+ gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
+
+@@ -2925,7 +2955,11 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
+ goto release_error;
+ }
+
+- gst_video_codec_frame_unref (frame);
++ if (self->dec_out_port->tunneled) {
++ frame->output_buffer = gst_buffer_new ();
++ gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
++ } else
++ gst_video_codec_frame_unref (frame);
+
+ GST_DEBUG_OBJECT (self, "Passed frame to component");
+
+@@ -3003,6 +3037,7 @@ gst_omx_video_dec_finish (GstVideoDecoder * decoder)
+ static GstFlowReturn
+ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
+ {
++ GstOMXVideoEnc *enc = NULL;
+ GstOMXVideoDecClass *klass;
+ GstOMXBuffer *buf;
+ GstOMXAcquireBufferReturn acq_ret;
+@@ -3031,6 +3066,14 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
+ return GST_FLOW_OK;
+ }
+
++ if (self->dec_out_port->tunneled) {
++ GstPad *peer = gst_pad_get_peer (GST_VIDEO_DECODER_SRC_PAD (self));
++ GstElement *element = peer ? gst_pad_get_parent_element (peer) : NULL;
++
++ if (element && GST_IS_OMX_VIDEO_ENC (element))
++ enc = GST_OMX_VIDEO_ENC (element);
++ }
++
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+@@ -3047,8 +3090,14 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
+ return GST_FLOW_ERROR;
+ }
+
+- g_mutex_lock (&self->drain_lock);
+- self->draining = TRUE;
++ if (enc) {
++ g_mutex_lock (&enc->drain_lock);
++ enc->draining = TRUE;
++ } else {
++ g_mutex_lock (&self->drain_lock);
++ self->draining = TRUE;
++ }
++
+ buf->omx_buf->nFilledLen = 0;
+ buf->omx_buf->nTimeStamp =
+ gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
+@@ -3059,6 +3108,10 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
++ if (enc)
++ g_mutex_unlock (&enc->drain_lock);
++ else
++ g_mutex_unlock (&self->drain_lock);
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ return GST_FLOW_ERROR;
+ }
+@@ -3067,18 +3120,33 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
+
+ if (G_UNLIKELY (self->dec->hacks & GST_OMX_HACK_DRAIN_MAY_NOT_RETURN)) {
+ gint64 wait_until = g_get_monotonic_time () + G_TIME_SPAN_SECOND / 2;
++ gboolean result;
++
++ if (enc)
++ result =
++ g_cond_wait_until (&enc->drain_cond, &enc->drain_lock, wait_until);
++ else
++ result =
++ g_cond_wait_until (&self->drain_cond, &self->drain_lock, wait_until);
+
+- if (!g_cond_wait_until (&self->drain_cond, &self->drain_lock, wait_until))
++ if (!result)
+ GST_WARNING_OBJECT (self, "Drain timed out");
+ else
+ GST_DEBUG_OBJECT (self, "Drained component");
+
+ } else {
+- g_cond_wait (&self->drain_cond, &self->drain_lock);
++ if (enc)
++ g_cond_wait (&enc->drain_cond, &enc->drain_lock);
++ else
++ g_cond_wait (&self->drain_cond, &self->drain_lock);
+ GST_DEBUG_OBJECT (self, "Drained component");
+ }
+
+- g_mutex_unlock (&self->drain_lock);
++ if (enc)
++ g_mutex_unlock (&enc->drain_lock);
++ else
++ g_mutex_unlock (&self->drain_lock);
++
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ self->started = FALSE;
+diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
+index 3a139bb..8f6cab3 100644
+--- a/omx/gstomxvideoenc.c
++++ b/omx/gstomxvideoenc.c
+@@ -364,7 +364,10 @@ gst_omx_video_enc_shutdown (GstOMXVideoEnc * self)
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->enc, OMX_StateLoaded);
+- gst_omx_port_deallocate_buffers (self->enc_in_port);
++ if (!self->enc_in_port->tunneled)
++ gst_omx_port_deallocate_buffers (self->enc_in_port);
++ else
++ gst_omx_port_set_enabled (self->enc_in_port, FALSE);
+ gst_omx_port_deallocate_buffers (self->enc_out_port);
+ if (state > OMX_StateLoaded)
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+@@ -1086,8 +1089,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
+ if (gst_omx_port_wait_buffers_released (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+- if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+- return FALSE;
++ if (!self->enc_in_port->tunneled)
++ if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
++ return FALSE;
+ if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->enc_in_port,
+@@ -1225,8 +1229,18 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+- if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+- return FALSE;
++ if (self->enc_in_port->tunneled) {
++ if (gst_omx_port_set_enabled (self->enc_in_port->tunneled,
++ TRUE) != OMX_ErrorNone)
++ return FALSE;
++
++ if (gst_omx_port_wait_enabled (self->enc_in_port->tunneled,
++ 1 * GST_SECOND) != OMX_ErrorNone)
++ return FALSE;
++ } else {
++ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
++ return FALSE;
++ }
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+@@ -1492,6 +1506,11 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
+
+ port = self->enc_in_port;
+
++ if (port->tunneled) {
++ gst_video_codec_frame_unref (frame);
++ return self->downstream_flow_ret;
++ }
++
+ while (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+ GstClockTime timestamp, duration;
+
+--
+1.7.9.5
+