Add HW video engine support (#179)

* Add Cedar HW video decoder support

* Add sunxifbsink gstreamer plugin

* sunxifbsink: remove warning log
gst-omx: remove resolution check after crop

* Add gstreamer scripts

* review comments fixes

* ffmpeg: enable h264_omx encoder

* add missing hashes and use defined git commit for libcedar

* mv miyoo specific patches to board

* make `gst-omx.mk` less platform specfic

* Add header python interpreter to gst-raw.py

* Add videoscale with nearest-neighbour to play video with higher resolutions fluently

* Use HW scaler

* libcedarc: fix crash when playing 640x480 video

* kernel: Add patch to increase VRAM

* Add fast gstreamer player

* fix gst-play hangs

* Add matroska plugin

* remove target

---------

Co-authored-by: Apaczer <94932128+Apaczer@users.noreply.github.com>
This commit is contained in:
tiopex
2025-07-21 13:11:52 +02:00
committed by GitHub
parent e306510c79
commit c336dad699
31 changed files with 5363 additions and 27 deletions

View File

@@ -0,0 +1,38 @@
diff --git a/arch/arm/configs/miyoo_defconfig b/arch/arm/configs/miyoo_defconfig
index f9cb0790f..625b5a30f 100644
--- a/arch/arm/configs/miyoo_defconfig
+++ b/arch/arm/configs/miyoo_defconfig
@@ -83,6 +83,12 @@ CONFIG_SUNXI_WATCHDOG=y
CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_MEDIA_CEC_SUPPORT is not set
+CONFIG_MEDIA_SUPPORT=y
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+# CONFIG_DVB_NET is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_FB=y
CONFIG_FB_MIYOO_VIDEO=y
CONFIG_FB_R61520=m
@@ -122,6 +128,10 @@ CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_MMC=y
CONFIG_MMC_SUNXI=y
CONFIG_STAGING=y
+CONFIG_STAGING_MEDIA=y
+CONFIG_VIDEO_SUNXI=y
+CONFIG_VIDEO_SUNXI_CEDAR_VE=y
+CONFIG_VIDEO_SUNXI_CEDAR_ION=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_PWM=y
CONFIG_PWM_SUNIV=y
@@ -144,6 +154,9 @@ CONFIG_CRYPTO_DRBG_MENU=y
# CONFIG_CRYPTO_HW is not set
CONFIG_LIBCRC32C=y
CONFIG_XZ_DEC=y
+CONFIG_DMA_PERNUMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=12
+CONFIG_CMA_ALIGNMENT=4
CONFIG_PRINTK_TIME=y
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4
# CONFIG_FTRACE is not set

View File

@@ -0,0 +1,95 @@
From 16996fbd2c84692c6bc8c426524e870a6c826550 Mon Sep 17 00:00:00 2001
From: tiopex <tiopxyz@gmail.com>
Date: Fri, 11 Jul 2025 23:57:28 +0200
Subject: [PATCH] video: increase VRAM
---
drivers/video/fbdev/gc9306fb.c | 2 +-
drivers/video/fbdev/hx8347dfb.c | 2 +-
drivers/video/fbdev/r61520fb.c | 2 +-
drivers/video/fbdev/rm68090fb.c | 2 +-
drivers/video/fbdev/st7789sTEfb.c | 2 +-
drivers/video/fbdev/st7789sfb.c | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/video/fbdev/gc9306fb.c b/drivers/video/fbdev/gc9306fb.c
index 4ecfbe9fb..f4cfef6a1 100644
--- a/drivers/video/fbdev/gc9306fb.c
+++ b/drivers/video/fbdev/gc9306fb.c
@@ -613,7 +613,7 @@ static int myfb_probe(struct platform_device *device)
par->bpp = 16;
fb_videomode_to_var(&myfb_var, mode);
- par->vram_size = 320 * 240 * 2 * 2;
+ par->vram_size = 640 * 480 * 2 * 2;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_size, (resource_size_t*)&par->vram_phys, GFP_KERNEL | GFP_DMA);
if(!par->vram_virt){
return -EINVAL;
diff --git a/drivers/video/fbdev/hx8347dfb.c b/drivers/video/fbdev/hx8347dfb.c
index c6b337999..80a0cc639 100644
--- a/drivers/video/fbdev/hx8347dfb.c
+++ b/drivers/video/fbdev/hx8347dfb.c
@@ -748,7 +748,7 @@ static int myfb_probe(struct platform_device *device)
par->bpp = 16;
fb_videomode_to_var(&myfb_var, mode);
- par->vram_size = 320*240*2*2;
+ par->vram_size = 640*480*2*2;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_size, (resource_size_t*)&par->vram_phys, GFP_KERNEL | GFP_DMA);
if(!par->vram_virt){
dev_err(&device->dev, "%s, failed to allocate frame buffer(vram)\n", __func__);
diff --git a/drivers/video/fbdev/r61520fb.c b/drivers/video/fbdev/r61520fb.c
index ca1d8562f..c657efc70 100644
--- a/drivers/video/fbdev/r61520fb.c
+++ b/drivers/video/fbdev/r61520fb.c
@@ -1566,7 +1566,7 @@ static int myfb_probe(struct platform_device *device)
par->bpp = 16;
fb_videomode_to_var(&myfb_var, mode);
- par->vram_size = 320*240*2*2;
+ par->vram_size = 640*480*2*2;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_size, (resource_size_t*)&par->vram_phys, GFP_KERNEL | GFP_DMA);
if(!par->vram_virt){
dev_err(&device->dev, "%s, failed to allocate frame buffer(vram)\n", __func__);
diff --git a/drivers/video/fbdev/rm68090fb.c b/drivers/video/fbdev/rm68090fb.c
index b3dcbe48b..1cf7268a7 100644
--- a/drivers/video/fbdev/rm68090fb.c
+++ b/drivers/video/fbdev/rm68090fb.c
@@ -684,7 +684,7 @@ static int myfb_probe(struct platform_device *device)
par->bpp = 16;
fb_videomode_to_var(&myfb_var, mode);
- par->vram_size = 320*240*2*2;
+ par->vram_size = 640*480*2*2;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_size, (resource_size_t*)&par->vram_phys, GFP_KERNEL | GFP_DMA);
if(!par->vram_virt){
dev_err(&device->dev, "%s, failed to allocate frame buffer(vram)\n", __func__);
diff --git a/drivers/video/fbdev/st7789sTEfb.c b/drivers/video/fbdev/st7789sTEfb.c
index ee895b575..176f11416 100644
--- a/drivers/video/fbdev/st7789sTEfb.c
+++ b/drivers/video/fbdev/st7789sTEfb.c
@@ -687,7 +687,7 @@ static int myfb_probe(struct platform_device *device)
par->bpp = 16;
fb_videomode_to_var(&myfb_var, mode);
- par->vram_size = (320 * 240 * 2 * 4) + 4096;
+ par->vram_size = (640 * 480 * 2 * 4) + 4096;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_size, (resource_size_t *)&par->vram_phys, GFP_KERNEL | GFP_DMA);
if(!par->vram_virt) {
return -EINVAL;
diff --git a/drivers/video/fbdev/st7789sfb.c b/drivers/video/fbdev/st7789sfb.c
index 28ef0ce8c..8867701ad 100644
--- a/drivers/video/fbdev/st7789sfb.c
+++ b/drivers/video/fbdev/st7789sfb.c
@@ -806,7 +806,7 @@ static int myfb_probe(struct platform_device *device)
par->bpp = 16;
fb_videomode_to_var(&myfb_var, mode);
- par->vram_size = (320 * 240 * 2 * 4) + 4096;
+ par->vram_size = (640 * 480 * 2 * 4) + 4096;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_size, (resource_size_t*)&par->vram_phys, GFP_KERNEL | GFP_DMA);
if (!par->vram_virt) {
return -EINVAL;
--
2.34.1

View File

@@ -0,0 +1,4 @@
title=Gstreamer HW player
description=Play a movie/audio file using HW decoder cedar
exec=/usr/bin/gst-play
selectordir=/mnt/output

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,340 @@
From 863e52e8f34c2c23c3411272734c7bed28c2d5fc Mon Sep 17 00:00:00 2001
From: xiebin <xiebin@allwinnertech.com>
Date: Thu, 1 Jun 2017 17:04:53 +0800
Subject: [PATCH 2/2] add mjpeg and remove h263 and mpeg4 encoder
---
config/bellagio/gstomx.conf | 20 +----
omx/Makefile.am | 6 +-
omx/gstomx.c | 3 +-
omx/gstomxmjpegenc.c | 174 ++++++++++++++++++++++++++++++++++++++++++++
omx/gstomxmjpegenc.h | 59 +++++++++++++++
5 files changed, 240 insertions(+), 22 deletions(-)
create mode 100644 omx/gstomxmjpegenc.c
create mode 100644 omx/gstomxmjpegenc.h
diff --git a/config/bellagio/gstomx.conf b/config/bellagio/gstomx.conf
index cf27588..8aaa01a 100644
--- a/config/bellagio/gstomx.conf
+++ b/config/bellagio/gstomx.conf
@@ -187,26 +187,8 @@ in-port-index=0
out-port-index=1
hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
-[omxh263videoenc]
-type-name=GstOMXH263Enc
-core-name=/usr/lib/libcdc_omxil_core.so
-component-name=OMX.allwinner.video.encoder.h263
-rank=257
-in-port-index=0
-out-port-index=1
-hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
-
-[omxmpeg4videoenc]
-type-name=GstOMXMPEG4VideoEnc
-core-name=/usr/lib/libcdc_omxil_core.so
-component-name=OMX.allwinner.video.encoder.mpeg4
-rank=257
-in-port-index=0
-out-port-index=1
-hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
-
[omxmjpegvideoenc]
-type-name=GstOMXMJPEGVideoEnc
+type-name=GstOMXMJPEGEnc
core-name=/usr/lib/libOmxCore.so
component-name=OMX.allwinner.video.encoder.mjpeg
rank=257
diff --git a/omx/Makefile.am b/omx/Makefile.am
index b3627f7..f7596dd 100644
--- a/omx/Makefile.am
+++ b/omx/Makefile.am
@@ -51,7 +51,8 @@ libgstomx_la_SOURCES = \
gstomxrv20dec.c \
gstomxdivx4dec.c \
gstomxrxdec.c \
- gstomxavsdec.c
+ gstomxavsdec.c \
+ gstomxmjpegenc.c
noinst_HEADERS = \
gstomx.h \
@@ -94,7 +95,8 @@ noinst_HEADERS = \
gstomxrv20dec.h \
gstomxdivx4dec.h \
gstomxrxdec.h \
- gstomxavsdec.h
+ gstomxavsdec.h \
+ gstomxmjpegenc.h
if !HAVE_EXTERNAL_OMX
OMX_INCLUDEPATH = -I$(abs_srcdir)/openmax
diff --git a/omx/gstomx.c b/omx/gstomx.c
index 31c43e3..175b350 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -61,6 +61,7 @@
#include "gstomxdivx4dec.h"
#include "gstomxrxdec.h"
#include "gstomxavsdec.h"
+#include "gstomxmjpegenc.h"
GST_DEBUG_CATEGORY (gstomx_debug);
@@ -2301,7 +2302,7 @@ static const GGetTypeFunction types[] = {
gst_omx_vp9_dec_get_type, gst_omx_h265_dec_get_type,
gst_omx_flv1_dec_get_type, gst_omx_rv20_dec_get_type,
gst_omx_rx_dec_get_type, gst_omx_divx4_dec_get_type,
- gst_omx_avs_dec_get_type
+ gst_omx_avs_dec_get_type, gst_omx_mjpeg_enc_get_type
#ifdef HAVE_VP8
, gst_omx_vp8_dec_get_type
#endif
diff --git a/omx/gstomxmjpegenc.c b/omx/gstomxmjpegenc.c
new file mode 100644
index 0000000..ed2234e
--- /dev/null
+++ b/omx/gstomxmjpegenc.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmjpegenc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mjpeg_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mjpeg_enc_set_format (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_mjpeg_enc_get_caps (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mjpeg_enc_debug_category, "omxmjpegenc", 0, \
+ "debug category for gst-omx video encoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMJPEGEnc, gst_omx_mjpeg_enc,
+ GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+static void
+gst_omx_mjpeg_enc_class_init (GstOMXMJPEGEncClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+ printf("mjpeg class init!\n");
+ videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_enc_set_format);
+ videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_enc_get_caps);
+
+ videoenc_class->cdata.default_src_template_caps = "image/jpeg";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX Mjpeg Video Encoder",
+ "Codec/Encoder/Video",
+ "Encode Mjpeg video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.mjpeg");
+}
+
+static void
+gst_omx_mjpeg_enc_init (GstOMXMJPEGEnc * self)
+{
+}
+
+static gboolean
+gst_omx_mjpeg_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXMJPEGEnc *self = GST_OMX_MJPEG_ENC (enc);
+ GstCaps *peercaps;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ OMX_ERRORTYPE err;
+ guint profile_id, level_id;
+
+ gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG;
+ err =
+ gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+ (self)->enc_out_port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting profile/level not supported by component");
+ return TRUE;
+ }
+
+ peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+ if (peercaps) {
+ GstStructure *s;
+
+ if (gst_caps_is_empty (peercaps)) {
+ gst_caps_unref (peercaps);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (peercaps, 0);
+ gst_caps_unref (peercaps);
+ }
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting profile/level not supported by component");
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %u", profile_id);
+ gst_caps_unref (peercaps);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %u", level_id);
+ gst_caps_unref (peercaps);
+ return FALSE;
+}
+
+static GstCaps *
+gst_omx_mjpeg_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXMJPEGEnc *self = GST_OMX_MJPEG_ENC (enc);
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ guint profile, level;
+
+ caps = gst_caps_new_empty_simple ("image/jpeg");
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex) {
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ return caps;
+}
diff --git a/omx/gstomxmjpegenc.h b/omx/gstomxmjpegenc.h
new file mode 100644
index 0000000..e053d04
--- /dev/null
+++ b/omx/gstomxmjpegenc.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_MJPEG_ENC_H__
+#define __GST_OMX_MJPEG_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MJPEG_ENC \
+ (gst_omx_mjpeg_enc_get_type())
+#define GST_OMX_MJPEG_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MJPEG_ENC,GstOMXMJPEGEnc))
+#define GST_OMX_MJPEG_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MJPEG_ENC,GstOMXMJPEGEncClass))
+#define GST_OMX_MJPEG_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MJPEG_ENC,GstOMXMJPEGEncClass))
+#define GST_IS_OMX_MJPEG_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MJPEG_ENC))
+#define GST_IS_OMX_MJPEG_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MJPEG_ENC))
+
+typedef struct _GstOMXMJPEGEnc GstOMXMJPEGEnc;
+typedef struct _GstOMXMJPEGEncClass GstOMXMJPEGEncClass;
+
+struct _GstOMXMJPEGEnc
+{
+ GstOMXVideoEnc parent;
+};
+
+struct _GstOMXMJPEGEncClass
+{
+ GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_mjpeg_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MJPEG_ENC_H__ */
--
2.7.4

View File

@@ -0,0 +1,83 @@
From d3096c4fc4e7d13647df55a7c74dc5ba1e143bc7 Mon Sep 17 00:00:00 2001
From: xiebin <xiebin@allwinnertech.com>
Date: Tue, 2 Jan 2018 17:20:30 +0800
Subject: [PATCH 4/4] add for zero copy
---
omx/gstomxbufferpool.c | 7 ++++++-
omx/gstomxvideo.c | 3 +++
omx/openmax/OMX_IVCommon.h | 12 ++++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c
index b57612d..607bee8 100644
--- a/omx/gstomxbufferpool.c
+++ b/omx/gstomxbufferpool.c
@@ -344,6 +344,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
GstBuffer *buf;
GstOMXBuffer *omx_buf;
+ GstMemoryFlags flags = 0;
g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR);
@@ -389,7 +390,10 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
- mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
+ if(pool->port->port_def.bBuffersContiguous)
+ flags|= GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS;
+
+ mem = gst_omx_memory_allocator_alloc (pool->allocator, flags, omx_buf);
buf = gst_buffer_new ();
gst_buffer_append_memory (buf, mem);
g_ptr_array_add (pool->buffers, buf);
@@ -405,6 +409,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
case GST_VIDEO_FORMAT_GRAY8:
break;
case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
stride[1] = nstride / 2;
offset[1] = offset[0] + stride[0] * nslice;
stride[2] = nstride / 2;
diff --git a/omx/gstomxvideo.c b/omx/gstomxvideo.c
index 8a42c71..fd4cad4 100644
--- a/omx/gstomxvideo.c
+++ b/omx/gstomxvideo.c
@@ -44,6 +44,9 @@ gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat)
case OMX_COLOR_FormatYUV420PackedPlanar:
format = GST_VIDEO_FORMAT_I420;
break;
+ case OMX_COLOR_FormatYVU420Planar:
+ format = GST_VIDEO_FORMAT_YV12;
+ break;
case OMX_COLOR_FormatYUV420SemiPlanar:
case OMX_COLOR_FormatYUV420PackedSemiPlanar:
format = GST_VIDEO_FORMAT_NV12;
diff --git a/omx/openmax/OMX_IVCommon.h b/omx/openmax/OMX_IVCommon.h
index 4c4995c..367670b 100644
--- a/omx/openmax/OMX_IVCommon.h
+++ b/omx/openmax/OMX_IVCommon.h
@@ -132,6 +132,18 @@ typedef enum OMX_COLOR_FORMATTYPE {
OMX_COLOR_Format24BitABGR6666,
OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ //* extended by aw;
+ OMX_COLOR_FormatYVU420SemiPlanar,
+ OMX_COLOR_FormatYVU420Planar,
+ //* end;
+
+ OMX_COLOR_FormatAndroidOpaque = 0x7F000789,
+ OMX_COLOR_FormatYUV420Flexible = 0x7F420888,
+ OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
+ OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
+ OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03,
+ OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002,
+ OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04,
OMX_COLOR_FormatMax = 0x7FFFFFFF
} OMX_COLOR_FORMATTYPE;
--
2.7.4

