GStreamer学习4----写一个插件

news2024/10/7 18:21:13

参考资料:

Constructing the Boilerplate

gstreamer插件-CSDN博客

在Constructing the Boilerplate 里面有生成插件的例子,

shell $ git clone https://gitlab.freedesktop.org/gstreamer/gst-template.git

使用里面的工具自动生成一个插件程序,比如MyFilter

shell $ cd gst-template/gst-plugin/src
shell $ ../tools/make_element MyFilter

注意,这样生成的自定义的element的名字使用起来应该是my_filter,

画一下图,就比较容易理解生成的代码结构

class的定义,init

element的定义,init

pad(sink,src)的定义

属性的设置和获取处理

chain的处理

event事件的处理

代码参考

 
 
/**
 * SECTION:element-myfilter
 *
 * FIXME:Describe myfilter here.
 *
 * <refsect2>
 * <title>Example launch line</title>
 * |[
 * gst-launch -v -m fakesrc ! myfilter ! fakesink silent=TRUE
 * ]|
 * </refsect2>
 */a
 
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
 
 
#ifndef __GST_MYFILTER_H__
#define __GST_MYFILTER_H__
 
#include <gst/gst.h>
#include <stdio.h>
 
G_BEGIN_DECLS
 
#define GST_TYPE_MYFILTER (gst_my_filter_get_type())
G_DECLARE_FINAL_TYPE (GstMyFilter, gst_my_filter,
    GST, MYFILTER, GstElement)
 
struct _GstMyFilter
{
  GstElement element;
 
  GstPad *sinkpad, *srcpad;
  gboolean width;
  gboolean height;
  gboolean silent;
};
 
G_END_DECLS
 
#endif /* __GST_MYFILTER_H__ */
 
GST_DEBUG_CATEGORY_STATIC (gst_my_filter_debug);
#define GST_CAT_DEFAULT gst_my_filter_debug
 
#define DEFAULT_PROP_WIDTH 0    /* Original */
#define DEFAULT_PROP_HEIGHT 0   /* Original */
 
/* Filter signals and args */
enum
{
  /* FILL ME */
  LAST_SIGNAL
};
 
enum
{
  PROP_0,
  PROP_SILENT,
  PROP_WIDTH,
  PROP_HEIGHT
};
 
 
/* the capabilities of the inputs and outputs.
 *
 * describe the real formats here.
 */
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY"));
 
 
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-raw, "
    "width = (int) [96, 1920], height = (int) [96, 1080]"
    )
    );
 
#define gst_my_filter_parent_class parent_class
G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT);
 
GST_ELEMENT_REGISTER_DEFINE (my_filter, "my_filter", GST_RANK_NONE,
    GST_TYPE_MYFILTER);
 
static void gst_my_filter_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_my_filter_get_property (GObject * object,
    guint prop_id, GValue * value, GParamSpec * pspec);
 
static gboolean gst_my_filter_sink_event (GstPad * pad,
    GstObject * parent, GstEvent * event);
static GstFlowReturn gst_my_filter_chain (GstPad * pad,
    GstObject * parent, GstBuffer * buf);
/* GObject vmethod implementations */
 
/* initialize the myfilter's class */
static void
gst_my_filter_class_init (GstMyFilterClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
 
  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
 
  gobject_class->set_property = gst_my_filter_set_property;
  gobject_class->get_property = gst_my_filter_get_property;
 
  g_object_class_install_property (gobject_class, PROP_SILENT,
      g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
          FALSE, G_PARAM_READWRITE));
  g_object_class_install_property (gobject_class, PROP_WIDTH,
    g_param_spec_uint ("width", "Width",
        "Width (0 = original)",
        0, G_MAXINT, DEFAULT_PROP_WIDTH,
        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  g_object_class_install_property (gobject_class, PROP_HEIGHT,
      g_param_spec_uint ("height", "Height",
          "Height (0 = original)",
          0, G_MAXINT, DEFAULT_PROP_HEIGHT,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
  gst_element_class_set_details_simple (gstelement_class,
      "MyFilter",
      "FIXME:Generic",
      "FIXME:Generic Template Element", " <<user@hostname.org>>");
 
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&src_factory));
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&sink_factory));
}
 
