From a390559120f53df63df8897703250a96106a889a Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Tue, 7 Feb 2017 15:01:57 +0530 Subject: [PATCH 23/24] omxvideodec : Added ip-mode and op-mode property Added below properties for decoder : ip-mode = 0 : Default workflow (memcopy involved) ip-mode = 1 : Zero copy mode (No copy from GstBuffer to GstOMXBuffer) op-mode = 0 : Default workflow (memcopy involved) op-mode = 1 : DMA Export (omx decoder will export DMA buffer) Signed-off-by: Devarsh Thakkar Upstream Status: Pending --- omx/gstomxvideodec.c | 218 +++++++++++++++++++++++++++++++++++++++++---------- omx/gstomxvideodec.h | 103 +++++++++++++++--------- 2 files changed, 240 insertions(+), 81 deletions(-) diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index 195f676..0c9a13e 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -88,9 +88,23 @@ static OMX_ERRORTYPE gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * static OMX_ERRORTYPE gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self); +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS +static void +gst_omx_video_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +static void +gst_omx_video_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +#endif + enum { - PROP_0 + PROP_0, +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + PROP_IP_MODE, + PROP_OP_MODE, +#endif }; /* class initialization */ @@ -103,6 +117,46 @@ enum G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoDec, gst_omx_video_dec, GST_TYPE_VIDEO_DECODER, DEBUG_INIT); +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + +#define DEFAULT_PROP_IP_MODE GST_OMX_DEC_IP_DEFAULT +#define DEFAULT_PROP_OP_MODE GST_OMX_DEC_OP_DEFAULT + +GType +gst_omx_dec_ip_mode_get_type (void) +{ + static GType omx_dec_ip_mode = 0; + + if (!omx_dec_ip_mode) { + static const GEnumValue ip_modes[] = { + {GST_OMX_DEC_IP_DEFAULT, "Default Mode", "default"}, + {GST_OMX_DEC_IP_ZERO_COPY, "No copy from GstBuffer to GstOMXBuffer", + "zerocopy"}, + {0, NULL, NULL} + }; + omx_dec_ip_mode = g_enum_register_static ("GstOMXDecIpMode", ip_modes); + } + return omx_dec_ip_mode; +} + +GType +gst_omx_dec_op_mode_get_type (void) +{ + static GType omx_dec_op_mode = 0; + + if (!omx_dec_op_mode) { + static const GEnumValue op_modes[] = { + {GST_OMX_DEC_OP_DEFAULT, "Default Mode", "default"}, + {GST_OMX_DEC_OP_DMA_EXPORT, "Export output as DMA buffer", "dma-export"}, + {0, NULL, NULL} + }; + omx_dec_op_mode = g_enum_register_static ("GstOMXDecOpMode", op_modes); + } + return omx_dec_op_mode; +} +#endif + + static void gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass) { @@ -112,6 +166,24 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass) gobject_class->finalize = gst_omx_video_dec_finalize; +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + gobject_class->set_property = gst_omx_video_dec_set_property; + gobject_class->get_property = gst_omx_video_dec_get_property; + + g_object_class_install_property (gobject_class, PROP_IP_MODE, + g_param_spec_enum ("ip-mode", "Input mode", + "Decoder input mode", + GST_TYPE_OMX_DEC_IP_MODE, + DEFAULT_PROP_IP_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_OP_MODE, + g_param_spec_enum ("op-mode", "Output mode", + "Decoder output mode", + GST_TYPE_OMX_DEC_OP_MODE, + DEFAULT_PROP_OP_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + +#endif + element_class->change_state = GST_DEBUG_FUNCPTR (gst_omx_video_dec_change_state); @@ -139,6 +211,7 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass) "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE; } + static void gst_omx_video_dec_init (GstOMXVideoDec * self) { @@ -160,7 +233,7 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder) OMX_VIDEO_PARAM_ENABLEBOARD enable_board; OMX_VIDEO_PARAM_ENABLEDMABUFFER enable_dmabuf; OMX_VIDEO_PARAM_ENABLEMCU enable_mcu; - static int use_dmabuf = 1, use_mcu = 1, use_board = 0; + static int use_dmabuf = 0, use_mcu = 1, use_board = 0; #endif GST_DEBUG_OBJECT (self, "Opening decoder"); @@ -214,18 +287,20 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder) enable_board.bEnable = use_board; OMX_SetParameter (self->dec->handle, type, &enable_board); - OMX_GetExtensionIndex (self->dec->handle, - (OMX_STRING) "OMX.allegro.linux.enableDMA", &DMAtype); - - memset (&enable_dmabuf, 0, sizeof (enable_dmabuf)); - enable_dmabuf.nSize = sizeof (enable_dmabuf); - enable_dmabuf.nVersion.s.nVersionMajor = OMXIL_MAJOR_VERSION; - enable_dmabuf.nVersion.s.nVersionMinor = OMXIL_MINOR_VERSION; - enable_dmabuf.nVersion.s.nRevision = OMXIL_REVISION; - enable_dmabuf.nVersion.s.nStep = OMXIL_STEP; - enable_dmabuf.bEnable = (OMX_BOOL) use_dmabuf; - enable_dmabuf.nPortIndex = 1; - OMX_SetParameter (self->dec->handle, DMAtype, &enable_dmabuf); + if (self->op_mode == GST_OMX_DEC_OP_DMA_EXPORT) { + OMX_GetExtensionIndex (self->dec->handle, + (OMX_STRING) "OMX.allegro.linux.enableDMA", &DMAtype); + use_dmabuf = 1; + memset (&enable_dmabuf, 0, sizeof (enable_dmabuf)); + enable_dmabuf.nSize = sizeof (enable_dmabuf); + enable_dmabuf.nVersion.s.nVersionMajor = OMXIL_MAJOR_VERSION; + enable_dmabuf.nVersion.s.nVersionMinor = OMXIL_MINOR_VERSION; + enable_dmabuf.nVersion.s.nRevision = OMXIL_REVISION; + enable_dmabuf.nVersion.s.nStep = OMXIL_STEP; + enable_dmabuf.bEnable = (OMX_BOOL) use_dmabuf; + enable_dmabuf.nPortIndex = 1; + OMX_SetParameter (self->dec->handle, DMAtype, &enable_dmabuf); + } OMX_GetExtensionIndex (self->dec->handle, (OMX_STRING) "OMX.allegro.enableMCU", &MCUtype); @@ -1887,10 +1962,12 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder, gboolean is_format_change = FALSE; gboolean needs_disable = FALSE; OMX_PARAM_PORTDEFINITIONTYPE port_def; +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS GList *buffer_list = NULL; GstMapInfo map_info; GstBuffer *mem = NULL; gint i; +#endif self = GST_OMX_VIDEO_DEC (decoder); klass = GST_OMX_VIDEO_DEC_GET_CLASS (decoder); @@ -2098,32 +2175,41 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder, OMX_StateIdle) != OMX_ErrorNone) return FALSE; +#if !defined (USE_OMX_TARGET_ZYNQ_USCALE_PLUS) + + if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone) + return FALSE; + +#else /* Need to allocate buffers to reach Idle state */ + if (self->ip_mode == GST_OMX_DEC_IP_DEFAULT) { + if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone) + return FALSE; + } /* Moving from OMX_AllocateBuffers to OMX_UseBuffers, Idea is to give address of GstBuffer's data received from previos element in pipeline to GstOMXBuffer's data pointer. But at _set_format stage we do not have those GstBuffer So below is hack of dummpy memory for OMX component initializing */ + if (self->ip_mode == GST_OMX_DEC_IP_ZERO_COPY) { + mem = gst_buffer_new_allocate (NULL, 1024, NULL); + gst_buffer_map (mem, &map_info, GST_MAP_READ); - /* if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone) - return FALSE; */ + gst_omx_port_update_port_definition (self->dec_in_port, NULL); - mem = gst_buffer_new_allocate (NULL, 1024, NULL); - gst_buffer_map (mem, &map_info, GST_MAP_READ); + for (i = 0; i < self->dec_in_port->port_def.nBufferCountActual; i++) + buffer_list = g_list_append (buffer_list, map_info.data); - gst_omx_port_update_port_definition (self->dec_in_port, NULL); + if (gst_omx_port_use_buffers (self->dec_in_port, + buffer_list) != OMX_ErrorNone) + return FALSE; - for (i = 0; i < self->dec_in_port->port_def.nBufferCountActual; i++) - buffer_list = g_list_append (buffer_list, map_info.data); - - if (gst_omx_port_use_buffers (self->dec_in_port, - buffer_list) != OMX_ErrorNone) - return FALSE; - - gst_buffer_unmap (mem, &map_info); - gst_buffer_unref (mem); - g_list_free (buffer_list); + gst_buffer_unmap (mem, &map_info); + gst_buffer_unref (mem); + g_list_free (buffer_list); + } +#endif if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone) return FALSE; @@ -2425,24 +2511,31 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder, buf->omx_buf->nFilledLen = MIN (size - offset, buf->omx_buf->nAllocLen - buf->omx_buf->nOffset); +#if !defined(USE_OMX_TARGET_ZYNQ_USCALE_PLUS) + gst_buffer_extract (frame->input_buffer, offset, + buf->omx_buf->pBuffer + buf->omx_buf->nOffset, + buf->omx_buf->nFilledLen); +#else + if (self->ip_mode == GST_OMX_DEC_IP_DEFAULT) { + gst_buffer_extract (frame->input_buffer, offset, + buf->omx_buf->pBuffer + buf->omx_buf->nOffset, + buf->omx_buf->nFilledLen); + } /* Instead of copying GstOMXBuffer to GstBuffer, Updating data pointer of GstOMXBuffer with GstBuffer data pointer */ - /* gst_buffer_extract (frame->input_buffer, offset, - buf->omx_buf->pBuffer + buf->omx_buf->nOffset, - buf->omx_buf->nFilledLen); */ - - GstMapInfo map = GST_MAP_INFO_INIT; + if (self->ip_mode == GST_OMX_DEC_IP_ZERO_COPY) { + GstMapInfo map = GST_MAP_INFO_INIT; - if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) { - GST_ERROR_OBJECT (self, "Failed to map input buffer"); + if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) { + GST_ERROR_OBJECT (self, "Failed to map input buffer"); + } + buf->omx_buf->pBuffer = map.data; + gst_buffer_unmap (frame->input_buffer, &map); + gst_buffer_ref (frame->input_buffer); + buf->input_buffer = frame->input_buffer; } - buf->omx_buf->pBuffer = map.data; - gst_buffer_unmap (frame->input_buffer, &map); - gst_buffer_ref (frame->input_buffer); - buf->input_buffer = frame->input_buffer; - - +#endif if (timestamp != GST_CLOCK_TIME_NONE) { buf->omx_buf->nTimeStamp = gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND); @@ -2704,3 +2797,44 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) return TRUE; } + +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS +static void +gst_omx_video_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object); + + switch (prop_id) { + case PROP_IP_MODE: + { + self->ip_mode = g_value_get_enum (value); + break; + } + case PROP_OP_MODE: + self->op_mode = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_omx_video_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object); + switch (prop_id) { + case PROP_IP_MODE: + g_value_set_enum (value, self->ip_mode); + break; + case PROP_OP_MODE: + g_value_set_enum (value, self->op_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} +#endif diff --git a/omx/gstomxvideodec.h b/omx/gstomxvideodec.h index 3978865..d54235f 100644 --- a/omx/gstomxvideodec.h +++ b/omx/gstomxvideodec.h @@ -32,7 +32,6 @@ #include "gstomx.h" G_BEGIN_DECLS - #define GST_TYPE_OMX_VIDEO_DEC \ (gst_omx_video_dec_get_type()) #define GST_OMX_VIDEO_DEC(obj) \ @@ -45,59 +44,85 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_VIDEO_DEC)) #define GST_IS_OMX_VIDEO_DEC_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VIDEO_DEC)) - typedef struct _GstOMXVideoDec GstOMXVideoDec; typedef struct _GstOMXVideoDecClass GstOMXVideoDecClass; -struct _GstOMXVideoDec -{ - GstVideoDecoder parent; +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS +#define GST_TYPE_OMX_DEC_IP_MODE (gst_omx_dec_ip_mode_get_type ()) +#define GST_TYPE_OMX_DEC_OP_MODE (gst_omx_dec_op_mode_get_type ()) + +GType gst_omx_dec_ip_mode_get_type (void); +GType gst_omx_dec_op_mode_get_type (void); + + typedef enum + { + GST_OMX_DEC_IP_DEFAULT = 0, + GST_OMX_DEC_IP_ZERO_COPY = 1, + } GstOMXDecIpMode; + + typedef enum + { + GST_OMX_DEC_OP_DEFAULT = 0, + GST_OMX_DEC_OP_DMA_EXPORT = 1, + } GstOMXDecOpMode; +#endif - /* < protected > */ - GstOMXComponent *dec; - GstOMXPort *dec_in_port, *dec_out_port; - - GstBufferPool *in_port_pool, *out_port_pool; + struct _GstOMXVideoDec + { + GstVideoDecoder parent; - /* < private > */ - GstVideoCodecState *input_state; - GstBuffer *codec_data; - /* TRUE if the component is configured and saw - * the first buffer */ - gboolean started; + /* < protected > */ + GstOMXComponent *dec; + GstOMXPort *dec_in_port, *dec_out_port; - GstClockTime last_upstream_ts; + GstBufferPool *in_port_pool, *out_port_pool; - /* Draining state */ - GMutex drain_lock; - GCond drain_cond; - /* TRUE if EOS buffers shouldn't be forwarded */ - gboolean draining; + /* < private > */ + GstVideoCodecState *input_state; + GstBuffer *codec_data; + /* TRUE if the component is configured and saw + * the first buffer */ + gboolean started; - /* TRUE if upstream is EOS */ - gboolean eos; + GstClockTime last_upstream_ts; - GstFlowReturn downstream_flow_ret; + /* Draining state */ + GMutex drain_lock; + GCond drain_cond; + /* TRUE if EOS buffers shouldn't be forwarded */ + gboolean draining; + + /* TRUE if upstream is EOS */ + gboolean eos; + + GstFlowReturn downstream_flow_ret; #ifdef USE_OMX_TARGET_RPI - GstOMXComponent *egl_render; - GstOMXPort *egl_in_port, *egl_out_port; - gboolean eglimage; + GstOMXComponent *egl_render; + GstOMXPort *egl_in_port, *egl_out_port; + gboolean eglimage; #endif -}; -struct _GstOMXVideoDecClass -{ - GstVideoDecoderClass parent_class; +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + GstOMXDecIpMode ip_mode; + GstOMXDecOpMode op_mode; +#endif + }; - GstOMXClassData cdata; + struct _GstOMXVideoDecClass + { + GstVideoDecoderClass parent_class; - gboolean (*is_format_change) (GstOMXVideoDec * self, GstOMXPort * port, GstVideoCodecState * state); - gboolean (*set_format) (GstOMXVideoDec * self, GstOMXPort * port, GstVideoCodecState * state); - GstFlowReturn (*prepare_frame) (GstOMXVideoDec * self, GstVideoCodecFrame *frame); -}; + GstOMXClassData cdata; -GType gst_omx_video_dec_get_type (void); + gboolean (*is_format_change) (GstOMXVideoDec * self, GstOMXPort * port, + GstVideoCodecState * state); + gboolean (*set_format) (GstOMXVideoDec * self, GstOMXPort * port, + GstVideoCodecState * state); + GstFlowReturn (*prepare_frame) (GstOMXVideoDec * self, + GstVideoCodecFrame * frame); + }; -G_END_DECLS + GType gst_omx_video_dec_get_type (void); +G_END_DECLS #endif /* __GST_OMX_VIDEO_DEC_H__ */ -- 2.7.4