一、Plugin Constructing the Boilerplate

news/2024/4/26 15:50:28/文章来源:https://blog.csdn.net/Creationyang/article/details/129135321

构建样板文件

在本章中,你将学习如何为一个新插件构建最少的代码。从起点开始,您将看到如何获取GStreamer模板源代码。然后,您将学习如何使用一些基本工具来复制和修改模板插件,以创建一个新的插件。如果您遵循这里的示例,那么在本章结束时,您将拥有一个可以编译并在GStreamer应用程序中使用的功能强大的音频过滤器插件。

得到GStreamer插件模板

目前有两种方法可以开发GStreamer的新插件:可以手工编写整个插件,也可以复制现有的插件模板并编写所需的插件代码。到目前为止,第二种方法是两种方法中比较简单的一种,因此在这里就不介绍第一种方法了。(嗯,也就是说,“留给读者做练习。”)

第一步是检出gst-template git模块的一个副本,以获取一个重要的工具和一个基本GStreamer插件的源代码模板。要查看gst-template模块,请确保已连接到互联网,然后在命令控制台中输入以下命令:

shell $ git clone https://gitlab.freedesktop.org/gstreamer/gst-template.git
Initialized empty Git repository in /some/path/gst-template/.git/
remote: Counting objects: 373, done.
remote: Compressing objects: 100% (114/114), done.
remote: Total 373 (delta 240), reused 373 (delta 240)
Receiving objects: 100% (373/373), 75.16 KiB | 78 KiB/s, done.
Resolving deltas: 100% (240/240), done.

这个命令会检出一系列文件和目录到gst-template中。我们要使用的模板在gst-template/gst-plugin/目录下。你应该查看该目录下的文件,以对插件源代码树的结构有一个大致的了解。

如果由于某种原因您无法访问git仓库,您也可以通过gitlab web界面下载最新版本的快照。

使用项目Stamp

创建新元素时要做的第一件事是指定一些基本细节:它的名称、编写它的人、它的版本号等。我们还需要定义一个对象来表示元素并存储元素所需的数据。这些细节统称为样板(boilerplate)。

定义样板代码的标准方法很简单,就是编写一些代码,然后填充一些结构。如上一节所述,最简单的方法是复制模板并根据需要添加功能。在./gst-plugin/tools/目录下有一个工具可以帮助你做到这一点。这个工具make_element是一个命令行实用工具,它为您创建样板代码。

要使用make_element,首先要打开一个终端窗口。切换到目录gst-template/gst-plugin/src,然后执行make_element命令。make_element的参数如下:

  • 1.插件的名称
  • 2.工具将使用的源文件。默认使用gstplugin。

例如,下面的命令根据插件模板创建MyFilter插件,并将输出文件放在目录gst-template/gst-plugin/src中:

注意:

  1. 对于插件的名称,大小写很重要。请记住,在某些操作系统下,通常指定目录和文件名时,大小写也很重要。最后一个命令创建两个文件:gstmyfilter.c和gstmyfilter.h。
  2. 建议您先创建一个gst-plugin目录的副本再继续下一步操作。现在需要从父目录运行meson build来引导构建环境。之后,可以使用众所周知的ninja -C build命令来构建和安装项目。
  3. 请注意,在默认情况下,meson将选择/usr/local作为默认位置。我们需要将/usr/local/lib/gstreamer-1.0添加到GST_PLUGIN_PATH中,以便让新插件显示gstreamer安装列表中。
  4. FIXME:这一节有点过时了。作为一个最小插件构建系统框架的例子,Gst-template仍然很有用。但是,对于创建元素,现在推荐使用gst-plugins-bad中的gst-element-maker工具。

检查基本代码

首先,我们将检查可能放在头文件中的代码(尽管由于代码的接口完全由插件系统定义,不依赖于读取头文件,因此这不是至关重要的)。