/* initialize the new element
 * instantiate pads and add them to element
 * set pad callback functions
 * initialize instance structure
 */
static void
gst_my_filter_init (GstMyFilter * filter)
{
  filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
  gst_pad_set_event_function (filter->sinkpad,
      GST_DEBUG_FUNCPTR (gst_my_filter_sink_event));
  gst_pad_set_chain_function (filter->sinkpad,
      GST_DEBUG_FUNCPTR (gst_my_filter_chain));
  GST_PAD_SET_PROXY_CAPS (filter->sinkpad);
  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
 
  filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
  GST_PAD_SET_PROXY_CAPS (filter->srcpad);
  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
 
  filter->silent = TRUE;
}
 
static void
gst_my_filter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstMyFilter *filter = GST_MYFILTER (object);
 
  switch (prop_id) {
    case PROP_SILENT:
      filter->silent = g_value_get_boolean (value);
      break;
    case PROP_WIDTH:
      filter->width = g_value_get_boolean (value);
      break;
    case PROP_HEIGHT:
      filter->height = g_value_get_boolean (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
 
static void
gst_my_filter_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstMyFilter *filter = GST_MYFILTER (object);
 
  switch (prop_id) {
    case PROP_SILENT:
      g_value_set_boolean (value, filter->silent);
      break;
    case PROP_WIDTH:
      g_value_set_boolean (value, filter->width);
      break;
    case PROP_HEIGHT:
      g_value_set_boolean (value, filter->height);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
 
/* GstElement vmethod implementations */
 
/* this function handles sink events */
static gboolean
gst_my_filter_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstMyFilter *filter;
  gboolean ret;
 
  filter = GST_MYFILTER (parent);
 
  GST_LOG_OBJECT (filter, "Received %s event: %" GST_PTR_FORMAT,
      GST_EVENT_TYPE_NAME (event), event);
 
  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;
 
      GstStructure *structure;
      gst_event_parse_caps (event, &caps);
 
      structure = gst_caps_get_structure(caps, 0);
 
      gint width, height;
      gst_structure_get_int(structure, "width", &width);
      gst_structure_get_int(structure, "height", &height);
      filter->width = width;
      filter->height = height;
 
      /* and forward */
      ret = gst_pad_event_default (pad, parent, event);
      break;
    }
    default:
      ret = gst_pad_event_default (pad, parent, event);
      break;
  }
  return ret;
}
 
 
 
/* chain function
 * this function does the actual processing
 */
static GstFlowReturn
gst_my_filter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstMyFilter *filter;
 
  filter = GST_MYFILTER (parent);
  
  if (filter->silent == FALSE){
    g_print ("I'm plugged, therefore I'm in.\n");
  }
 
  GstFlowReturn ret = gst_pad_push (filter->srcpad, buf);
  
  /* just push out the incoming buffer without touching it */
  return ret;
}
 
 
/* entry point to initialize the plug-in
 * initialize the plug-in itself
 * register the element factories and other features
 */
static gboolean
myfilter_init (GstPlugin * myfilter)
{
  /* debug category for filtering log messages
   *
   * exchange the string 'Template myfilter' with your description
   */
  GST_DEBUG_CATEGORY_INIT (gst_my_filter_debug, "myfilter",
      0, "Template myfilter");
 
  return GST_ELEMENT_REGISTER (my_filter, myfilter);
}
 
/* PACKAGE: this is usually set by meson depending on some _INIT macro
 * in meson.build and then written into and defined in config.h, but we can
 * just set it ourselves here in case someone doesn't use meson to
 * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
 */
#ifndef PACKAGE
#define PACKAGE "myfirstmyfilter"
#endif
 
/* gstreamer looks for this structure to register myfilters
 *
 * exchange the string 'Template myfilter' with your myfilter description
 */
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    myfilter,
    "my_filter",
    myfilter_init,
    PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

在gst_my_filter_chain方法中,

static GstFlowReturn
gst_my_filter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstMyFilter *filter;
 
  filter = GST_MYFILTER (parent);
  
  if (filter->silent == FALSE){
    g_print ("I'm plugged, therefore I'm in.\n");
  }
 
  GstFlowReturn ret = gst_pad_push (filter->srcpad, buf);
  
  /* just push out the incoming buffer without touching it */
  return ret;
}

