diff -Naur a/omx/gstomx.h b/omx/gstomx.h --- a/omx/gstomx.h 2020-10-26 19:17:03.488452200 +0800 +++ b/omx/gstomx.h 2022-04-24 18:50:01.353690234 +0800 @@ -332,6 +332,7 @@ */ gint settings_cookie; gint configured_settings_cookie; + GstBuffer * c_buf; }; struct _GstOMXComponent { diff -Naur a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c --- a/omx/gstomxvideoenc.c 2020-10-26 19:17:03.492452100 +0800 +++ b/omx/gstomxvideoenc.c 2022-04-24 18:53:42.211595096 +0800 @@ -2102,6 +2102,143 @@ return TRUE; } +#ifdef USE_OMX_TARGET_STARFIVE +static GstBuffer * +gst_omx_try_importing_buffer (GstOMXVideoEnc * self, GstBufferPool * pool, + GstOMXPort * port, GstVideoInfo * v_info, guint i, GstVideoFrame ** frame) +{ + GstBufferPoolAcquireParams params = { 0, }; + GstBuffer *buffer = NULL; + GstMemory *mem; + GstMapFlags flags = GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF; + gboolean is_mapped = FALSE; + + *frame = NULL; + + if (gst_buffer_pool_acquire_buffer (pool, &buffer, ¶ms) != GST_FLOW_OK) { + GST_INFO_OBJECT (self, "Failed to acquire %d-th buffer", i); + return NULL; + } + + if (gst_buffer_n_memory (buffer) != 1) { + GST_INFO_OBJECT (self, "%d-th buffer has more than one memory (%d)", i, + gst_buffer_n_memory (buffer)); + goto out; + } + + mem = gst_buffer_peek_memory (buffer, 0); + if (!mem) { + GST_INFO_OBJECT (self, "Failed to acquire memory of %d-th buffer", i); + goto out; + } + + if ( !gst_is_dmabuf_memory (mem)) { + GST_INFO_OBJECT (self, + " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %lu", + i, port->port_def.nBufferSize); + goto out; + } + + *frame = g_slice_new0 (GstVideoFrame); + + is_mapped = gst_video_frame_map (*frame, v_info, buffer, flags); + GST_INFO_OBJECT (self, " *frame = %p, mem: %p", *frame, mem); + + if (!is_mapped) { + GST_INFO_OBJECT (self, "Failed to map %d-th buffer", i); + goto out; + } + + if (GST_VIDEO_FRAME_SIZE (*frame) < port->port_def.nBufferSize) { + GST_INFO_OBJECT (self, + "Frame size of %d-th buffer (%" G_GSIZE_FORMAT + ") is too small for port buffer size (%d)", i, + GST_VIDEO_FRAME_SIZE (*frame), (guint32) port->port_def.nBufferSize); + goto out; + } + + return buffer; + +out: + if (*frame) { + if (is_mapped) + gst_video_frame_unmap (*frame); + g_slice_free (GstVideoFrame, *frame); + *frame = NULL; + } + gst_buffer_unref (buffer); + return NULL; +} +#endif + +#ifdef USE_OMX_TARGET_STARFIVE +static gboolean +gst_omx_video_enc_use_buffers (GstOMXVideoEnc * self) +{ + GstOMXPort * port = self->enc_in_port; + GstBufferPool *pool = port->c_buf->pool; + GstVideoCodecState *input_state = self->input_state; + GstVideoInfo v_info = input_state->info; + guint n = port->port_def.nBufferCountActual; + GList *images = NULL; + GList *buffers = NULL; + GList *frames = NULL; + OMX_ERRORTYPE err = OMX_ErrorNone; + gboolean is_mapped = FALSE ; + GST_DEBUG(" nBufferCountActual=%d, nBufferCountMin= %lu", n, port->port_def.nBufferCountMin); + + if ( pool != NULL ) { + guint i; + for (i = 0; i < n; i++) { + GstBuffer * buf = NULL; + GstVideoFrame *frame = NULL; + buf = gst_omx_try_importing_buffer (self, pool, port, &v_info, i, &frame); + if (!buf) { + GST_DEBUG_OBJECT (self, "Failed to import %d-th buffer", i); + g_list_free (images); + g_list_free_full (frames, (GDestroyNotify) gst_video_frame_unmap); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + break; + } else { + buffers = g_list_append (buffers, buf); + frames = g_list_append (frames, frame); + images = g_list_append (images, GST_VIDEO_FRAME_PLANE_DATA (frame, 0)); + GST_DEBUG_OBJECT (self, " pBuffer: %p", GST_VIDEO_FRAME_PLANE_DATA (frame, 0)); + } + } + } + + if (images) { + is_mapped = TRUE; + + err = gst_omx_port_use_buffers (port, images); + g_list_free (images); + g_list_free_full (frames, (GDestroyNotify) gst_video_frame_unmap); + + if (err == OMX_ErrorNone) { + GST_DEBUG_OBJECT (self, "Using %d buffers", n); + } else { + GST_INFO_OBJECT (self, + "Failed to OMX_UseBuffer on port: %s (0x%08x)", + gst_omx_error_to_string (err), err); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + return FALSE; + } + } + + if ( !is_mapped ) { + GST_WARNING_OBJECT (self, " failed to call UseBuffer, trying to use allocation"); + self->input_dmabuf = FALSE; + self->input_allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER; + if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone){ + return FALSE; + } + } + + return TRUE; +} +#endif + static gboolean gst_omx_video_enc_allocate_in_buffers (GstOMXVideoEnc * self) { @@ -2115,6 +2252,9 @@ return FALSE; break; case GST_OMX_BUFFER_ALLOCATION_USE_BUFFER: +#ifdef USE_OMX_TARGET_STARFIVE + return gst_omx_video_enc_use_buffers(self); +#endif default: /* Not supported */ g_return_val_if_reached (FALSE); @@ -2179,8 +2319,18 @@ gst_omx_video_enc_pick_input_allocation_mode (GstOMXVideoEnc * self, GstBuffer * inbuf) { +#ifdef USE_OMX_TARGET_STARFIVE + if (!gst_omx_is_dynamic_allocation_supported ()){ + if (gst_is_dmabuf_memory (gst_buffer_peek_memory (inbuf, 0))){ + GST_DEBUG_OBJECT (self, "select GST_OMX_BUFFER_ALLOCATION_USE_BUFFER"); + return GST_OMX_BUFFER_ALLOCATION_USE_BUFFER; + } + return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER; + } +#else if (!gst_omx_is_dynamic_allocation_supported ()) return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER; +#endif if (can_use_dynamic_buffer_mode (self, inbuf)) { GST_DEBUG_OBJECT (self, @@ -2272,6 +2422,15 @@ input); self->input_dmabuf = FALSE; +#ifdef USE_OMX_TARGET_STARFIVE + if (self->input_allocation == + GST_OMX_BUFFER_ALLOCATION_USE_BUFFER) { + self->input_dmabuf = TRUE; + self->enc_in_port->c_buf = input; + GST_DEBUG_OBJECT (self, "input_dmabuf is true"); + } +#endif + #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS if (gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) { if (self->input_allocation == @@ -2786,7 +2945,11 @@ } if (self->enc_in_port->allocation == - GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) { + GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC +#ifdef USE_OMX_TARGET_STARFIVE + || self->enc_in_port->allocation == GST_OMX_BUFFER_ALLOCATION_USE_BUFFER +#endif + ) { if (gst_buffer_n_memory (inbuf) > 1) { GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("input buffer now has more than one memory, can't use dynamic allocation any more")); @@ -2812,12 +2975,29 @@ gst_buffer_get_size (inbuf)); } else { /* dmabuf input */ +#ifdef USE_OMX_TARGET_STARFIVE + if (self->enc_in_port->allocation == GST_OMX_BUFFER_ALLOCATION_USE_BUFFER) { + GstMemory *mem = gst_buffer_peek_memory (inbuf, 0); + GST_LOG_OBJECT (self, " mem: %p, inbuf: %p, outbuf: %p", mem, inbuf, outbuf); + if (!gst_omx_buffer_map_memory (outbuf, mem)) { + GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),("failed to import")); + GST_ERROR_OBJECT (self, "failed to import dmabuf %p, inbuf: %p",mem, inbuf); + return FALSE; + } + } else { + if (!gst_omx_buffer_import_fd (outbuf, inbuf)) { + GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), + ("failed to import dmabuf")); + return FALSE; + } + } +#else if (!gst_omx_buffer_import_fd (outbuf, inbuf)) { GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("failed to import dmabuf")); return FALSE; } - +#endif GST_LOG_OBJECT (self, "Import dmabuf of %" G_GSIZE_FORMAT " bytes", gst_buffer_get_size (inbuf)); }