当前位置: 首页 > news >正文

一、Plugin Constructing the Boilerplate

构建样板文件

在本章中,你将学习如何为一个新插件构建最少的代码。从起点开始,您将看到如何获取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

相关文章:

一、Plugin Constructing the Boilerplate

构建样板文件 在本章中&#xff0c;你将学习如何为一个新插件构建最少的代码。从起点开始&#xff0c;您将看到如何获取GStreamer模板源代码。然后&#xff0c;您将学习如何使用一些基本工具来复制和修改模板插件&#xff0c;以创建一个新的插件。如果您遵循这里的示例&#x…...

15、存储过程与函数

文章目录1 存储过程概述1.1 理解1.2 分类2 创建存储过程2.1 语法分析2.2 代码举例3 调用存储过程3.1 调用格式3.2 代码举例3.3 如何调试4 存储函数的使用4.1 语法分析4.2 调用存储函数4.3 代码举例4.4 对比存储函数和存储过程5 存储过程和函数的查看、修改、删除5.1 查看5.2 修…...

uniapp 原生安卓开发插件(module),以及android环境本地调试(二)

uniapp 原生安卓开发插件&#xff08;module&#xff09;&#xff0c;以及android环境本地调试&#xff08;一&#xff09; 1、前景 承接上一篇文章&#xff0c;由于uniapp每天只有限定的打包次数&#xff0c;所以每次插件调试都打包成为基座&#xff0c;这个不太方便&#x…...

【Java期末复习】《面向对象程序设计》练习库

目录 一、单选题 二、填空题 三、程序填空题 1、 super使用--有如下父类和子类的定义&#xff0c;根据要求填写代码 2、简单加法计算器的实现 3、House类 4、矩形类 5、创建一个Box类&#xff0c;求其体积 四、函数题 6-1 求圆面积自定义异常类 6-2 判断一个数列是…...

照片文件损坏能修复吗?

很多时候&#xff0c;我们都是把相机拍的照片保存在电脑上&#xff0c;或手机照片太多&#xff0c;也会上传到电脑里保存。这样就能腾出更多的存储空间。但在电脑里的照片文件有时会莫名其妙的损坏&#xff0c;提示已损坏等情况&#xff0c;一旦发生这样的事&#xff0c;这些照…...

Git分布式版本控制工具

1&#xff1a;目标了解Git基本概念 能够概述git工作流程 能够使用Git常用命令 熟悉Git代码托管服务 能够使用idea操作git 2&#xff1a;概述2.1&#xff1a;开发中的实际场景场景一&#xff1a;备份 小明负责的模块就要完成了&#xff0c;就在即将Release之前的一瞬间&#xff…...

Python爬虫(8)selenium爬虫后数据,存入sqlit3实现增删改查

之前的文章有关于更多操作方式详细解答&#xff0c;本篇基于前面的知识点进行操作&#xff0c;如果不了解可以先看之前的文章 Python爬虫&#xff08;8&#xff09;selenium爬虫后数据&#xff0c;存入sqlit3实现增删改查导入默认包和环境元素定位创建一个sqlit3表将爬虫到的信…...

最全Linux驱动开发全流程详细解析(持续更新)

Linux驱动开发详细解析 一、驱动概念 驱动与底层硬件直接打交道&#xff0c;充当了硬件与应用软件中间的桥梁。 具体任务 读写设备寄存器&#xff08;实现控制的方式&#xff09;完成设备的轮询、中断处理、DMA通信&#xff08;CPU与外设通信的方式&#xff09;进行物理内存…...

华为OD机试 - 乱序整数序列两数之和绝对值最小 | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …...

网上插画教学哪家质量好,汇总5大插画培训班

网上插画教学哪家质量好&#xff1f;给大家梳理了国内5家专业的插画师培训班&#xff0c;最新五大插画班排行榜&#xff0c;各有优势和特色&#xff01; 一&#xff1a;国内知名插画培训机构排名 1、轻微课&#xff08;五颗星&#xff09; 主打课程有日系插画、游戏原画、古风插…...