#include <gst/gst.h>/* Definition of structure storing data for this element. */
typedef struct _GstMyFilter {GstElement element;GstPad *sinkpad, *srcpad;gboolean silent;} GstMyFilter;/* Standard definition defining a class for this element. */
typedef struct _GstMyFilterClass {GstElementClass parent_class;
} GstMyFilterClass;/* Standard macros for defining types for this element.  */
#define GST_TYPE_MY_FILTER (gst_my_filter_get_type())
#define GST_MY_FILTER(obj) \(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter))
#define GST_MY_FILTER_CLASS(klass) \(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass))
#define GST_IS_MY_FILTER(obj) \(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER))
#define GST_IS_MY_FILTER_CLASS(klass) \(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER))/* Standard function returning type information. */
GType gst_my_filter_get_type (void);GST_ELEMENT_REGISTER_DECLARE(my_filter)

使用这个头文件,你可以使用以下宏在源文件中设置元素基础,以便正确调用所有函数:

#include "filter.h"G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT);
GST_ELEMENT_REGISTER_DEFINE(my_filter, "my-filter", GST_RANK_NONE, GST_TYPE_MY_FILTER);

宏GST_ELEMENT_REGISTER_DEFINE与GST_ELEMENT_REGISTER_DECLARE结合使用,允许在插件内部或通过调用GST_ELEMENT_REGISTER (my_filter)从任何其他插件/应用程序注册元素。

元素元数据

元素元数据提供额外的元素信息。它配置了gst_element_class_set_metadata或gst_element_class_set_static_metadata,参数如下:

  • 元素的英文长名称。
  • 元素的类型,请参阅GStreamer核心源代码树中的docs/additional/design/draft-klass.txt文档了解详细信息和示例。
  • 元素用途的简要描述。
  • 元素作者的名字,后面可以加上尖括号中的联系电子邮件地址。

例如:

gst_element_class_set_static_metadata (klass,"An example plugin","Example/FirstExample","Shows the basic structure of a plugin","your name <your.name@your.isp>");

元素的细节是在_class_init()函数期间注册到插件的,这个函数是GObject系统的一部分。在向GLib注册类型的函数中,应该为这个GObject设置_class_init()函数。

static void
gst_my_filter_class_init (GstMyFilterClass * klass)
{GstElementClass *element_class = GST_ELEMENT_CLASS (klass);[..]gst_element_class_set_static_metadata (element_class,"An example plugin","Example/FirstExample","Shows the basic structure of a plugin","your name <your.name@your.isp>");}

GstStaticPadTemplate

GstStaticPadTemplate是元素将(或可能)创建和使用的pad
的描述。它包含:

  • pad的简称。
  • pad的方向。
  • pad存在的属性(请求、始终、有时)。这表明该pad是否始终存在(always垫),仅在某些情况下存在(sometimes垫),或者仅在应用程序请求这样一个垫(request垫)时存在。

此元素支持的类型(功能)。

例如:

static GstStaticPadTemplate sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS ("ANY")
);

这些pad模板是在_class_init()函数中使用gst_element_class_add_pad_template()注册的。对于这个函数,您需要一个处理GstPadTemplate,您可以从静态pad模板创建与gst_static_pad_template_get()。有关此的更多细节请参见下文。

元素的_init()函数使用gst_pad_new_from_static_template()从这些静态模板创建pad。为了使用gst_pad_new_from_static_template()从这个模板创建一个新的pad,需要将pad模板声明为全局变量。有关此主题的更多信息请参见指定pad。

static GstStaticPadTemplate sink_factory = [..],src_factory = [..];static void
gst_my_filter_class_init (GstMyFilterClass * klass)
{GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
[..]gst_element_class_add_pad_template (element_class,gst_static_pad_template_get (&src_factory));gst_element_class_add_pad_template (element_class,gst_static_pad_template_get (&sink_factory));
}