可以使用Basic tutorial 8: Short-cutting the pipeline 例子的的方法来获取buffer中的内存数据,来进行操作,

  gst_buffer_map (buffer, &map, GST_MAP_WRITE);
  raw = (gint16 *)map.data;

 比如数据格式是RGB,获取到长宽后,可以进行颜色转换,画面镜像处理等等,

就比如最近欧洲杯里讨论的比较火的广告内容区域化转换处理,就可以在gst_my_filter_chain里进行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1854671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 简单使用 sftp 和 lftp命令

目录 一. 环境准备二. sftp命令连接到SFTP服务器三. lftp命令3.1 连接FTP和SFTP服务器3.2 将文件从sftp服务器下载到本地指定目录 四. 通过WinSCP命令行从SFTP服务器获取文件到Windows 一. 环境准备 ⏹在安卓手机上下载个MiXplorer&#xff0c;用作SFTP和FTP服务器 官网: htt…

Mathtype7在Word2016中闪退(安装过6)

安装教程&#xff1a;https://blog.csdn.net/Little_pudding10/article/details/135465291 Mathtype7在Word2016中闪退是因为安装过Mathtype6&#xff0c;MathPage.wll和MathType Comm***.dotm)&#xff0c;不会随着Mathtype的删除自动删除&#xff0c;而新版的Mathtype中的文件…

Debian Linux安装minikubekubectl

minikube&kubectl minkube用于在本地开发环境中快速搭建一个单节点的Kubernetes集群,还有k3s&#xff0c;k3d&#xff0c;kind都是轻量级的k8skubectl是使用K8s API 与K8s集群的控制面进行通信的命令行工具 这里使用Debian Linux演示&#xff0c;其他系统安装见官网,首先…

React+TS 从零开始教程(2):简中简 HelloWolrd

源码链接&#xff1a;https://pan.quark.cn/s/c6fbc31dcb02 这一节&#xff0c;我们来见识ReactTS的威力&#xff0c;开始上手开发第一个组件&#xff0c;什么组件呢&#xff1f; 当然是简中简的 HelloWolrd组件啦。 在src下创建一个components&#xff0c;然后新建Hello.tsx …

nlp基础-文本预处理及循环神经网络

1 认识文本预处理 1 文本预处理及其作用 定义&#xff1a;文本送给模型之前&#xff0c;提前要做的工作 作用&#xff1a;指导模型超参数的选择 、提升模型的评估指标 举个例子&#xff1a; 思路常识&#xff0c;打造成 X Y关于Y&#xff1a;10分类标签是否均衡关于X&#xf…

【break】大头哥哥做题

【break】大头哥哥做题 时间限制: 1000 ms 内存限制: 65536 KB 【题目描述】 【参考代码】 #include <iostream> using namespace std; int main(){ int sum 0;//求和int day 0;//天数 while(1){int a;cin>>a;if(a-1){break;//结束当前循环 }sum sum a; …

自动更新阿里云CDN SSL证书

deploy-certificate-to-aliyun 随着各大CA机构开始收割用户&#xff0c;云厂商们提供的免费SSL证书也由之前的12个月变成现在的3个月。笔者一直使用阿里云的OSS作为图床&#xff0c;说实话在如果继续在阿里云上三个月免费一换也太频繁了 笔者在这里使用github action来每隔两个…

odoo的采购询价单,默认情况下显示‘draft‘,‘sent‘,‘purchase‘,请问什么情况下才会显示‘to approve‘?

odoo的采购询价单&#xff0c;默认情况下显示’draft’,‘sent’,‘purchase’&#xff0c;请问什么情况下才会显示’to approve’? 见下图&#xff1a; 这与操作人员的角色是相关的&#xff1a; 当操作人员是群组 “采购 / 用户”时&#xff0c;点击“confirm order/确认订…

细说AGV的12种导航方式和原理

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 这十二种导航方式各自具有不同的特点和应用场景&#xff0c;下面我将逐一进行简要介绍&#xff1a; 磁钉导航&#xff1a; 原理&#xf…

基于CDMA的多用户水下无线光通信(2)——系统模型和基于子空间的延时估计

