diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0001-add-starfive-support.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0001-add-starfive-support.patch new file mode 100644 index 0000000..28801e6 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0001-add-starfive-support.patch @@ -0,0 +1,69 @@ +diff --git a/config/meson.build b/config/meson.build +index 1068c6d..7f8abe9 100755 +--- a/config/meson.build ++++ b/config/meson.build +@@ -6,6 +6,8 @@ elif omx_target == 'zynqultrascaleplus' + sub = 'zynqultrascaleplus' + elif omx_target == 'tizonia' + sub = 'tizonia' ++ elif omx_target == 'stf' ++ sub = 'stf' + else + # No config file defined for the 'generic' target + sub = '' +diff --git a/config/stf/gstomx.conf b/config/stf/gstomx.conf +new file mode 100644 +index 0000000..b4cdebb +--- /dev/null ++++ b/config/stf/gstomx.conf +@@ -0,0 +1,17 @@ ++[omxh265dec] ++type-name=GstOMXH265Dec ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.dec.decoder.h265 ++in-port-index=0 ++out-port-index=1 ++rank=0 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual ++ ++[omxh264dec] ++type-name=GstOMXH264Dec ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.dec.decoder.h264 ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual +diff --git a/config/stf/meson.build b/config/stf/meson.build +new file mode 100644 +index 0000000..dc99c08 +--- /dev/null ++++ b/config/stf/meson.build +@@ -0,0 +1 @@ ++install_data (['gstomx.conf'], install_dir : omx_conf_dir) +diff --git a/meson.build b/meson.build +index 32c7fa7..aeda56a 100755 +--- a/meson.build ++++ b/meson.build +@@ -216,6 +216,8 @@ elif omx_target == 'tizonia' + tizil_includedir = tizil_dep.get_pkgconfig_variable('includedir') + gst_omx_args += ['-I' + tizil_includedir + '/tizonia'] + omx_inc = [] ++elif omx_target == 'stf' ++ warning('stf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') + endif +diff --git a/meson_options.txt b/meson_options.txt +index e18beb2..4fc6139 100755 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -1,7 +1,7 @@ + option('header_path', type : 'string', value : '', + description : 'An extra include directory to find the OpenMax headers') + option('target', type : 'combo', +- choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus'], value : 'none', ++ choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus', 'stf'], value : 'none', + description : 'The OMX platform to target') + option('struct_packing', type : 'combo', + choices : ['0', '1', '2', '4', '8'], value : '0', diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch new file mode 100755 index 0000000..ae9e95b --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch @@ -0,0 +1,70 @@ +From 810800c303965e5cb0cf135210667c003f050ee0 Mon Sep 17 00:00:00 2001 +From: "andy.hu" +Date: Tue, 10 Aug 2021 19:18:00 +0800 +Subject: [PATCH] Fix(gst-omx): Enable the gst-omx VPU decoding and encoding + support h264 High L5.2 + +--- + +diff --git a/meson.build b/meson.build +index aeda56a..48121ab 100644 +--- a/meson.build ++++ b/meson.build +@@ -217,6 +217,7 @@ elif omx_target == 'tizonia' + gst_omx_args += ['-I' + tizil_includedir + '/tizonia'] + omx_inc = [] + elif omx_target == 'stf' ++ cdata.set('USE_OMX_TARGET_STARFIVE', 1) + warning('stf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') +diff --git a/omx/gstomxh264enc.c b/omx/gstomxh264enc.c +index 51d84a8..875f974 100644 +--- a/omx/gstomxh264enc.c ++++ b/omx/gstomxh264enc.c +@@ -824,6 +824,11 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port, + case OMX_VIDEO_AVCLevel51: + level = "5.1"; + break; ++#ifdef USE_OMX_TARGET_STARFIVE ++ case OMX_VIDEO_AVCLevel52: ++ level = "5.2"; ++ break; ++#else + #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + case OMX_ALG_VIDEO_AVCLevel52: + level = "5.2"; +@@ -837,6 +842,7 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port, + case OMX_ALG_VIDEO_AVCLevel62: + level = "6.2"; + break; ++#endif + #endif + default: + g_assert_not_reached (); +diff --git a/omx/gstomxh264utils.c b/omx/gstomxh264utils.c +index ba29211..a6e95e3 100644 +--- a/omx/gstomxh264utils.c ++++ b/omx/gstomxh264utils.c +@@ -115,6 +115,10 @@ gst_omx_h264_utils_get_level_from_str (const gchar * level) + return OMX_VIDEO_AVCLevel5; + } else if (g_str_equal (level, "5.1")) { + return OMX_VIDEO_AVCLevel51; ++#ifdef USE_OMX_TARGET_STARFIVE ++ } else if (g_str_equal (level, "5.2")) { ++ return OMX_VIDEO_AVCLevel52; ++#else + #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + } else if (g_str_equal (level, "5.2")) { + return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel52; +@@ -124,6 +128,7 @@ gst_omx_h264_utils_get_level_from_str (const gchar * level) + return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel61; + } else if (g_str_equal (level, "6.2")) { + return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel62; ++#endif + #endif + } + +-- +2.17.1 + diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0003-add-video-scale-support.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0003-add-video-scale-support.patch new file mode 100644 index 0000000..fd088ca --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0003-add-video-scale-support.patch @@ -0,0 +1,50 @@ +--- a/omx/gstomxvideodec.c 2020-10-26 19:17:03.000000000 +0800 ++++ b/omx/gstomxvideodec.c 2021-08-16 16:23:08.082113380 +0800 +@@ -2185,6 +2185,7 @@ + gst_omx_video_dec_negotiate (GstOMXVideoDec * self) + { + OMX_VIDEO_PARAM_PORTFORMATTYPE param; ++ OMX_PARAM_PORTDEFINITIONTYPE port_def; + OMX_ERRORTYPE err; + GstCaps *comp_supported_caps; + GList *negotiation_map = NULL, *l; +@@ -2192,6 +2193,7 @@ + GstVideoFormat format; + GstStructure *s; + const gchar *format_str; ++ gint width, height; + + GST_DEBUG_OBJECT (self, "Trying to negotiate a video format with downstream"); + +@@ -2281,6 +2283,31 @@ + gst_omx_error_to_string (err), err); + } + ++ if (gst_structure_get_int(s, "width", &width) && gst_structure_get_int(s, "height", &height)) ++ { ++ GST_OMX_INIT_STRUCT (&port_def); ++ port_def.nPortIndex = self->dec_out_port->index; ++ err = gst_omx_component_get_parameter (self->dec, ++ OMX_IndexParamPortDefinition, &port_def); ++ if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, "Failed to get video port definition: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ return FALSE; ++ } ++ ++ port_def.format.video.nFrameHeight = height; ++ port_def.format.video.nFrameWidth = width; ++ ++ err = ++ gst_omx_component_set_parameter (self->dec, ++ OMX_IndexParamPortDefinition, &port_def); ++ if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, "Failed to set video port definition: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ return FALSE; ++ } ++ } ++ + gst_caps_unref (intersection); + return (err == OMX_ErrorNone); + } diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0004-add-encoder-support.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0004-add-encoder-support.patch new file mode 100644 index 0000000..25633e7 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0004-add-encoder-support.patch @@ -0,0 +1,24 @@ +--- a/config/stf/gstomx.conf 2021-08-18 14:51:51.384176799 +0800 ++++ b/config/stf/gstomx.conf 2021-08-18 14:50:58.972186447 +0800 +@@ -15,3 +15,21 @@ + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual ++ ++[omxh265enc] ++type-name=GstOMXH265Enc ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.enc.encoder.h265 ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual;video-framerate-integer ++ ++[omxh264enc] ++type-name=GstOMXH264Enc ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.enc.encoder.h264 ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual;video-framerate-integer diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0005-rank-257-for-sf-codecs.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0005-rank-257-for-sf-codecs.patch new file mode 100644 index 0000000..2d2f9ba --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0005-rank-257-for-sf-codecs.patch @@ -0,0 +1,19 @@ +diff -Naur a/config/stf/gstomx.conf b/config/stf/gstomx.conf +--- a/config/stf/gstomx.conf 2021-08-23 16:04:48.928905742 +0800 ++++ b/config/stf/gstomx.conf 2021-08-23 16:03:38.590578856 +0800 +@@ -4,7 +4,7 @@ + component-name=sf.dec.decoder.h265 + in-port-index=0 + out-port-index=1 +-rank=0 ++rank=257 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual + + [omxh264dec] +@@ -13,5 +13,5 @@ + component-name=sf.dec.decoder.h264 + in-port-index=0 + out-port-index=1 +-rank=1 ++rank=257 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch new file mode 100644 index 0000000..55387cc --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch @@ -0,0 +1,19 @@ +--- a/omx/gstomxvideodec.c ++++ b/omx/gstomxvideodec.c +@@ -718,6 +718,15 @@ + goto out; + } + ++#ifdef USE_OMX_TARGET_STARFIVE ++ 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; ++ } ++#endif ++ + *frame = g_slice_new0 (GstVideoFrame); + + is_mapped = gst_video_frame_map (*frame, v_info, buffer, flags); + diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0007-add-omxmjpegdec-support.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0007-add-omxmjpegdec-support.patch new file mode 100644 index 0000000..def9fe6 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0007-add-omxmjpegdec-support.patch @@ -0,0 +1,16 @@ +--- a/config/stf/gstomx.conf ++++ b/config/stf/gstomx.conf +@@ -33,3 +33,12 @@ + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual;video-framerate-integer ++ ++[omxmjpegdec] ++type-name=GstOMXMJPEGDec ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.dec.decoder.mjpeg ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual + diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0008-support-nv21-i422-y444-for-omxmjpegdec.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0008-support-nv21-i422-y444-for-omxmjpegdec.patch new file mode 100644 index 0000000..c360b82 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0008-support-nv21-i422-y444-for-omxmjpegdec.patch @@ -0,0 +1,100 @@ +--- a/config/stf/gstomx.conf ++++ b/config/stf/gstomx.conf +@@ -42,3 +42,4 @@ + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual ++src-template-caps=video/x-raw, format = (string) { NV16_10LE32, NV12_10LE32, NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8, Y42B, Y444 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ] +--- a/omx/gstomxbufferpool.c ++++ b/omx/gstomxbufferpool.c +@@ -370,9 +370,29 @@ + case GST_VIDEO_FORMAT_NV12_10LE32: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV16_10LE32: ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_NV21: ++#endif + stride[1] = nstride; + offset[1] = offset[0] + stride[0] * nslice; + break; ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_Y42B: ++ stride[0] = GST_ROUND_UP_4 (nstride); ++ stride[1] = GST_ROUND_UP_8 (nstride) / 2; ++ stride[2] = stride[1]; ++ ++ offset[1] = stride[0] * nslice; ++ offset[2] = offset[1] + stride[1] * nslice; ++ break; ++ ++ case GST_VIDEO_FORMAT_Y444: ++ stride[1] = nstride; ++ stride[2] = nstride; ++ offset[1] = offset[0] + stride[0] * nslice; ++ offset[2] = offset[1] + stride[1] * nslice; ++ break; ++#endif + default: + g_assert_not_reached (); + break; +--- a/omx/gstomxvideo.c ++++ b/omx/gstomxvideo.c +@@ -93,6 +93,17 @@ + format = GST_VIDEO_FORMAT_NV16_10LE32; + break; + #pragma GCC diagnostic pop ++#endif ++#ifdef USE_OMX_TARGET_STARFIVE ++ case OMX_COLOR_FormatYUV422Planar: ++ format = GST_VIDEO_FORMAT_Y42B; ++ break; ++ case OMX_COLOR_FormatYUV444Interleaved: ++ format = GST_VIDEO_FORMAT_Y444; ++ break; ++ case OMX_COLOR_FormatYVU420SemiPlanar: ++ format = GST_VIDEO_FORMAT_NV21; ++ break; + #endif + default: + format = GST_VIDEO_FORMAT_UNKNOWN; +--- a/omx/gstomxvideodec.c ++++ b/omx/gstomxvideodec.c +@@ -592,6 +592,9 @@ + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_YVYU: ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_Y42B: ++#endif + dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2; + break; + case GST_VIDEO_FORMAT_GRAY8: +@@ -609,6 +612,9 @@ + dst_height[2] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) / 2; + break; + case GST_VIDEO_FORMAT_NV12: ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_NV21: ++#endif + dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo); + src_stride[1] = nstride; + src_size[1] = src_stride[1] * nslice / 2; +@@ -638,6 +644,18 @@ + src_size[1] = src_stride[1] * nslice; + dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo); + break; ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_Y444: ++ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo); ++ dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo); ++ dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo); ++ src_size[1] = src_size[0]; ++ src_size[2] = src_size[0]; ++ src_stride[1] = nstride; ++ dst_height[1] = dst_height[0]; ++ dst_height[2] = dst_height[0]; ++ break; ++#endif + default: + g_assert_not_reached (); + break; diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0009-suport-usebuffer-mode-for-encoding.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0009-suport-usebuffer-mode-for-encoding.patch new file mode 100644 index 0000000..a98259d --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0009-suport-usebuffer-mode-for-encoding.patch @@ -0,0 +1,247 @@ +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)); + } diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0010-add-property-framerate.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0010-add-property-framerate.patch new file mode 100644 index 0000000..c007634 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0010-add-property-framerate.patch @@ -0,0 +1,144 @@ +--- a/omx/gstomxmjpegdec.h ++++ b/omx/gstomxmjpegdec.h +@@ -45,6 +45,16 @@ + struct _GstOMXMJPEGDec + { + GstOMXVideoDec parent; ++#ifdef USE_OMX_TARGET_STARFIVE ++ //If container shows fps as public api, it won't work ++ //as GstBuffer containing pts/dts/duration and it will calculate fps in upstream. ++ //i.e. ++ //not works: ++ // gst-launch-1.0 -v filesrc location=xxx.mp4 ! qtdemux name=demux demux.video_0 ! jpegparse ! omxmjpegdec framerate=xxx ! kmssink driver-name=starfive force-modesetting=1 ++ //works: ++ // gst-launch-1.0 -v filesrc location=xxx.mjpeg ! jpegparse ! omxmjpegdec framerate=xxx ! kmssink driver-name=starfive force-modesetting=1 ++ gint framerate; ++#endif + }; + + struct _GstOMXMJPEGDecClass + +--- a/omx/gstomxmjpegdec.c ++++ b/omx/gstomxmjpegdec.c +@@ -28,16 +28,28 @@ + + GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg_dec_debug_category); + #define GST_CAT_DEFAULT gst_omx_mjpeg_dec_debug_category +- ++#ifdef USE_OMX_TARGET_STARFIVE ++#define DEFAULT_FRAMERATE 0 ++#endif + /* prototypes */ + static gboolean gst_omx_mjpeg_dec_is_format_change (GstOMXVideoDec * dec, + GstOMXPort * port, GstVideoCodecState * state); + static gboolean gst_omx_mjpeg_dec_set_format (GstOMXVideoDec * dec, + GstOMXPort * port, GstVideoCodecState * state); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++static void gst_omx_mjpeg_dec_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec); ++static void gst_omx_mjpeg_dec_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec); ++#endif + enum + { ++#ifdef USE_OMX_TARGET_STARFIVE ++ PROP_0, ++ PROP_FRAMERATE ++#else + PROP_0 ++#endif + }; + + /* class initialization */ +@@ -54,11 +66,16 @@ + { + GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ GObjectClass *gobject_class = G_OBJECT_CLASS (videodec_class); ++#endif + videodec_class->is_format_change = + GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_is_format_change); + videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_set_format); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_set_property); ++ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_get_property); ++#endif + videodec_class->cdata.default_sink_template_caps = "image/jpeg, " + "width=(int) [1,MAX], " "height=(int) [1,MAX]"; + +@@ -67,7 +84,16 @@ + "Codec/Decoder/Video/Hardware", + "Decode MJPEG video streams", + "Sebastian Dröge "); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ g_object_class_install_property (gobject_class, PROP_FRAMERATE, ++ g_param_spec_int ("framerate", ++ "Framerate", ++ "Frames per second in raw stream.\n \ ++ Only workable for the container not exposing fps.\n\ ++ '0' means disabled.", ++ 0, G_MAXINT, ++ DEFAULT_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++#endif + gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg"); + } + +@@ -89,10 +115,53 @@ + { + gboolean ret; + OMX_PARAM_PORTDEFINITIONTYPE port_def; ++#ifdef USE_OMX_TARGET_STARFIVE ++ GstVideoInfo *info = &state->info; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (dec); + ++ if (mjpeg_dec->framerate != DEFAULT_FRAMERATE) { ++ GST_DEBUG_OBJECT (dec, " change fps from %d/%d to %d/1" GST_PTR_FORMAT, info->fps_n, info->fps_d, mjpeg_dec->framerate); ++ info->fps_n = mjpeg_dec->framerate; ++ info->fps_d = 1; ++ if (state->caps) { ++ gst_caps_set_simple (state->caps, "framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL); ++ } ++ } ++#endif + gst_omx_port_get_port_definition (port, &port_def); + port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG; + ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone; + + return ret; + } ++#ifdef USE_OMX_TARGET_STARFIVE ++static void ++gst_omx_mjpeg_dec_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec) ++{ ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (object); ++ switch (prop_id) { ++ case PROP_FRAMERATE: ++ mjpeg_dec->framerate = g_value_get_int (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gst_omx_mjpeg_dec_get_property (GObject * object, guint prop_id, GValue * value, ++ GParamSpec * pspec) ++{ ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (object); ++ switch (prop_id) { ++ case PROP_FRAMERATE: ++ g_value_set_int (value, mjpeg_dec->framerate); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++#endif diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0011-hanle-some-extra-profile-for-avc.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0011-hanle-some-extra-profile-for-avc.patch new file mode 100644 index 0000000..c9916ed --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0011-hanle-some-extra-profile-for-avc.patch @@ -0,0 +1,38 @@ +--- a/omx/gstomxh264utils.c ++++ b/omx/gstomxh264utils.c +@@ -54,6 +54,19 @@ + #endif + }; + ++#ifdef USE_OMX_TARGET_STARFIVE ++static const H264ProfileMapping h264_ext_profiles[] = { ++ {"progressive-high", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh}, ++ {"constrained-high", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh}, ++ {"high-10-intra", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh10}, ++ {"high-4:2:2-intra", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh422}, ++}; ++#endif ++ + OMX_VIDEO_AVCPROFILETYPE + gst_omx_h264_utils_get_profile_from_str (const gchar * profile) + { +@@ -63,6 +76,15 @@ + if (g_str_equal (profile, h264_profiles[i].profile)) + return h264_profiles[i].e; + } ++ ++#ifdef USE_OMX_TARGET_STARFIVE ++ for (i = 0; i < G_N_ELEMENTS (h264_ext_profiles); i++) { ++ if (g_str_equal (profile, h264_ext_profiles[i].profile)) { ++ GST_INFO("extra profile: %s ==> avc profie type: %d", profile, h264_ext_profiles[i].e); ++ return h264_ext_profiles[i].e; ++ } ++ } ++#endif + + return OMX_VIDEO_AVCProfileMax; + } diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0012-combine-sps-pps-header-to-idr.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0012-combine-sps-pps-header-to-idr.patch new file mode 100644 index 0000000..b5116e8 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0012-combine-sps-pps-header-to-idr.patch @@ -0,0 +1,67 @@ +Combine SPS/PPS header to IDR frame. + +Signed-off-by: Windsome Zeng + +diff -purN a/meson.build b/meson.build +--- a/meson.build 2022-05-13 11:31:02.725614796 +0800 ++++ b/meson.build 2022-05-13 11:32:26.213975419 +0800 +@@ -218,6 +218,7 @@ elif omx_target == 'tizonia' + omx_inc = [] + elif omx_target == 'stf' + cdata.set('USE_OMX_TARGET_STARFIVE', 1) ++ gst_omx_args += ['-DCOMBINE_SPS_PPS_HEADERS'] + warning('stf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') +diff -purN a/omx/gstomx.c b/omx/gstomx.c +--- a/omx/gstomx.c 2022-05-13 11:31:02.725614796 +0800 ++++ b/omx/gstomx.c 2022-05-13 11:33:15.461950978 +0800 +@@ -70,6 +70,11 @@ static GHashTable *core_handles; + G_LOCK_DEFINE_STATIC (buffer_flags_str); + static GHashTable *buffer_flags_str; + ++#ifdef COMBINE_SPS_PPS_HEADERS ++static OMX_U8 *sps_pps_header = NULL; ++static OMX_U32 sps_pps_header_size = 0; ++#endif ++ + GstOMXCore * + gst_omx_core_acquire (const gchar * filename) + { +@@ -903,6 +908,36 @@ FillBufferDone (OMX_HANDLETYPE hComponen + + g_assert (buf->omx_buf == pBuffer); + ++#ifdef COMBINE_SPS_PPS_HEADERS ++ if (pBuffer->nFlags == 0x80) { ++ g_assert (sps_pps_header == NULL); ++ if (sps_pps_header) ++ g_free (sps_pps_header); ++ ++ sps_pps_header = g_new (OMX_U8, pBuffer->nFilledLen); ++ if (sps_pps_header) { ++ sps_pps_header_size = pBuffer->nFilledLen; ++ memcpy(sps_pps_header, pBuffer->pBuffer + pBuffer->nOffset, pBuffer->nFilledLen); ++ } ++ return OMX_ErrorNone; ++ } ++ ++ if (sps_pps_header) { ++ g_assert (sps_pps_header_size + pBuffer->nFilledLen <= pBuffer->nAllocLen); ++ if (sps_pps_header_size + pBuffer->nFilledLen <= pBuffer->nAllocLen) { ++ OMX_U8 *buf; ++ buf = pBuffer->pBuffer + pBuffer->nOffset; ++ memmove (buf + sps_pps_header_size, buf, pBuffer->nFilledLen); ++ memcpy (buf, sps_pps_header, sps_pps_header_size); ++ pBuffer->nFilledLen += sps_pps_header_size; ++ ++ g_free (sps_pps_header); ++ sps_pps_header = NULL; ++ sps_pps_header_size = 0; ++ } ++ } ++#endif /* COMBINE_SPS_PPS_HEADERS */ ++ + if (buf->port->tunneled) { + GST_ERROR ("FillBufferDone on tunneled port"); + return OMX_ErrorBadParameter; diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0013-Modify-sf-component-name-to-in-std-format.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0013-Modify-sf-component-name-to-in-std-format.patch new file mode 100644 index 0000000..81d3f94 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0013-Modify-sf-component-name-to-in-std-format.patch @@ -0,0 +1,62 @@ +From f207f1287cf8732459e928940dd6e762fb546bff Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Mon, 25 Jul 2022 09:45:44 +0800 +Subject: [PATCH] Modify sf component name to adapt omx + +Signed-off-by: Som Qin +--- + config/stf/gstomx.conf | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/config/stf/gstomx.conf b/config/stf/gstomx.conf +index 398a62c..4eae679 100644 +--- a/config/stf/gstomx.conf ++++ b/config/stf/gstomx.conf +@@ -1,7 +1,7 @@ + [omxh265dec] + type-name=GstOMXH265Dec + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.dec.decoder.h265 ++component-name=OMX.sf.video_decoder.hevc.internal + in-port-index=0 + out-port-index=1 + rank=257 +@@ -10,7 +10,7 @@ hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-a + [omxh264dec] + type-name=GstOMXH264Dec + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.dec.decoder.h264 ++component-name=OMX.sf.video_decoder.avc.internal + in-port-index=0 + out-port-index=1 + rank=257 +@@ -19,7 +19,7 @@ hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-a + [omxh265enc] + type-name=GstOMXH265Enc + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.enc.encoder.h265 ++component-name=OMX.sf.video_encoder.hevc + in-port-index=0 + out-port-index=1 + rank=1 +@@ -28,7 +28,7 @@ hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-a + [omxh264enc] + type-name=GstOMXH264Enc + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.enc.encoder.h264 ++component-name=OMX.sf.video_encoder.avc + in-port-index=0 + out-port-index=1 + rank=1 +@@ -37,7 +37,7 @@ hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-a + [omxmjpegdec] + type-name=GstOMXMJPEGDec + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.dec.decoder.mjpeg ++component-name=OMX.sf.video_decoder.mjpeg.internal + in-port-index=0 + out-port-index=1 + rank=1 +-- +2.25.1 + diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0014-support-nv21-for-omxh264_5dec.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0014-support-nv21-for-omxh264_5dec.patch new file mode 100644 index 0000000..ca48b7d --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0014-support-nv21-for-omxh264_5dec.patch @@ -0,0 +1,16 @@ +Add NV21 for omxh264dec omxh265dec + +Signed-off-by: Leo Lu + +diff -purN a/omx/gstomxvideo.h b/omx/gstomxvideo.h +--- a/omx/gstomxvideo.h 2021-09-09 03:05:28.042623000 +0800 ++++ b/omx/gstomxvideo.h 2022-08-23 13:45:37.042353044 +0800 +@@ -36,7 +36,7 @@ G_BEGIN_DECLS + + /* Keep synced with gst_omx_video_get_format_from_omx(). Sort by decreasing quality */ + #define GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \ +- "NV16, YUY2, YVYU, UYVY, NV12, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }" ++ "NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }" + + #define GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \ + "NV16, NV12, I420, GRAY8 }" diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0015_Add_NV21_for_gstomxvideoenc_class.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0015_Add_NV21_for_gstomxvideoenc_class.patch new file mode 100644 index 0000000..a3230f0 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0015_Add_NV21_for_gstomxvideoenc_class.patch @@ -0,0 +1,72 @@ +Add NV21 for omxvideoenc class + +Signed-off-by: Leo Lu + +diff -purN a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c +--- a/omx/gstomxvideoenc.c 2022-08-26 18:07:10.171979169 +0800 ++++ b/omx/gstomxvideoenc.c 2022-08-29 09:54:54.979229076 +0800 +@@ -1391,6 +1391,7 @@ get_chroma_info_from_input (GstOMXVideoE + break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_NV12: ++ case GST_VIDEO_FORMAT_NV21: + *chroma_format = "4:2:0"; + *bit_depth_luma = *bit_depth_chroma = 8; + break; +@@ -2045,6 +2046,7 @@ gst_omx_video_enc_configure_input_buffer + + case OMX_COLOR_FormatYUV420PackedSemiPlanar: + case OMX_COLOR_FormatYUV420SemiPlanar: ++ case OMX_COLOR_FormatYVU420SemiPlanar: + port_def.nBufferSize = + (port_def.format.video.nStride * port_def.format.video.nFrameHeight) + + (port_def.format.video.nStride * +@@ -2693,6 +2695,9 @@ gst_omx_video_enc_set_format (GstVideoEn + case GST_VIDEO_FORMAT_ARGB: + port_def.format.video.eColorFormat = OMX_COLOR_Format32bitBGRA8888; + break; ++ case GST_VIDEO_FORMAT_NV21: ++ port_def.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar; ++ break; + default: + GST_ERROR_OBJECT (self, "Unsupported format %s", + gst_video_format_to_string (info->finfo->format)); +@@ -3094,6 +3099,7 @@ gst_omx_video_enc_fill_buffer (GstOMXVid + break; + } + case GST_VIDEO_FORMAT_NV12: ++ case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV12_10LE32: + case GST_VIDEO_FORMAT_NV16_10LE32: +@@ -3728,6 +3734,7 @@ filter_supported_formats (GList * negoti + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV16_10LE32: + case GST_VIDEO_FORMAT_GRAY8: ++ case GST_VIDEO_FORMAT_NV21: + cur = g_list_next (cur); + continue; + default: +diff -purN a/omx/gstomxvideo.h b/omx/gstomxvideo.h +--- a/omx/gstomxvideo.h 2022-08-26 18:07:10.219979290 +0800 ++++ b/omx/gstomxvideo.h 2022-08-29 09:55:41.307514974 +0800 +@@ -39,7 +39,7 @@ G_BEGIN_DECLS + "NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }" + + #define GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \ +- "NV16, NV12, I420, GRAY8 }" ++ "NV16, NV12, NV21, I420, GRAY8 }" + + typedef struct + { +diff -purN a/omx/openmax/OMX_IVCommon.h b/omx/openmax/OMX_IVCommon.h +--- a/omx/openmax/OMX_IVCommon.h 2021-09-09 03:05:28.046623200 +0800 ++++ b/omx/openmax/OMX_IVCommon.h 2022-08-29 09:56:49.415927528 +0800 +@@ -130,6 +130,7 @@ typedef enum OMX_COLOR_FORMATTYPE { + OMX_COLOR_Format18BitBGR666, + OMX_COLOR_Format24BitARGB6666, + OMX_COLOR_Format24BitABGR6666, ++ OMX_COLOR_FormatYVU420SemiPlanar, /* NV21 */ + OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_COLOR_FormatMax = 0x7FFFFFFF diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0016-Modify-gstomxmjpegdec-format.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0016-Modify-gstomxmjpegdec-format.patch new file mode 100644 index 0000000..07fade3 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0016-Modify-gstomxmjpegdec-format.patch @@ -0,0 +1,86 @@ +Changed Y444 for correct format +Add VYUY v308 NV61 format for omxmjpegdec + +Signed-off-by: Leo Lu + +diff -purN a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +--- a/omx/gstomxbufferpool.c 2022-09-23 11:48:33.011477728 +0800 ++++ b/omx/gstomxbufferpool.c 2022-09-23 15:01:05.053735591 +0800 +@@ -355,10 +355,13 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: ++ case GST_VIDEO_FORMAT_GRAY8: ++ break; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_YVYU: +- case GST_VIDEO_FORMAT_GRAY8: ++ case GST_VIDEO_FORMAT_VYUY: ++ stride[0] = GST_ROUND_UP_4(nstride * 2); + break; + case GST_VIDEO_FORMAT_I420: + stride[1] = nstride / 2; +@@ -370,6 +373,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + case GST_VIDEO_FORMAT_NV12_10LE32: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV16_10LE32: ++ case GST_VIDEO_FORMAT_NV61: + #ifdef USE_OMX_TARGET_STARFIVE + case GST_VIDEO_FORMAT_NV21: + #endif +@@ -392,6 +396,9 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + offset[1] = offset[0] + stride[0] * nslice; + offset[2] = offset[1] + stride[1] * nslice; + break; ++ case GST_VIDEO_FORMAT_v308: ++ stride[0] = GST_ROUND_UP_4(nstride * 3); ++ break; + #endif + default: + g_assert_not_reached (); +diff -purN a/omx/gstomxvideo.c b/omx/gstomxvideo.c +--- a/omx/gstomxvideo.c 2022-09-23 11:48:33.011477728 +0800 ++++ b/omx/gstomxvideo.c 2022-09-23 15:00:40.937734140 +0800 +@@ -99,11 +99,20 @@ gst_omx_video_get_format_from_omx (OMX_C + format = GST_VIDEO_FORMAT_Y42B; + break; + case OMX_COLOR_FormatYUV444Interleaved: +- format = GST_VIDEO_FORMAT_Y444; ++ format = GST_VIDEO_FORMAT_v308; + break; + case OMX_COLOR_FormatYVU420SemiPlanar: + format = GST_VIDEO_FORMAT_NV21; + break; ++ case OMX_COLOR_FormatCrYCbY: ++ format = GST_VIDEO_FORMAT_VYUY; ++ break; ++ case OMX_COLOR_FormatYUV444Planar: ++ format = GST_VIDEO_FORMAT_Y444; ++ break; ++ case OMX_COLOR_FormatYVU422SemiPlanar: ++ format = GST_VIDEO_FORMAT_NV61; ++ break; + #endif + default: + format = GST_VIDEO_FORMAT_UNKNOWN; +diff -purN a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c +--- a/omx/gstomxvideodec.c 2022-09-23 11:48:33.011477728 +0800 ++++ b/omx/gstomxvideodec.c 2022-09-23 11:42:45.251075196 +0800 +@@ -646,6 +646,7 @@ gst_omx_video_dec_fill_buffer (GstOMXVid + break; + #ifdef USE_OMX_TARGET_STARFIVE + case GST_VIDEO_FORMAT_Y444: ++ case GST_VIDEO_FORMAT_v308: + dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo); + dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo); + dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo); +diff -purN a/config/stf/gstomx.conf b/config/stf/gstomx.conf +--- a/config/stf/gstomx.conf 2022-09-23 11:48:33.079477828 +0800 ++++ b/config/stf/gstomx.conf 2022-09-23 15:04:52.249741473 +0800 +@@ -42,4 +42,4 @@ in-port-index=0 + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual +-src-template-caps=video/x-raw, format = (string) { NV16_10LE32, NV12_10LE32, NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8, Y42B, Y444 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ] ++src-template-caps=video/x-raw, format = (string) { NV16_10LE32, NV12_10LE32, NV16, NV61, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8, Y42B, Y444, VYUY, v308 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ] diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch new file mode 100644 index 0000000..14ef731 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch @@ -0,0 +1,388 @@ +Support mirror rotation scale for omxmjpegdec + +Signed-off-by: Leo Lu + +diff -purN a/omx/gstomxmjpegdec.c b/omx/gstomxmjpegdec.c +--- a/omx/gstomxmjpegdec.c 2022-10-14 13:42:12.749600862 +0800 ++++ b/omx/gstomxmjpegdec.c 2022-10-14 13:36:08.488195374 +0800 +@@ -30,8 +30,19 @@ GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg + #define GST_CAT_DEFAULT gst_omx_mjpeg_dec_debug_category + #ifdef USE_OMX_TARGET_STARFIVE + #define DEFAULT_FRAMERATE 0 ++#define DEFAULT_MIRROR 0 ++#define DEFAULT_ROTATION 0 ++#define DEFAULT_SCALEH 0 ++#define DEFAULT_SCALEV 0 + #endif + /* prototypes */ ++ ++static gboolean ++gst_omx_jpegdec_set_scale (GstOMXVideoDec * self); ++static gboolean ++gst_omx_jpegdec_set_rotation (GstOMXVideoDec * self); ++static gboolean ++gst_omx_jpegdec_set_mirror (GstOMXVideoDec * self); + static gboolean gst_omx_mjpeg_dec_is_format_change (GstOMXVideoDec * dec, + GstOMXPort * port, GstVideoCodecState * state); + static gboolean gst_omx_mjpeg_dec_set_format (GstOMXVideoDec * dec, +@@ -46,10 +57,14 @@ enum + { + #ifdef USE_OMX_TARGET_STARFIVE + PROP_0, +- PROP_FRAMERATE ++ PROP_FRAMERATE, + #else +- PROP_0 ++ PROP_0, + #endif ++ PROP_MIRROR, ++ PROP_SCALEH, ++ PROP_SCALEV, ++ PROP_ROTATION, + }; + + /* class initialization */ +@@ -61,6 +76,67 @@ enum + G_DEFINE_TYPE_WITH_CODE (GstOMXMJPEGDec, gst_omx_mjpeg_dec, + GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT); + ++#define GST_OMX_MJPEG_DEC_MIRROR_MODE (gst_omx_mjpeg_dec_mirror_mode_get_type ()) ++ ++static GType ++gst_omx_mjpeg_dec_mirror_mode_get_type (void) ++{ ++ static GType qtype = 0; ++ if (qtype == 0) { ++ static const GEnumValue values[] = { ++ { OMX_MirrorNone, "None", "none"}, ++ { OMX_MirrorVertical, "Mirror Vertical", "V"}, ++ { OMX_MirrorHorizontal, "Mirror Horizontal", "H"}, ++ { OMX_MirrorBoth, "Mirror Both", "VH"}, ++ { 0, NULL, NULL} ++ }; ++ ++ qtype = g_enum_register_static("GstOMXMJPEGDecMirrorMode",values); ++ } ++ return qtype; ++} ++ ++#define GST_OMX_MJPEG_DEC_ROTATION_MODE (gst_omx_mjpeg_dec_rotation_mode_get_type ()) ++ ++static GType ++gst_omx_mjpeg_dec_rotation_mode_get_type (void) ++{ ++ static GType qtype = 0; ++ if (qtype == 0) { ++ static const GEnumValue values[] = { ++ { ROTATION_0, "None", "none"}, ++ { ROTATION_90, "Rotate 90", "M1"}, ++ { ROTATION_180, "Rotate 180", "M2"}, ++ { ROTATION_270, "Rotate 270", "M3"}, ++ { 0, NULL, NULL} ++ }; ++ ++ qtype = g_enum_register_static ("GstOMXMJPEGDecRotationMode", values); ++ } ++ return qtype; ++} ++ ++#define GST_OMX_MJPEG_DEC_SCALE_MODE (gst_omx_mjpeg_dec_scale_mode_get_type ()) ++ ++static GType ++gst_omx_mjpeg_dec_scale_mode_get_type (void) ++{ ++ static GType qtype = 0; ++ if (qtype == 0) { ++ static const GEnumValue values[] = { ++ { SCALEMODE_0, "None", "none"}, ++ { SCALEMODE1_2, "Scale half", "1/2"}, ++ { SCALEMODE1_4, "Scale quarter", "1/4"}, ++ { SCALEMODE1_8, "Scale eighth", "1/8"}, ++ { 0, NULL, NULL} ++ }; ++ ++ qtype = g_enum_register_static ("GstOMXMJPEGDecScaleMode", values); ++ } ++ return qtype; ++} ++ ++ + static void + gst_omx_mjpeg_dec_class_init (GstOMXMJPEGDecClass * klass) + { +@@ -94,12 +170,40 @@ gst_omx_mjpeg_dec_class_init (GstOMXMJPE + 0, G_MAXINT, + DEFAULT_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + #endif ++ g_object_class_install_property (gobject_class, PROP_MIRROR, ++ g_param_spec_enum ("mirror", "MIRROR", ++ "Mirror 0(none), 1(V), 2(H), 3(VH).", ++ GST_OMX_MJPEG_DEC_MIRROR_MODE, ++ DEFAULT_MIRROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (gobject_class, PROP_ROTATION, ++ g_param_spec_enum ("rotation", "ROTATION", ++ "Rotation 0(none), 1(90), 2(180), 3(270).", ++ GST_OMX_MJPEG_DEC_ROTATION_MODE, ++ DEFAULT_ROTATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (gobject_class, PROP_SCALEH, ++ g_param_spec_enum ("scaleH", "ScaleH", ++ "Horizontal downscale: 0(none), 1(1/2), 2(1/4), 3(1/8).", ++ GST_OMX_MJPEG_DEC_SCALE_MODE, DEFAULT_SCALEH, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (gobject_class, PROP_SCALEV, ++ g_param_spec_enum ("scaleV", "ScaleV", ++ "Vertical downscale: 0(none), 1(1/2), 2(1/4), 3(1/8).", ++ GST_OMX_MJPEG_DEC_SCALE_MODE, DEFAULT_SCALEV, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ + gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg"); + } + + static void + gst_omx_mjpeg_dec_init (GstOMXMJPEGDec * self) + { ++ self->mirror = DEFAULT_MIRROR; ++ self->rotation = DEFAULT_ROTATION; ++ self->scaleH = DEFAULT_SCALEH; ++ self->scaleV = DEFAULT_SCALEV; + } + + static gboolean +@@ -128,6 +232,15 @@ gst_omx_mjpeg_dec_set_format (GstOMXVide + } + } + #endif ++ if (!gst_omx_jpegdec_set_mirror (dec)) ++ return FALSE; ++ ++ if (!gst_omx_jpegdec_set_rotation (dec)) ++ return FALSE; ++ ++ if (!gst_omx_jpegdec_set_scale (dec)) ++ return FALSE; ++ + gst_omx_port_get_port_definition (port, &port_def); + port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG; + ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone; +@@ -144,6 +257,18 @@ gst_omx_mjpeg_dec_set_property (GObject + case PROP_FRAMERATE: + mjpeg_dec->framerate = g_value_get_int (value); + break; ++ case PROP_MIRROR: ++ mjpeg_dec->mirror = g_value_get_enum (value); ++ break; ++ case PROP_ROTATION: ++ mjpeg_dec->rotation = g_value_get_enum (value); ++ break; ++ case PROP_SCALEH: ++ mjpeg_dec->scaleH = g_value_get_enum (value); ++ break; ++ case PROP_SCALEV: ++ mjpeg_dec->scaleV = g_value_get_enum (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -159,9 +284,164 @@ gst_omx_mjpeg_dec_get_property (GObject + case PROP_FRAMERATE: + g_value_set_int (value, mjpeg_dec->framerate); + break; ++ case PROP_MIRROR: ++ g_value_set_enum (value, mjpeg_dec->mirror); ++ break; ++ case PROP_ROTATION: ++ g_value_set_enum (value, mjpeg_dec->rotation); ++ break; ++ case PROP_SCALEH: ++ g_value_set_enum (value, mjpeg_dec->scaleH); ++ break; ++ case PROP_SCALEV: ++ g_value_set_enum (value, mjpeg_dec->scaleV); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + #endif ++ ++static gboolean ++gst_omx_jpegdec_set_rotation (GstOMXVideoDec * self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_ROTATIONTYPE rotation_config; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ ++ GST_OBJECT_LOCK (self); ++ ++ GST_OMX_INIT_STRUCT (&rotation_config); ++ rotation_config.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonRotate, &rotation_config); ++ ++ if (err == OMX_ErrorNone) { ++ if (mjpeg_dec->rotation >= 0 && mjpeg_dec->rotation <= 270) ++ rotation_config.nRotation = mjpeg_dec->rotation; ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonRotate, &rotation_config); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a rotation not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting rotation settings %u not supported by the component", ++ mjpeg_dec->rotation); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set rotation parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get rotation parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++} ++ ++ ++ ++static gboolean ++gst_omx_jpegdec_set_mirror (GstOMXVideoDec * self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_MIRRORTYPE mirror_config; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ ++ GST_OBJECT_LOCK (self); ++ ++ GST_OMX_INIT_STRUCT (&mirror_config); ++ mirror_config.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonMirror, &mirror_config); ++ ++ if (err == OMX_ErrorNone) { ++ if (mjpeg_dec->mirror >= 0 && mjpeg_dec->mirror <= OMX_MirrorBoth) ++ mirror_config.eMirror = mjpeg_dec->mirror; ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonMirror, &mirror_config); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a mirror not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting mirror settings %u not supported by the component", ++ mjpeg_dec->mirror); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set mirror parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get mirror parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++} ++ ++static gboolean ++gst_omx_jpegdec_set_scale (GstOMXVideoDec * self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_SCALEFACTORTYPE scale_config; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ ++ GST_OBJECT_LOCK (self); ++ ++ GST_OMX_INIT_STRUCT (&scale_config); ++ scale_config.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonScale, &scale_config); ++ ++ if (err == OMX_ErrorNone) { ++ if ((mjpeg_dec->scaleV >= 0 && mjpeg_dec->scaleV <= 3 ) || ++ (mjpeg_dec->scaleH >= 0 && mjpeg_dec->scaleH <= 3)) { ++ scale_config.xWidth = (1 << 16) >> (mjpeg_dec->scaleH & 0x3); ++ scale_config.xHeight = (1 << 16) >> (mjpeg_dec->scaleV & 0x3); ++ } ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonScale, &scale_config); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a scale not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting scale settings %u %u not supported by the component", ++ mjpeg_dec->scaleV, mjpeg_dec->scaleH); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set scale parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get scale parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++} +\ No newline at end of file +diff -purN a/omx/gstomxmjpegdec.h b/omx/gstomxmjpegdec.h +--- a/omx/gstomxmjpegdec.h 2022-10-14 13:42:12.749600862 +0800 ++++ b/omx/gstomxmjpegdec.h 2022-10-14 13:29:24.849638506 +0800 +@@ -55,6 +55,10 @@ struct _GstOMXMJPEGDec + // gst-launch-1.0 -v filesrc location=xxx.mjpeg ! jpegparse ! omxmjpegdec framerate=xxx ! kmssink driver-name=starfive force-modesetting=1 + gint framerate; + #endif ++ guint32 mirror; ++ guint32 scaleH; ++ guint32 scaleV; ++ guint32 rotation; + }; + + struct _GstOMXMJPEGDecClass +@@ -68,3 +72,19 @@ G_END_DECLS + + #endif /* __GST_OMX_MJPEG_DEC_H__ */ + ++typedef enum ROTATIONTYPE ++{ ++ ROTATION_0 = 0, ++ ROTATION_90 = 90, ++ ROTATION_180 = 180, ++ ROTATION_270 = 270, ++} ROTATIONTYPE; ++ ++typedef enum SCALETYPE ++{ ++ SCALEMODE_0 = 0, ++ SCALEMODE1_2, ++ SCALEMODE1_4, ++ SCALEMODE1_8, ++} SCALETYPE; ++ diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0018-support-cut-for-gstomxmjpegdec.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0018-support-cut-for-gstomxmjpegdec.patch new file mode 100644 index 0000000..1ad9e36 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0018-support-cut-for-gstomxmjpegdec.patch @@ -0,0 +1,194 @@ +Support cut property for omxmjpegdec + +Signed-off-by: Leo Lu + +diff -purN a/omx/gstomxmjpegdec.c b/omx/gstomxmjpegdec.c +--- a/omx/gstomxmjpegdec.c 2022-10-14 14:48:24.207804442 +0800 ++++ b/omx/gstomxmjpegdec.c 2022-10-14 14:46:42.979857812 +0800 +@@ -34,6 +34,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg + #define DEFAULT_ROTATION 0 + #define DEFAULT_SCALEH 0 + #define DEFAULT_SCALEV 0 ++#define DEFAULT_ROI "" ++ + #endif + /* prototypes */ + +@@ -43,6 +45,8 @@ static gboolean + gst_omx_jpegdec_set_rotation (GstOMXVideoDec * self); + static gboolean + gst_omx_jpegdec_set_mirror (GstOMXVideoDec * self); ++static gboolean ++gst_omx_jpegdec_set_roi (GstOMXVideoDec * self); + static gboolean gst_omx_mjpeg_dec_is_format_change (GstOMXVideoDec * dec, + GstOMXPort * port, GstVideoCodecState * state); + static gboolean gst_omx_mjpeg_dec_set_format (GstOMXVideoDec * dec, +@@ -65,6 +69,7 @@ enum + PROP_SCALEH, + PROP_SCALEV, + PROP_ROTATION, ++ PROP_ROI, + }; + + /* class initialization */ +@@ -194,6 +199,17 @@ gst_omx_mjpeg_dec_class_init (GstOMXMJPE + GST_OMX_MJPEG_DEC_SCALE_MODE, DEFAULT_SCALEV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + ++ g_object_class_install_property (gobject_class, PROP_ROI, ++ g_param_spec_string ("roi", "ROI", ++ "Cutting image roi=,,, .\n \ ++ roi coord and width/height(from left top).\n \ ++ X Coordinate of the top left corner of the rectangle.\n \ ++ Y Coordinate of the top left corner of the rectangle.\n \ ++ Width of the rectangle.\n \ ++ Height of the rectangle.\n \ ++ EX:omxmjpegdec roi=0,0,800,480", ++ DEFAULT_ROI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ + gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg"); + } + +@@ -204,6 +220,7 @@ gst_omx_mjpeg_dec_init (GstOMXMJPEGDec * + self->rotation = DEFAULT_ROTATION; + self->scaleH = DEFAULT_SCALEH; + self->scaleV = DEFAULT_SCALEV; ++ memset (self->roi, 0, ROI_ARRAY_SIZE); + } + + static gboolean +@@ -240,6 +257,9 @@ gst_omx_mjpeg_dec_set_format (GstOMXVide + + if (!gst_omx_jpegdec_set_scale (dec)) + return FALSE; ++ ++ if (!gst_omx_jpegdec_set_roi (dec)) ++ return FALSE; + + gst_omx_port_get_port_definition (port, &port_def); + port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG; +@@ -269,6 +289,9 @@ gst_omx_mjpeg_dec_set_property (GObject + case PROP_SCALEV: + mjpeg_dec->scaleV = g_value_get_enum (value); + break; ++ case PROP_ROI: ++ strncpy (mjpeg_dec->roi, g_value_get_string (value), ROI_ARRAY_SIZE); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -296,6 +319,9 @@ gst_omx_mjpeg_dec_get_property (GObject + case PROP_SCALEV: + g_value_set_enum (value, mjpeg_dec->scaleV); + break; ++ case PROP_ROI: ++ g_value_set_string (value, mjpeg_dec->roi); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -444,4 +470,81 @@ gst_omx_jpegdec_set_scale (GstOMXVideoDe + + GST_OBJECT_UNLOCK (self); + return result; +-} +\ No newline at end of file ++} ++ ++static gboolean ++gst_omx_jpegdec_set_roi (GstOMXVideoDec *self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_RECTTYPE RectConfig; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ gchar* val; ++ gchar roi_tmp[ROI_ARRAY_SIZE]; ++ strncpy (roi_tmp, mjpeg_dec->roi, ROI_ARRAY_SIZE); ++ ++ GST_OBJECT_LOCK (self); ++ GST_OMX_INIT_STRUCT (&RectConfig); ++ RectConfig.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonScale, &RectConfig); ++ if (err == OMX_ErrorNone) { ++ if (strlen (mjpeg_dec->roi) > 0) { ++ val = strtok (roi_tmp, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nLeft = atoi (val); ++ } ++ val = strtok (NULL, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nTop = atoi (val); ++ } ++ val = strtok (NULL, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nWidth = atoi (val); ++ } ++ val = strtok (NULL, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nHeight = atoi (val); ++ } ++ } else { ++ GST_OBJECT_UNLOCK (self); ++ return TRUE; ++ } ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonOutputCrop, &RectConfig); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a ROI not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting ROI settings %s not supported by the component", mjpeg_dec->roi); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set ROI parameters: %s (0x%08x)", gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get ROI parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++ ++ROI_PARAM_ERROR: ++ GST_ERROR_OBJECT (self, "Invalid ROI parameter: %s", mjpeg_dec->roi); ++ GST_OBJECT_UNLOCK (self); ++ return FALSE; ++} +diff -purN a/omx/gstomxmjpegdec.h b/omx/gstomxmjpegdec.h +--- a/omx/gstomxmjpegdec.h 2022-10-14 14:48:24.207804442 +0800 ++++ b/omx/gstomxmjpegdec.h 2022-10-14 14:42:09.876591323 +0800 +@@ -42,6 +42,8 @@ G_BEGIN_DECLS + typedef struct _GstOMXMJPEGDec GstOMXMJPEGDec; + typedef struct _GstOMXMJPEGDecClass GstOMXMJPEGDecClass; + ++#define ROI_ARRAY_SIZE 128 ++ + struct _GstOMXMJPEGDec + { + GstOMXVideoDec parent; +@@ -59,6 +61,8 @@ struct _GstOMXMJPEGDec + guint32 scaleH; + guint32 scaleV; + guint32 rotation; ++ gchar roi[ROI_ARRAY_SIZE]; ++ + }; + + struct _GstOMXMJPEGDecClass diff --git a/recipes-multimedia/gstreamer/sf-gst-omx/0019-Add-Interlaced-mode-judgment.patch b/recipes-multimedia/gstreamer/sf-gst-omx/0019-Add-Interlaced-mode-judgment.patch new file mode 100644 index 0000000..f8136d9 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx/0019-Add-Interlaced-mode-judgment.patch @@ -0,0 +1,66 @@ +Add Interlaced-mode judgment for gstomxvideodec class +Fix compiler warnings + +Signed-off-by: Leo Lu + +diff -purN a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c +--- a/omx/gstomxvideodec.c 2022-11-03 17:02:54.601333539 +0800 ++++ b/omx/gstomxvideodec.c 2022-11-03 16:06:20.435534119 +0800 +@@ -740,7 +740,7 @@ gst_omx_try_importing_buffer (GstOMXVide + #ifdef USE_OMX_TARGET_STARFIVE + 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", ++ " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %u", + i, port->port_def.nBufferSize); + goto out; + } +@@ -2795,7 +2795,7 @@ gst_omx_video_dec_set_format (GstVideoDe + gboolean needs_disable = FALSE; + OMX_PARAM_PORTDEFINITIONTYPE port_def; + OMX_U32 framerate_q16 = gst_omx_video_calculate_framerate_q16 (info); +- ++ static gboolean interlaced_print_flag = FALSE; + self = GST_OMX_VIDEO_DEC (decoder); + klass = GST_OMX_VIDEO_DEC_GET_CLASS (decoder); + +@@ -2857,9 +2857,17 @@ gst_omx_video_dec_set_format (GstVideoDe + /*We cannot use GST_VIDEO_INFO_FIELD_HEIGHT() as encoded content may use either + * interlace-mode=interleaved or alternate. In both case we'll output alternate + * so the OMX frame height needs to be halfed. */ +- if (GST_VIDEO_INFO_IS_INTERLACED (info)) ++ if (GST_VIDEO_INFO_IS_INTERLACED (info)) { + port_def.format.video.nFrameHeight = + GST_ROUND_UP_2 (port_def.format.video.nFrameHeight / 2); ++ if (!interlaced_print_flag) { ++ g_print("Current stream mode is %s, but just support PROGRESSIVE type. \n", ++ gst_video_interlace_mode_to_string (info->interlace_mode)); ++ GST_ERROR_OBJECT (self, "Just support PROGRESSIVE type "); ++ interlaced_print_flag = TRUE; ++ } ++ return FALSE; ++ } + port_def.format.video.xFramerate = framerate_q16; + + if (klass->cdata.hacks & GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER) { +diff -purN a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c +--- a/omx/gstomxvideoenc.c 2022-11-03 17:02:54.593333485 +0800 ++++ b/omx/gstomxvideoenc.c 2022-11-03 13:46:10.137177818 +0800 +@@ -2136,7 +2136,7 @@ gst_omx_try_importing_buffer (GstOMXVide + + 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", ++ " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %u", + i, port->port_def.nBufferSize); + goto out; + } +@@ -2187,7 +2187,7 @@ gst_omx_video_enc_use_buffers (GstOMXVid + GList *frames = NULL; + OMX_ERRORTYPE err = OMX_ErrorNone; + gboolean is_mapped = FALSE ; +- GST_DEBUG(" nBufferCountActual=%d, nBufferCountMin= %lu", n, port->port_def.nBufferCountMin); ++ GST_DEBUG(" nBufferCountActual=%d, nBufferCountMin= %u", n, port->port_def.nBufferCountMin); + + if ( pool != NULL ) { + guint i; diff --git a/recipes-multimedia/gstreamer/sf-gst-omx_1.18.5.bb b/recipes-multimedia/gstreamer/sf-gst-omx_1.18.5.bb new file mode 100644 index 0000000..57815c3 --- /dev/null +++ b/recipes-multimedia/gstreamer/sf-gst-omx_1.18.5.bb @@ -0,0 +1,79 @@ +SUMMARY = "OpenMAX IL plugins for GStreamer" +DESCRIPTION = "Wraps available OpenMAX IL components and makes them available as standard GStreamer elements." +HOMEPAGE = "http://gstreamer.freedesktop.org/" +SECTION = "multimedia" + +LICENSE = "LGPL-2.1-or-later" +LICENSE_FLAGS = "commercial" +LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \ + file://omx/gstomx.h;beginline=1;endline=21;md5=5c8e1fca32704488e76d2ba9ddfa935f" + +SRC_URI = " \ + https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-${PV}.tar.xz \ +" + +SRC_URI[sha256sum] = "2cd457c1e8deb1a9b39608048fb36a44f6c9a864a6b6115b1453a32e7be93b42" + +S = "${WORKDIR}/gst-omx-${PV}" + +DEPENDS = "gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-bad virtual/libomxil" + +inherit meson pkgconfig upstream-version-is-even + +GSTREAMER_1_0_OMX_TARGET ?= "bellagio" +GSTREAMER_1_0_OMX_CORE_NAME ?= "${libdir}/libomxil-bellagio.so.0" + +EXTRA_OEMESON += "-Dtarget=${GSTREAMER_1_0_OMX_TARGET}" + +python __anonymous () { + omx_target = d.getVar("GSTREAMER_1_0_OMX_TARGET") + if omx_target in ['generic', 'bellagio']: + # Bellagio headers are incomplete (they are missing the OMX_VERSION_MAJOR,# + # OMX_VERSION_MINOR, OMX_VERSION_REVISION, and OMX_VERSION_STEP macros); + # appending a directory path to gst-omx' internal OpenMAX IL headers fixes this + d.appendVar("CFLAGS", " -I${S}/omx/openmax") + elif omx_target == "rpi": + # Dedicated Raspberry Pi OpenMAX IL support makes this package machine specific + d.setVar("PACKAGE_ARCH", d.getVar("MACHINE_ARCH")) +} + +set_omx_core_name() { + sed -i -e "s;^core-name=.*;core-name=${GSTREAMER_1_0_OMX_CORE_NAME};" "${D}${sysconfdir}/xdg/gstomx.conf" +} +do_install[postfuncs] += " set_omx_core_name " + +FILES:${PN} += "${libdir}/gstreamer-1.0/*.so" +FILES:${PN}-staticdev += "${libdir}/gstreamer-1.0/*.a" + +VIRTUAL-RUNTIME_libomxil ?= "libomxil" +RDEPENDS:${PN} = "${VIRTUAL-RUNTIME_libomxil}" + +# TODO this recipe is currently a WIP patch set +# in order to make life easier, the above is a verbatim copy of the original recipe, all VisionFive2 specific parts go below: +# from the above, only the recipe version and checksum is different to poky to ease patch applying + +SRC_URI += " \ + file://0001-add-starfive-support.patch \ + file://0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch \ + file://0003-add-video-scale-support.patch \ + file://0004-add-encoder-support.patch \ + file://0005-rank-257-for-sf-codecs.patch \ + file://0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch \ + file://0007-add-omxmjpegdec-support.patch \ + file://0008-support-nv21-i422-y444-for-omxmjpegdec.patch \ + file://0009-suport-usebuffer-mode-for-encoding.patch \ + file://0010-add-property-framerate.patch \ + file://0011-hanle-some-extra-profile-for-avc.patch \ + file://0012-combine-sps-pps-header-to-idr.patch \ + file://0013-Modify-sf-component-name-to-in-std-format.patch \ + file://0014-support-nv21-for-omxh264_5dec.patch \ + file://0015_Add_NV21_for_gstomxvideoenc_class.patch \ + file://0016-Modify-gstomxmjpegdec-format.patch \ + file://0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch \ + file://0018-support-cut-for-gstomxmjpegdec.patch \ + file://0019-Add-Interlaced-mode-judgment.patch \ +" +GSTREAMER_1_0_OMX_TARGET:visionfive2 = "stf" +GSTREAMER_1_0_OMX_CORE_NAME:visionfive2 = "${libdir}/libsf-omx-il.so" +EXTRA_OEMESON:append:visionfive2 = " -Dheader_path=${STAGING_DIR_TARGET}/usr/include/khronos" +VIRTUAL-RUNTIME_libomxil:visionfive2 = "libsf-omxil"