View File

@@ -0,0 +1,33 @@
>From 6b2c45cc5c93bd3d19467ffc22195d8dad32545f Mon Sep 17 00:00:00 2001
From: xiebin <xiebin@allwinnertech.com>
Date: Wed, 31 Jan 2018 13:38:08 +0800
Subject: [PATCH 5/5] patch for omx drop frames
---
omx/gstomxvideodec.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 79b4daa..a88bdba 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -2171,6 +2171,7 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
guint offset = 0, size;
GstClockTime timestamp, duration;
OMX_ERRORTYPE err;
+ static int drop_num = 0;
self = GST_OMX_VIDEO_DEC (decoder);
klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
@@ -2178,7 +2179,7 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
GST_DEBUG_OBJECT (self, "Handling frame");
if (!self->started) {
- if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
+ if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && drop_num++ < 20) {
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
return GST_FLOW_OK;
}
--
2.7.4

View File

@@ -0,0 +1,56 @@
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index bfad2f3..36b6927 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -1022,6 +1022,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
case GST_VIDEO_FORMAT_I420:
port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
break;
+ case GST_VIDEO_FORMAT_YV12:
+ port_def.format.video.eColorFormat = OMX_COLOR_FormatYVU420Planar;
+ break;
case GST_VIDEO_FORMAT_NV12:
port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
break;
@@ -1057,6 +1060,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
switch (port_def.format.video.eColorFormat) {
case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYVU420Planar:
case OMX_COLOR_FormatYUV420PackedPlanar:
port_def.nBufferSize =
(port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
@@ -1135,8 +1139,13 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
}
GST_DEBUG_OBJECT (self, "Updating outport port definition");
+
+ gst_omx_port_get_port_definition (self->enc_out_port, &port_def);
+ port_def.format.video.nFrameWidth = info->width;
+ port_def.format.video.nFrameHeight = info->height;
+
if (gst_omx_port_update_port_definition (self->enc_out_port,
- NULL) != OMX_ErrorNone)
+ &port_def) != OMX_ErrorNone)
return FALSE;
if (self->target_bitrate != 0xffffffff) {
@@ -1285,7 +1294,7 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
{
GstVideoCodecState *state = gst_video_codec_state_ref (self->input_state);
GstVideoInfo *info = &state->info;
- OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->enc_in_port->port_def;
+ OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->enc_out_port->port_def;
gboolean ret = FALSE;
GstVideoFrame frame;
@@ -1310,7 +1319,8 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
/* Different strides */
switch (info->finfo->format) {
- case GST_VIDEO_FORMAT_I420:{
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:{
gint i, j, height, width;
guint8 *src, *dest;
gint src_stride, dest_stride;

View File

@@ -0,0 +1,12 @@
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 79b4daa..bbd123c 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -476,6 +476,7 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
break;
case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
src_stride[1] = nstride / 2;
src_size[1] = (src_stride[1] * nslice) / 2;

View File

@@ -0,0 +1,123 @@
diff --git a/omx/gstomxh264enc.c b/omx/gstomxh264enc.c
index aa33ae5..48ef3d7 100644
--- a/omx/gstomxh264enc.c
+++ b/omx/gstomxh264enc.c
@@ -30,6 +30,7 @@
#include <OMX_Broadcom.h>
#include <OMX_Index.h>
#endif
+#include "OMX_IndexExt.h"
GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_enc_debug_category);
#define GST_CAT_DEFAULT gst_omx_h264_enc_debug_category
@@ -54,6 +55,7 @@ enum
#ifdef USE_OMX_TARGET_RPI
PROP_INLINESPSPPSHEADERS,
#endif
+ PROP_BYTE_STREAM,
PROP_PERIODICITYOFIDRFRAMES,
PROP_INTERVALOFCODINGINTRAFRAMES
};
@@ -61,6 +63,7 @@ enum
#ifdef USE_OMX_TARGET_RPI
#define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT TRUE
#endif
+#define GST_OMX_H264_VIDEO_ENC_BYTE_STREAM_DEFAULT FALSE
#define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT (0xffffffff)
#define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
@@ -98,6 +101,11 @@ gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
#endif
+ g_object_class_install_property (gobject_class, PROP_BYTE_STREAM,
+ g_param_spec_boolean ("byte-stream", "Byte Stream",
+ "Generate byte stream format of NALU",
+ GST_OMX_H264_VIDEO_ENC_BYTE_STREAM_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
g_param_spec_uint ("periodicty-idr", "Target Bitrate",
@@ -146,6 +154,8 @@ gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
self->inline_sps_pps_headers = g_value_get_boolean (value);
break;
#endif
+ case PROP_BYTE_STREAM:
+ self->byte_stream = g_value_get_boolean (value);
case PROP_PERIODICITYOFIDRFRAMES:
self->periodicty_idr = g_value_get_uint (value);
break;
@@ -170,6 +180,9 @@ gst_omx_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
g_value_set_boolean (value, self->inline_sps_pps_headers);
break;
#endif
+ case PROP_BYTE_STREAM:
+ g_value_set_boolean (value, self->byte_stream);
+ break;
case PROP_PERIODICITYOFIDRFRAMES:
g_value_set_uint (value, self->periodicty_idr);
break;
@@ -189,6 +202,7 @@ gst_omx_h264_enc_init (GstOMXH264Enc * self)
self->inline_sps_pps_headers =
GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
#endif
+ self->byte_stream = GST_OMX_H264_VIDEO_ENC_BYTE_STREAM_DEFAULT;
self->periodicty_idr =
GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
self->interval_intraframes =
@@ -226,6 +240,7 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
OMX_PARAM_PORTDEFINITIONTYPE port_def;
OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
OMX_VIDEO_CONFIG_AVCINTRAPERIOD config_avcintraperiod;
+ OMX_NALSTREAMFORMATTYPE config_nalstreamformattype;
#ifdef USE_OMX_TARGET_RPI
OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
#endif
@@ -263,6 +278,35 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
}
#endif
+ if (self->byte_stream != GST_OMX_H264_VIDEO_ENC_BYTE_STREAM_DEFAULT) {
+ GST_OMX_INIT_STRUCT (&config_nalstreamformattype);
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamNalStreamFormat, &config_nalstreamformattype);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't get OMX_IndexParamNalStreamFormat %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "default Nal Stream Format:%u",
+ (guint) config_nalstreamformattype.eNaluFormat);
+
+ if (self->byte_stream != GST_OMX_H264_VIDEO_ENC_BYTE_STREAM_DEFAULT)
+ config_nalstreamformattype.eNaluFormat = OMX_NaluFormatFourByteInterleaveLength;
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamNalStreamFormat, &config_nalstreamformattype);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't set OMX_IndexParamNalStreamFormat %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+ }
+
if (self->periodicty_idr !=
GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
|| self->interval_intraframes !=
diff --git a/omx/gstomxh264enc.h b/omx/gstomxh264enc.h
index 03326e1..d962d7b 100644
--- a/omx/gstomxh264enc.h
+++ b/omx/gstomxh264enc.h
@@ -46,6 +46,7 @@ struct _GstOMXH264Enc
{
GstOMXVideoEnc parent;
+ gboolean byte_stream;
#ifdef USE_OMX_TARGET_RPI
gboolean inline_sps_pps_headers;
#endif

View File

@@ -0,0 +1,85 @@
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 38de95b..894f813 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -1879,9 +1879,12 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
+ /*
gst_omx_video_dec_drain (decoder);
gst_omx_video_dec_flush (decoder);
gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
+ */
+ gst_omx_video_dec_flush (decoder);
if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
@@ -1901,7 +1904,7 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
}
#endif
-
+ /*
if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
return FALSE;
if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
@@ -1921,7 +1924,7 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
return FALSE;
if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
return FALSE;
-
+ */
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
if (self->eglimage) {
OMX_STATETYPE egl_state;
@@ -1959,6 +1962,9 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
self->input_state = NULL;
GST_DEBUG_OBJECT (self, "Decoder drained and disabled");
+ /* The local port_def is now obsolete so get it again. */
+ if (!needs_disable)
+ gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
}
port_def.format.video.nFrameWidth = info->width;
@@ -1994,15 +2000,17 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
if (needs_disable) {
if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
return FALSE;
+ /*
if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
return FALSE;
-
+ */
if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
return FALSE;
+ /*
if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
return FALSE;
-
+ */
if (gst_omx_port_wait_enabled (self->dec_out_port,
5 * GST_SECOND) != OMX_ErrorNone)
return FALSE;
@@ -2100,7 +2108,9 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
/* 1) Flush the ports */
GST_DEBUG_OBJECT (self, "flushing ports");
+ /*
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ */
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
@@ -2129,7 +2139,9 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
#endif
/* 4) Unset flushing to allow ports to accept data again */
+ /*
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+ */
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)

View File

@@ -0,0 +1,38 @@
From 68550592fadb8aae28f3c84813e76d2c07ba4059 Mon Sep 17 00:00:00 2001
From: tiopex <tiopxyz@gmail.com>
Date: Wed, 11 Jun 2025 13:14:33 +0200
Subject: [PATCH] Remove check error on port disabling
---
omx/gstomx.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/omx/gstomx.c b/omx/gstomx.c
index 038ce32..d9f8af0 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -3185,8 +3185,8 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
if (timeout == 0) {
if (port->enabled_pending || port->disabled_pending)
- err = OMX_ErrorTimeout;
- goto done;
+ err = OMX_ErrorNone;
+ //goto done;
}
/* And now wait until the enable/disable command is finished */
@@ -3210,8 +3210,8 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
GST_ERROR_OBJECT (comp->parent,
"Timeout waiting for %s port %u to be %s", comp->name, port->index,
(enabled ? "enabled" : "disabled"));
- err = OMX_ErrorTimeout;
- goto done;
+ err = OMX_ErrorNone;
+ //goto done;
} else if (last_error != OMX_ErrorNone) {
GST_ERROR_OBJECT (comp->parent,
"Got error while waiting for %s port %u to be %s: %s (0x%08x)",
--
2.34.1

View File

@@ -0,0 +1,60 @@
From 50913a1d0fe6f3b074f1dd3847ed5ffb401284a9 Mon Sep 17 00:00:00 2001
From: tiopxyz <tiopxyz@gmail.com>
Date: Mon, 7 Jul 2025 13:45:56 +0200
Subject: [PATCH] Add gst-raw.py script
---
config/miyoo/gst-raw.py | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 config/miyoo/gst-raw.py
diff --git a/config/miyoo/gst-raw.py b/config/miyoo/gst-raw.py
new file mode 100644
index 0000000..4ccfb0f
--- /dev/null
+++ b/config/miyoo/gst-raw.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+import subprocess
+import sys
+import termios
+import tty
+import signal
+
+if len(sys.argv) < 2:
+ print("Usage: python3 p.py <filename>")
+ sys.exit(1)
+
+filename = sys.argv[1]
+
+cmd = [
+ 'gst-launch-1.0',
+ 'filesrc', 'location=' + filename,
+ '!', 'qtdemux', 'name=demux',
+ 'demux.audio_0', '!', 'queue', '!', 'decodebin', '!', 'audioconvert', '!', 'alsasink',
+ 'demux.video_0', '!', 'queue', '!', 'decodebin', '!',
+ 'sunxifbsink', 'hardware-overlay=true', 'video-memory=2', 'buffer-pool=true', 'full-screen=true', '-e', '-q', '-f'
+]
+
+proc = subprocess.Popen(cmd)
+
+def get_key():
+ fd = sys.stdin.fileno()
+ old = termios.tcgetattr(fd)
+ try:
+ tty.setraw(fd)
+ ch = sys.stdin.read(1)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old)
+ return ch
+
+_ = get_key()
+print("Key pressed, terminating gst-launch...")
+proc.send_signal(signal.SIGINT)
+
+proc.wait()
+print("gst-launch stopped.")
+
--
2.34.1

View File

@@ -0,0 +1,25 @@
From 625e183efb5a59434c14b008696e54224014adda Mon Sep 17 00:00:00 2001
From: tiopex <tiopxyz@gmail.com>
Date: Fri, 20 Jun 2025 23:41:18 +0200
Subject: [PATCH] omxvideodec: remove resolution check with goto in fill_buffer
---
omx/gstomxvideodec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index e044c78..e441cd4 100755
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -544,7 +544,7 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
(guint) port_def->format.video.nFrameWidth,
(guint) port_def->format.video.nFrameHeight,
vinfo->width, vinfo->height);
- goto done;
+ //goto done;
}
/* Same strides and everything */
--
2.34.1

View File

@@ -0,0 +1,313 @@
From 4422f386b9dd03980f93563d57b1eaf9e72e1f0a Mon Sep 17 00:00:00 2001
From: tiopex <tiopxyz@gmail.com>
Date: Tue, 15 Jul 2025 11:24:51 +0200
Subject: [PATCH] gst-play
---
Makefile.am | 2 +-
configure.ac | 1 +
player/Makefile.am | 5 +
player/gst-play.c | 257 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 264 insertions(+), 1 deletion(-)
create mode 100644 player/Makefile.am
create mode 100644 player/gst-play.c
diff --git a/Makefile.am b/Makefile.am
index 82affc6..e8c9581 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = common omx tools config m4
+SUBDIRS = common omx tools config m4 player
if BUILD_EXAMPLES
SUBDIRS += examples
diff --git a/configure.ac b/configure.ac
index b1ef5fa..f2a98ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -388,6 +388,7 @@ config/rpi/Makefile
examples/Makefile
examples/egl/Makefile
m4/Makefile
+player/Makefile
)
AC_OUTPUT
diff --git a/player/Makefile.am b/player/Makefile.am
new file mode 100644
index 0000000..a8f7c4c
--- /dev/null
+++ b/player/Makefile.am
@@ -0,0 +1,5 @@
+bin_PROGRAMS = gst-play
+
+gst_play_SOURCES = gst-play.c
+gst_play_CFLAGS = $(GST_CFLAGS)
+gst_play_LDADD = $(GST_LIBS)
diff --git a/player/gst-play.c b/player/gst-play.c
new file mode 100644
index 0000000..c1a5fa7
--- /dev/null
+++ b/player/gst-play.c
@@ -0,0 +1,257 @@
+#include <gst/gst.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <termios.h>
+#include <unistd.h>
+
+void reset_terminal_mode(void);
+void set_conio_terminal_mode(void);
+int kbhit(void);
+void int_handler(int dummy);
+static void on_pad_added(GstElement *src, GstPad *pad, gpointer user_data);
+
+static gboolean running = TRUE;
+static GstElement *pipeline;
+static GstElement *video_sink;
+static gboolean paused = FALSE;
+
+static struct termios orig_termios;
+
+void reset_terminal_mode(void) {
+ tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
+}
+
+void set_conio_terminal_mode(void) {
+ struct termios new_termios;
+
+ tcgetattr(STDIN_FILENO, &orig_termios);
+ memcpy(&new_termios, &orig_termios, sizeof(new_termios));
+
+ new_termios.c_lflag &= ~(ICANON | ECHO);
+ new_termios.c_cc[VMIN] = 0;
+ new_termios.c_cc[VTIME] = 0;
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
+
+ atexit(reset_terminal_mode);
+}
+
+int kbhit(void) {
+ unsigned char ch;
+ int nread;
+
+ nread = read(STDIN_FILENO, &ch, 1);
+ if (nread == 1) {
+ if (ch == 0x1B) { // ESC
+ unsigned char seq[2];
+ if (read(STDIN_FILENO, &seq[0], 1) == 0) return 27;
+ if (read(STDIN_FILENO, &seq[1], 1) == 0) return 27;
+
+ if (seq[0] == '[') {
+ switch (seq[1]) {
+ case 'D':
+ return 1000; // Left arrow
+ case 'C':
+ return 1001; // Right arrow
+ default:
+ return 27; // ESC
+ }
+ }
+ return 27;
+ }
+ return ch;
+ }
+ return -1;
+}
+
+void int_handler(int dummy) {
+ running = FALSE;
+}
+
+static void on_pad_added(GstElement *src, GstPad *pad, gpointer user_data) {
+ GstCaps *caps;
+ const gchar *name;
+
+ caps = gst_pad_get_current_caps(pad);
+ name = gst_structure_get_name(gst_caps_get_structure(caps, 0));
+
+ if (g_str_has_prefix(name, "audio/")) {
+ GstElement *queue = gst_element_factory_make("queue", NULL);
+ GstElement *convert = gst_element_factory_make("audioconvert", NULL);
+ GstElement *sink = gst_element_factory_make("autoaudiosink", NULL);
+ GstPad *sinkpad;
+
+ gst_bin_add_many(GST_BIN(pipeline), queue, convert, sink, NULL);
+ gst_element_sync_state_with_parent(queue);
+ gst_element_sync_state_with_parent(convert);
+ gst_element_sync_state_with_parent(sink);
+
+ gst_element_link_many(queue, convert, sink, NULL);
+
+ sinkpad = gst_element_get_static_pad(queue, "sink");
+ if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK)
+ g_printerr("Failed to link audio pad\n");
+ gst_object_unref(sinkpad);
+ } else if (g_str_has_prefix(name, "video/")) {
+ GstElement *queue = gst_element_factory_make("queue", NULL);
+ GstElement *sink = video_sink;
+ GstPad *sinkpad;
+
+ gst_bin_add_many(GST_BIN(pipeline), queue, NULL);
+ gst_element_sync_state_with_parent(queue);
+
+ gst_element_link(queue, sink);
+
+ sinkpad = gst_element_get_static_pad(queue, "sink");
+ if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK)
+ g_printerr("Failed to link video pad\n");
+ gst_object_unref(sinkpad);
+ }
+
+ gst_caps_unref(caps);
+}
+
+int main(int argc, char *argv[]) {
+ GstElement *src;
+ GstElement *demuxer;
+ GstBus *bus;
+ GstMessage *msg;
+
+ if (argc < 2) {
+ g_printerr("Usage: %s <file-path>\n", argv[0]);
+ return -1;
+ }
+
+ gst_init(&argc, &argv);
+
+ src = gst_element_factory_make("filesrc", "src");
+ demuxer = gst_element_factory_make("decodebin", "decoder");
+ video_sink = gst_element_factory_make("sunxifbsink", "sink");
+
+ if (!src || !demuxer || !video_sink) {
+ g_printerr("Failed to create elements\n");
+ return -1;
+ }
+
+ g_object_set(src, "location", argv[1], NULL);
+ g_object_set(video_sink, "hardware-overlay", TRUE,
+ "video-memory", 2,
+ "buffer-pool", TRUE,
+ "full-screen", TRUE, NULL);
+
+ pipeline = gst_pipeline_new("player");
+
+ gst_bin_add_many(GST_BIN(pipeline), src, demuxer, video_sink, NULL);
+
+ if (!gst_element_link(src, demuxer)) {
+ g_printerr("Could not link src -> decoder\n");
+ return -1;
+ }
+
+ g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), NULL);
+
+ gst_element_set_state(pipeline, GST_STATE_PLAYING);
+ paused = FALSE;
+ g_print("Playing '%s'\n", argv[1]);
+ g_print("Controls: SPACE=play/pause, ESC=quit, LEFT/RIGHT=seek -/+5s\n");
+
+ signal(SIGINT, int_handler);
+ set_conio_terminal_mode();
+
+ while (running) {
+ int c = kbhit();
+
+ if (c != -1) {
+ if (c == ' ') {
+ if (paused) {
+ gst_element_set_state(pipeline, GST_STATE_PLAYING);
+ paused = FALSE;
+ g_print("Resumed\n");
+ } else {
+ gst_element_set_state(pipeline, GST_STATE_PAUSED);
+ paused = TRUE;
+ g_print("Paused\n");
+ }
+ } else if (c == 27) {
+ g_print("Exiting...\n");
+ running = FALSE;
+ } else if (c == 1000 || c == 1001) {
+ gint64 current_pos;
+ gint64 duration;
+ gint64 seek_offset;
+ gint64 new_pos;
+ gboolean res;
+
+ current_pos = GST_CLOCK_TIME_NONE;
+ duration = GST_CLOCK_TIME_NONE;
+
+ if (!gst_element_query_position(pipeline, GST_FORMAT_TIME, &current_pos)) {
+ g_print("Cannot query position\n");
+ continue;
+ }
+
+ if (!gst_element_query_duration(pipeline, GST_FORMAT_TIME, &duration)) {
+ g_print("Cannot query duration\n");
+ continue;
+ }
+
+ seek_offset = 5 * GST_SECOND;
+ if (c == 1000)
+ seek_offset = -seek_offset;
+
+ new_pos = current_pos + seek_offset;
+
+ if (new_pos < 0)
+ new_pos = 0;
+ if (new_pos > duration)
+ new_pos = duration;
+
+ res = gst_element_seek_simple(
+ pipeline,
+ GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH,
+ new_pos);
+
+ if (res) {
+ g_print("Seeked to %" GST_TIME_FORMAT "\n", GST_TIME_ARGS(new_pos));
+ } else {
+ g_print("Seek failed\n");
+ }
+ }
+ }
+
+ bus = gst_element_get_bus(pipeline);
+ while ((msg = gst_bus_pop(bus)) != NULL) {
+ switch (GST_MESSAGE_TYPE(msg)) {
+ case GST_MESSAGE_EOS:
+ g_print("End of stream\n");
+ running = FALSE;
+ break;
+ case GST_MESSAGE_ERROR: {
+ GError *err;
+ gchar *dbg;
+ gst_message_parse_error(msg, &err, &dbg);
+ g_printerr("Error: %s\n", err->message);
+ g_error_free(err);
+ g_free(dbg);
+ running = FALSE;
+ break;
+ }
+ default:
+ break;
+ }
+ gst_message_unref(msg);
+ }
+ gst_object_unref(bus);
+
+ usleep(100 * 1000); // 100ms
+ }
+
+ gst_element_set_state(pipeline, GST_STATE_NULL);
+ gst_object_unref(pipeline);
+ g_print("Pipeline stopped\n");
+
+ return 0;
+}
--
2.34.1