模板中的最后一个参数是其类型或支持的类型列表。在这个例子中,我们使用了ANY,这意味着这个元素将接受所有输入。在实际情况中,您可以设置一个媒体类型和可选的一组属性,以确保只接收受支持的输入。这种表示应该是一个字符串,以媒体类型开始,然后是一组以逗号分隔的属性及其支持的值。如果音频滤波器支持任意采样的原始整数16位音频、单声道或立体声,正确的模板应该是这样的:

static GstStaticPadTemplate sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS ("audio/x-raw, ""format = (string) " GST_AUDIO_NE (S16) ", ""channels = (int) { 1, 2 }, ""rate = (int) [ 8000, 96000 ]")
);

被大括号(“{“和”}”)括起来的值是列表,被方括号(“[“和”]”)括起来的值是范围。它还支持多组类型,并且应该用分号(“;”)分隔。在关于pad的这一章中,我们将看到如何使用类型来知道流的确切格式:指定pad。

Constructor Functions

每个元素都有两个函数,用于构造元素。_class_init()函数,只用于初始化类一次(指定类有哪些信号、参数和虚函数,并设置全局状态);以及_init()函数,该函数用于初始化该类型的特定实例。

The plugin_init function

编写了定义插件所有部分的代码后,还需要编写plugin_init()函数。这是一个特殊的函数,插件加载后就会调用它,返回TRUE或FALSE,取决于插件是否正确地加载并初始化了任何依赖项。此外,在这个函数中,应该注册插件中任何受支持的元素类型。

static gboolean
plugin_init (GstPlugin *plugin)
{return GST_ELEMENT_REGISTER (my_filter, plugin);
}GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,GST_VERSION_MINOR,my_filter,"My filter plugin",plugin_init,VERSION,"LGPL","GStreamer","http://gstreamer.net/"
)

请注意,plugin_init()函数返回的信息将缓存在一个中央注册表中。因此,函数总是返回相同的信息是很重要的:例如,它不能根据运行时条件使元素factory可用。如果一个元素只能在某些条件下工作(例如,如果声卡没有被其他进程使用),这必须反映为该元素在不可用时无法进入就绪状态,而不是插件试图否认该插件的存在。

Specifying the pads

如前所述,填充区是数据进出元素的端口,这使得它们在元素创建过程中非常重要。在样板代码中,我们看到了静态pad模板如何使用element类注册pad模板。在这里,我们将看到如何创建实际的元素,使用_event()函数为特定的格式进行配置,以及如何注册函数以让数据流经元素。

在element _init()函数中,根据_class_init()函数中的element类注册的pad模板创建pad。在创建pad之后,必须设置_chain()函数指针,它将在sinkpad上接收和处理输入数据。你也可以选择设置一个_event()函数指针和一个_query()函数指针。此外,pad也可以在循环模式下工作,这意味着它们可以自己拉取数据。稍后会详细讨论这个话题。之后,您必须将pad注册到元素。事情是这样的:

static void
gst_my_filter_init (GstMyFilter *filter)
{/* pad through which data comes in to the element */filter->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");/* pads are configured here with gst_pad_set_*_function () */gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);/* pad through which data goes out of the element */filter->srcpad = gst_pad_new_from_static_template (&src_template, "src");/* pads are configured here with gst_pad_set_*_function () */gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);/* properties initial value */filter->silent = FALSE;
}

参考1:官方GStreamer Constructing the Boilerplate
参考2:官方GStreamer Specifying the pads

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【云原生】初识Kubernetes的理论基础

一、kubernetes概述 1.1 kubernetes介绍 K8S的全称为Kubernetes (K12345678S)&#xff0c;首字母与尾字母中间有8个字母&#xff0c;缩写为K8S 作用 用于自动部署、扩展和管理“容器化(containerized) 应用程序”的开源系统。可以理解成K8S是负责自动化运维管理多个容器化程序…

【云原生】k8s之Yaml文件详解