对云原生集群网络流量可观测性的一点思考

问题背景 在云原生技术的广泛普及和实施过程中&#xff0c;笔者接触到的很多用户需求里都涉及到对云原生集群的可观测性要求。 实现集群的可观测性&#xff0c;是进行集群安全防护的前提条件 。而在可观测性的需求中&#xff0c;集群中容器和容器之间网络流量的可观测性需求是…...

借力英特尔® Smart Edge,灵雀云 ACP 5G 专网解决方案获得多维度优化加速

近日&#xff0c;灵雀云联合英特尔推出了集成Smart Edge 模块的灵雀云 ACP 5G 专网解决方案&#xff0c;同时共同发布了《借力英特尔 Smart Edge&#xff0c;基于云原生解决方案的灵雀云 ACP 5G 专网版本获得多维度优化加速》白皮书。 得益于云计算技术和 5G 网络的高速发展&am…...

【Pytorch项目实战】基于PaddlenHub的口罩检测与语音提示

文章目录一、项目思路二、环境配置1.1、PaddlenHub模块&#xff08;飞桨预训练模型应用工具&#xff09;&#xff08;1&#xff09;预训练模型&#xff1a;pyramidbox_lite_mobile_mask&#xff08;2&#xff09;face_detection人脸检测模型&#xff08;默认为 pyramidbox_lite…...

EasyExcel 让Excel导入导出更简单

一、什么是EasyExcel?二、对比ApachePoi 其他Excel框架 优势在于哪里三、本质上对于原生做了哪些优化&#xff1f;四、有哪些功能五、如何实践&#xff1f; 5.1 常规文件读取5.2 常规文件写入5.3 常规WEB的上传和下载 一、什么是EasyExcel? EasyExcel是对07版POI的提升和优…...

华为OD机试 - 需要广播的服务器数量 | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …...

三次握手四次挥手详细解析面试常问

文章目录1.第2次握手传回了ACK&#xff0c;为什么还要传回SYN&#xff1f;2.断开连接-TCP 四次挥手3.为什么要四次挥手&#xff1f;4.为什么不能把服务器发送的 ACK 和 FIN 合并起来&#xff0c;变成三次挥手&#xff1f;5.如果第二次挥手时服务器的 ACK 没有送达客户端&#x…...

组合由于继承

目录 前言&#xff1a; 1.什么是继承&#xff1f; 2.继承的劣势、问题&#xff1f; 3.组合相比继承有哪些优势&#xff1f; 4、如何判断该用组合还是继承&#xff1f; 参考资料 前言&#xff1a; 我们在平时日常开发设计的过程中&#xff0c;经常会有人提到一条经典的设…...

大学计算机基础 知识点总结

一/ 计算机的发展、类型及其应用领域。 1. 计算机(computer)是一种能自动、高速进行大量算术运算和逻辑运算的电子设备。 其特点为&#xff1a;速度快、精度高、存储容量大、通用性强、具有逻辑判断和自动控制能力。 2. 第一台计算机&#xff1a;ENIAC&#xff0c;美国&#…...

手撸React组件库前必须清楚的9个问题

1. 组件库文档问题 以前常用的组件库文档storybook&#xff0c;包括现在也有用dumi、vitepress做组件库文档等。storybook缺点不美观、webpack的热更新太慢&#xff0c;虽然新版本支持了vite提高了速度但还不算稳定。好在各种文档、mdx、测试等组件第三方工具很多集成进去能很…...

试用国内及国外AI绘图软件后的总结

最近AI很火&#xff0c;所以这几天抱着试试看的角度试用了多款AI绘图软件&#xff0c;大概测试了市面上的3款工具吧&#xff0c;3款国外的&#xff0c;1款国内的。因为有对比&#xff0c;波哥也不是专业的评测机构出身&#xff0c;所以这些比对无论是从角度&#xff0c;还是从对…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...