本文首先介绍了基于CDMA的多用户UOWC系统模型&#xff0c;并给出了多用户收发信号的数学模型。然后介绍基于子空间的延时估计算法&#xff0c;该算法只需要已知所有用户的扩频码&#xff0c;然后根据扩频波形的循环移位在观测空间的信号子空间上的投影进行延时估计。 1、基于C…

基于CDMA的多用户水下无线光通信(1)——背景介绍

研究生期间做多用户水下无线光通信&#xff08;Underwater Optical Wireless Communication&#xff0c;UOWC&#xff09;&#xff0c;写几篇博客分享一下学的内容。导师给了大方向&#xff0c;让我用直接序列码分多址&#xff08;Direct Sequence Code Division Multiple Acce…

分布式锁实现方案

分布式锁 1 什么是分布式锁 ​ 就是在分布式环境下&#xff0c;保证某个公共资源只能在同一时间被多进程应用的某个进程的某一个线程访问时使用锁。 2 几个使用场景分析 一段代码同一时间只能被同一个不同进程的一个线程执行 库存超卖 (库存被减到 负数)&#xff0c;上面案…

智慧园区数字化能源云平台的多元化应用场景,您知道哪些?

智慧园区数字化能源云平台的多元化应用场景&#xff0c;您知道哪些&#xff1f; 智慧园区数字化能源云平台&#xff0c;作为新一代信息技术与传统能源管理深度融合的典范&#xff0c;正引领着产业园区向智慧化、绿色化转型的浪潮。该平台依托于大数据、云计算及人工智能等前沿…

AI 大模型企业应用实战(13)-Lostinthemiddle长上下文精度处理

1 长文本切分信息丢失处理方案 10检索时性能大幅下降相关信息在头尾性能最高检索 ->> 排序 ->使用 实战 安装依赖&#xff1a; ! pip install sentence-transformers 演示如何使用 Langchain 库中的组件来处理长文本和检索相关信息。 导入所需的库使用指定的预训…

【计算机组成原理】部分题目汇总

计算机组成原理 部分题目汇总 一. 简答题 RISC和CICS 简要说明&#xff0c;比较异同 RISC&#xff08;精简指令集&#xff09;注重简单快速的指令执行&#xff0c;使用少量通用寄存器&#xff0c;固定长度指令&#xff0c;优化硬件性能&#xff0c;依赖软件&#xff08;如编译…

基于YOLOv5+PyQT5的吸烟行为检测(含pyqt页面、模型、数据集)

简介 吸烟不仅对个人健康有害,也可能在某些特定场合带来安全隐患。为了有效地监控公共场所和工作环境中的吸烟行为,我们开发了一种基于YOLOv5目标检测模型的吸烟检测系统。本报告将详细介绍该系统的实际应用与实现,包括系统架构、功能实现、使用说明、检测示例、数据集获取…

I2C总线8位IO扩展器PCF8574

PCF8574用于I2C总线的远程8位I/O扩展器 PCF8574国产有多个厂家有替代产品&#xff0c;图示为其中一款HT8574 1 产品特点 低待机电流消耗&#xff1a;10 uA&#xff08;最大值&#xff09; I2C 转并行端口扩展器 漏极开路中断输出 与大多数微控制器兼容 具有大电流驱动能力的闭…

JavaScript 预编译与执行机制解析

在深入探讨JavaScript预编译与执行机制之前&#xff0c;我们首先需要明确几个基本概念&#xff1a;声明提升、函数执行上下文、全局执行上下文以及调用栈。这些概念共同构成了JavaScript运行时环境的核心组成部分&#xff0c;对于理解代码的执行流程至关重要。本文将围绕这些核…

网信办公布第六批深度合成服务算法备案清单,深兰科技大模型入选

6月12日&#xff0c;国家互联网信息办公室发布了第六批深度合成服务算法备案信息&#xff0c;深兰科技硅基知识智能对话多模态大模型算法通过相关审核&#xff0c;成功入选该批次《境内深度合成服务算法备案清单》。同时入选的还有腾讯混元大模型多模态算法、支付宝图像生成算法…

《分析模式》“鸦脚”表示法起源,Everest、Barker和Hay

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 《分析模式》这本书里面用的并不是UML表示法。作者Martin Fowler在书中也说了&#xff0c;该书写于1994-1995年&#xff0c;当时还没有UML。作者在书中用的是一种常被人称为“鸦脚”的…