一、K8S支持的文件格式 kubernetes支持YAML和JSON文件格式管理资源对象。 JSON格式&#xff1a;主要用于api接口之间消息的传递YAML格式&#xff1a;用于配置和管理&#xff0c;YAML是一种简洁的非标记性语言&#xff0c;内容格式人性化&#xff0c;较易读 1、yaml和json的主…

[Golang实战]github.io部署个人博客hugo[新手开箱可用][小白教程]

[Golang实战]github.io部署个人博客hugo[新手开箱可用][小白教程]1.新手教程(小白也能学会)2.开始准备2.1myBlog是hugo的项目1.安装Hugo2.创建hugo项目2.2 xxxx.github.io是github.io中规定的pages项目3.成功部署4.TODO自动化workflows部署github.io1.新手教程(小白也能学会) …

分析| 2023年移动开发平台的发展空间

春节过后返工已经过月&#xff0c;许多移动开发领域的企业都在忙着做技术调研与选型。在此之前&#xff0c;不如先回顾一下2022年的市场趋势&#xff0c;再结合好的移动开发平台的标准&#xff0c;从中窥见2023年的发展前景。 Gartner十大战略技术趋势 全球权威咨询机构Gartne…

分析称勒索攻击在非洲、中东与中国增长最快

Orange Cyberdefense&#xff08;OCD&#xff09;于 2022 年 12 月 1 日发布了最新的网络威胁年度报告。报告中指出&#xff0c;网络勒索仍然是头号威胁 &#xff0c;也逐渐泛滥到世界各地。 报告中的网络威胁指的是企业网络中的某些资产被包括勒索软件在内的攻击进行勒索&…

2022-06-16_555时基的迷人历史和先天缺陷!

https://www.eet-china.com/news/magazine220608.html 555时基的迷人历史和先天缺陷&#xff01; 发布于2022-06-16 03:39:12 LARRY STABILE 流行数十年的555时基&#xff0c;业内不知晓的工程师应该寥寥无几&#xff01;几乎所有的数字电路教材中&#xff0c;都有该芯片的身影…

LeetCode 周赛 333,你管这叫 Medium 难度?

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 大家好&#xff0c;我是小彭。 上周是 LeetCode 第 333 场周赛&#xff0c;你参加了吗&#xff1f;这场周赛质量很高&#xff0c;但难度标得不对&#xff0c;我真的会谢。算法…

基于龙芯 2K1000 的嵌入式 Linux 系统移植和驱动程序设计

2.1 需求分析 本课题以龙芯 2K1000 处理器为嵌入式系统的处理器&#xff0c;需要实现一个完成的嵌 入式软件系统&#xff0c;系统能够正常启动并可以稳定运行嵌入式 Linux。设计网络设备驱 动&#xff0c;可以实现板卡与其他网络设备之间的网络连接和文件传输。设计 PCIE 设备驱…

重温一下C#的时间类型,并简单写一个定时器功能

&#x1f389;&#x1f389; 时间是一个非常抽象的概念&#xff0c;本篇文章我们不深究目前电脑上的时候是如何保持全网同步。主要是讲讲在使用C#编程语言里的时间类型。最后使用定时任务简单写一个提醒功能&#xff0c;比如&#xff1a;每天10点准时打开一次csdn首页&#xff…

yolov5源码解读--数据处理模块

yolov5源码解读--数据处理模块加载数据读取图片加载标签马赛克数据增强图片标签其他的数据增强变图像变标签__getitem__构建Batch加载数据 create_dataloader 跳转到datasets.py文件中&#xff0c;可以看到支持输入的文件类型非常丰富。。 回归正题 跳转LoadImagesAndLabel…

分析JEP 290机制的Java实现

简介 https://openjdk.org/jeps/290 Filter Incoming Serialization Data过滤传入的序列化数据 JEP290是Java官方提供的一套来防御反序列化的机制&#xff0c;其核心在于提供了一个ObjectInputFilter接口&#xff0c;通过设置filter对象&#xff0c;然后在反序列化&#xff…

c盘系统盘满了,无损扩容

磁盘管理 计算机-管理-磁盘管理 diskmgmt.msc1.选中c盘&#xff0c;右键选择扩展卷&#xff0c;如果是灰色&#xff0c;表示无法扩展 注意&#xff1a; 未分配区域不在同一磁盘&#xff0c;无法分配&#xff1b; 物理上不挨着的区域&#xff0c;无法分配&#xff1b; 2.把与c…

【Spring Cloud Alibaba】003-Nacos 概述与单机搭建

【Spring Cloud Alibaba】003-Nacos 概述与单机搭建 文章目录【Spring Cloud Alibaba】003-Nacos 概述与单机搭建一、Nacos 概述0、新技术学习思路推荐1、什么是 Nacos2、架构图架构图架构图信息二、Nacos 单机搭建1、下载与启动下载地址编辑 startup.cmd 文件下面对两种模式的…

cocos2d-x4.0 win10环境搭建

cocos2d-x默认只支持win32的版本&#xff0c;win64的我测试link不行 我搭建使用的环境 windows10vs2019py2.7cmake3 从GitHub上clone源码https://github.com/cocos2d/cocos2d-x coco2d-x默认带了submodule&#xff0c;有协同子模块&#xff0c;最好是一起下载&#xff0c;搞个…

破解遗留系统快速重构的5步心法(附实例)

前两天和一个架构师朋友闲聊&#xff0c;说到了 「重构」 这个话题&#xff0c;他们公司早年间上线的项目系统&#xff0c;因一直没专人在演进过程中为代码质量负责&#xff0c;导致现在代码越来越混乱&#xff0c;逐渐堆积成“屎山”&#xff0c;目前的维护成本已远高于重新开…

ubuntu server系统树莓派安装mysql8.0开启远程访问

文章目录前言博客一、安装mysql8.0二、创建一个远程访问的新用户三、在MySQL配置文件中启用远程访问。四、navicat15连接mysql8.0返回10061chatgpt回复前言 百度了半天没解决&#xff0c;问了下chatgpt成功解决了…… 博客 一、安装mysql8.0 确认MySQL 8.0服务器已安装并正在…

恺望数据:解决智驾数据生产痛点,提供自动化生产线和规模化人力

最近Chat GPT引起了一个热点话题&#xff0c;就是人工智能是否真的可以替代人类工作&#xff0c;特别是在需要进行数据标注等需要人力的领域。 自动驾驶数据服务公司恺望数据在最近的一个会议上透露了一些消息&#xff0c;他们已经推出了一个基于自动化的数据生产系统&#xff…

uniapp 引入彩色symbol和 指令权限

uniapp 引入iconfont图标库彩色symbol 1&#xff0c;先去阿里巴巴矢量图标库登录 然后点击下载至本地 2.下载本地&#xff0c;然后解压文件夹 3.打开终端cmd命令窗口 npm安装全局包npm i -g iconfont-tools 4.终端切换到上面解压的文件夹里面&#xff0c;运行iconfont-too…

idea 中的 profiles 详解

profile 主要是为了解决不同环境所需的不同变量、配置等问题. profile 一般出现在两个地方&#xff1a;settings.xml&#xff0c;pom.xml 在 settings.xml 时&#xff0c;一般用来做仓库的选择(只使用 aliyun 仓库可以这样配置 settings.xml) 在 pom.xml 时&#xff0c;一般…

EM算法总结

目录 一。Jensen不等式&#xff1a;若f是凸函数 二。最大似然估计 三。二项分布的最大似然估计 四。进一步考察 1.按照MLE的过程分析 2.化简对数似然函数 3.参数估计的结论 4.符合直观想象 五。从直观理解猜测GMM的参数估计 1.问题&#xff1a;随机变量无法直接…