GStreamer——教程——基础教程2:GStreamer concepts

news2024/11/28 9:44:22

基本教程2:GStreamer概念

1,目标

之前的教程展示了如何自动构建管道。现在我们将手动构建一条pipeline:初始化每一个element并将它们连接起来。在此过程中,我们将学习:

  • 什么是GStreamer元素以及如何创建一个。

  • 如何将elements相互连接。

  • 如何自定义element的行为(属性)。

  • 如何监视bus的错误条件并从GStreamer messages 中提取信息。

2,自制 Hello World

将此代码复制到名为basic-tutorial-2.c文本文件中(或找到它 在您的GStreamer安装中)。

基础教程

#include <gst/gst.h>

#ifdef __APPLE__
#include <TargetConditionals.h>
#endif

int
tutorial_main (int argc, char *argv[])
{
  GstElement *pipeline, *source, *sink;
  GstBus *bus;
  GstMessage *msg;
  GstStateChangeReturn ret;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  /* Create the elements */
  source = gst_element_factory_make ("videotestsrc", "source");
  sink = gst_element_factory_make ("autovideosink", "sink");

  /* Create the empty pipeline */
  pipeline = gst_pipeline_new ("test-pipeline");

  if (!pipeline || !source || !sink) {
    g_printerr ("Not all elements could be created.\n");
    return -1;
  }

  /* Build the pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
  if (gst_element_link (source, sink) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return -1;
  }

  /* Modify the source's properties */
  g_object_set (source, "pattern", 0, NULL);

  /* Start playing */
  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return -1;
  }

  /* Wait until error or EOS */
  bus = gst_element_get_bus (pipeline);
  msg =
      gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
      GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

  /* Parse message */
  if (msg != NULL) {
    GError *err;
    gchar *debug_info;

    switch (GST_MESSAGE_TYPE (msg)) {
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (msg, &err, &debug_info);
        g_printerr ("Error received from element %s: %s\n",
            GST_OBJECT_NAME (msg->src), err->message);
        g_printerr ("Debugging information: %s\n",
            debug_info ? debug_info : "none");
        g_clear_error (&err);
        g_free (debug_info);
        break;
      case GST_MESSAGE_EOS:
        g_print ("End-Of-Stream reached.\n");
        break;
      default:
        /* We should not reach here because we only asked for ERRORs and EOS */
        g_printerr ("Unexpected message received.\n");
        break;
    }
    gst_message_unref (msg);
  }

  /* Free resources */
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}

int
main (int argc, char *argv[])
{
#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE
  return gst_macos_main ((GstMainFunc) tutorial_main, argc, argv, NULL);
#else
  return tutorial_main (argc, argv);
#endif
}

需要帮忙吗?

如果您需要帮助来编译此代码,请参阅为您的平台构建教程部分:Linux、Mac OS X或Windows,或在Linux上使用此特定命令:

gcc basic-tutorial-2.c -o basic-tutorial-2 `pkg-config --cflags --libs gstreamer-1.0`

如果您需要帮助来运行此代码,请参阅您平台的运行教程部分:Linux、Mac OS X[2]或Windows。

本教程打开一个窗口并显示一个测试模式,没有音频

所需库:gstreamer-1.0

3,工作流

这些 element 是GStreamer的基本构造单位。它们处理从source element(数据生产者)通过filter element流向sink element(数据消费者)的数据。

图1.示例管道

3.1,创建 element

我们将跳过GStreamer初始化,因为它与之前的教程相同:

  /* Create the elements */
  source = gst_element_factory_make ("videotestsrc", "source");
  sink = gst_element_factory_make ("autovideosink", "sink");

如本代码所示,如何使用gst_element_factory_make()新建一个element 。

第一个参数是要创建的element名,即插件名(基本教程14:方便的元素显示了一个 一些常见类型和基本教程10:GStreamer工具展示了如何 获取所有可用类型的列表)。

第二个参数是给这个特殊实例起的名称,在同一条pipeline中,必须是唯一的名称。如果你没有保留指针,给 element名可以方便你在以后检索它们(并且可以得到更有意义的调试输出)。但是,假如你传递NULL作为实例名,GStreamer也会自动为它初始化一个唯一的名称。

3.2,创建 pipeline

对于本教程,我们创建两个元素:videotestsrc 和 autovideosink。中间没有filter element,所以整个pipeline看起来就如下图:

图2.本教程中构建的管道

Videotestsrc是一个按照制定pattern生成测试视频source element(它将生产数据),这个插件在测试和教程中很好用,但通常并不会出现在真实的应用中。

autovideosink是一个在窗口中播放它接收到的图像的sink element(它将消费数据),GStreamer包含有很多视频sink element,具体取决于操作系统,它们能够处理不同的图像格式,autovideosink将自动选择其中一个并实例话化,所以用户不需要担心平台兼容性问题。

  /* Create the empty pipeline */
  pipeline = gst_pipeline_new ("test-pipeline");

gst_pipeline_new()创建 pipeline,GStreamer中的所有元素在使用之前通常必须包含在一条pipeline 中,pipeline将负责一些时钟和消息功能。

  /* Build the pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
  if (gst_element_link (source, sink) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return -1;
  }

一条pipeline也是一个特殊的 bin,它是用于 包含其他elements。因此,适用于bin的所有方法也适用于pipeline。

在我们的例子中,我们调用gst_bin_add_many()来将elements添加到pipeline中(注意映射)。此函数接受一个要被添加到pipeline中的element列表,因为不确定列表长度所以需要以NULL结尾。添加单个element可以使gst_bin_add()。

然而,这些元素还没有相互联系。为此, 我们需要使用gst_element_link()。它的第一个参数是source, 第二个是destination。顺序很重要,因为链接必须按照数据流建立(即,从source elemnt到sink element)。请记住,只有 element 驻留在同一个bin中可以链接在一起,所以记得在之前将它们添加到pipeline中试图链接它们!

3.3,属性

GStreamer元素都是一种特殊的GObject,它是提供属性设施的实体。

大多数GStreamer元素都具有可自定义的属性:可以修改的命名属性以更改元素的行为(可写属性)或查询以了解元素的内部状态(可读属性)。

属性从g_object_get()中读取并写入用g_object_set()。

g_object_set()可以接受一个以NULL结束的属性名-属性值键值对列表,所以可以一次性设置多个属性。

这就是为什么属性处理方法具有g_前缀的原因。

回到上面的例子中,

  /* Modify the source's properties */
  g_object_set (source, "pattern", 0, NULL);

上面的代码行改变了videotestsrc的“pattern”属性, 它控制元素输出的测试视频类型。尝试不同的 值!

element 公开的所有属性的名称和可能值可以使用基本教程10:GStreamer工具或该元素的文档中描述的gst-inspect-1.0工具找到 (这里指的是videotestsrc)。

3.4,Error 监听

至此,我们已经构建和设置了整个管道,教程的其余部分与上一个非常相似,但我们将添加更多错误检查:

  /* Start playing */
  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return -1;
  }

我们调用gst_element_set_state(),但是这次将检查状态改变的返回值。假如状态修改失败,将返回一个error值并进行相关退出处理,还有更多详细信息在基础教程3:动态管道中给出。

  /* Wait until error or EOS */
  bus = gst_element_get_bus (pipeline);
  msg =
      gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
      GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

  /* Parse message */
  if (msg != NULL) {
    GError *err;
    gchar *debug_info;

    switch (GST_MESSAGE_TYPE (msg)) {
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (msg, &err, &debug_info);
        g_printerr ("Error received from element %s: %s\n",
            GST_OBJECT_NAME (msg->src), err->message);
        g_printerr ("Debugging information: %s\n",
            debug_info ? debug_info : "none");
        g_clear_error (&err);
        g_free (debug_info);
        break;
      case GST_MESSAGE_EOS:
        g_print ("End-Of-Stream reached.\n");
        break;
      default:
        /* We should not reach here because we only asked for ERRORs and EOS */
        g_printerr ("Unexpected message received.\n");
        break;
    }
    gst_message_unref (msg);
  }

gst_bus_timed_pop_filtered() 等待执行结束并返回带有我们之前忽略的GstMessage。我们要求gst_bus_timed_pop_filtered() 返回时GStreamer 遇到错误条件或EOS,所以我们需要检查发生了哪一个,并在屏幕上打印一条消息(您的应用程序将可能想采取更复杂的行动)。

GstMessage是一个非常通用的结构,它可以传递几乎任何类型的信息。幸运的是,GStreamer提供了一系列消息的解析函数。

在这种情况下,一旦我们知道消息包含错误(通过使用 GST_MESSAGE_TYPE() 宏),我们可以使用 gst_message_parse_error() 返回GLib的GError结构和对调试有用的字符串。检查代码以了解如何这些被使用并在之后释放。

3.5,GStreamer bus

在这一点上,值得更正式地介绍一下GStreamer bus 。GStreamer bus它是负责将element生成的GstMessages 按顺序交付给应用程序和应用程序线程(这点很重要,因此GStreamer实际是在其他的线程中处理媒体流)的对象。

消息可以通过 gst_bus_timed_pop_filtered()及其相关函数同步地从总线中提取,或者通过信号异步地提取(如在下一个教程中所示)。你的应用程序应该始终关注总线,以便被通知错误和其他与播放相关的问题。

其余的代码是清理序列,与基础教程1: Hello world!中的相同。

4,练习

如果您想练习,请尝试此练习:尝试在这条example pipeline的source和sink之间添加视频filter element,例如vertigotv,你需要创建它,将它加入pipeline,并将它和pipeline中的其他元素连接起来。

根据您的平台和可用插件,您可能会得到一个 “negotiation”错误,因为sink element 正在生产什么(更多关于基本教程6:媒体格式和Pad功能的协商)。在这种情况下你需要在filter 之后添加videoconvert(即构建一个4个元素的管道。更多关于 videoconvert在基本教程14:Handy elements)。

5,总结

本教程展示了:

  • 如何使用gst_element_factory_make() 创建element

  • 如何使用gst_pipeline_new()创建一个空的pipeline。

  • 如何使用gst_bin_add_many()向pipeline中添加element。

  • 如何使用gst_element_link()连接element。

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

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

相关文章

redis设计与实现(五)RDB与AOF持久化

RDB持久化 因为Redis是内存数据库&#xff0c;它将自己的数据库状态储存在内存里面&#xff0c;所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面&#xff0c;那么一旦服务器进程退出&#xff0c;服务器中的数据库状态也会消失不见。 为了解决这个问题&#xff0c;…

CC2500和CC1101移植说明

主要通过如何移植、移植注意、关于芯片配置、如何生成导出配置四大步骤来说明CC2500和CC1101移植 首先通过下图1这个宏进行选择 如何移植 要移植的部分在 CC2500_hal.c 和 CC2500_hal.h中, 搜索 "//移植" 就可以定位到 库 所需的依赖, 需要根据 您的环境实现这些…

sap怎么批量给信息记录打上删除标识

1.MEMASSIN-----事务代码 2.选择完成字段 3.根据条件查询需要冻结的信息记录 4.输入查询条件 5.全部勾选完成标识&#xff0c;点击保存&#xff0c;即可冻结完成

AI Stable diffusion 报错:稳定扩散模型加载失败,退出

可能是内存不够&#xff0c;看看你最近是加了新的大的模型&#xff0c;可以把你的stable-diffusion-webui\models\Stable-diffusion目录下的某个ckpt删除掉&#xff0c;可能ckpt太大&#xff0c;无法加载成功&#xff1b; Stable diffusion model failed to load, exiting 如图…

【RAM】利用AWS Resource Access Manager服务实现与其他账户共享AWS资源

文章目录 1. 先决条件说明2. 导航至ARM控制面板3. 指定资源共享详细信息4. 关联托管式权限5. 向委托人授予访问权限6. 查看和创建7. 查看由我共享的资源8. 资源共享详细信息9. 取消关联10. 参考链接11. 生成式AI书籍推荐&#x1f4e2; 1. 先决条件说明 报错现象&#xff1a; …

工业屏:千万不要以为电脑显示啥样,工业屏就啥样,注意色差。

重要的事情说三遍&#xff1a;一定要放到实际场景下调色&#xff0c;定要放到实际场景下调色&#xff0c;定要放到实际场景下调色。 工业控制屏的色域通常比普通电脑显示器要小。工业控制屏主要用于工业环境中&#xff0c;需要满足特定行业的需求和标准。由于工业控制屏的设计…

④-2单细胞学习-cellchat单数据代码补充版(通讯网络)

目录 通讯网络系统分析 ①社会网络分析 1&#xff0c;计算每个细胞群的网络中心性指标 2&#xff0c;识别细胞的信号流模式 ②非负矩阵分解&#xff08;NMF&#xff09;识别细胞的通讯模式 1&#xff0c;信号输出细胞的模式识别 2&#xff0c;信号输入细胞的模式识别 信…

el-table表头修改文字或者背景颜色,通过header-row-style设置样式

方式一 <el-table :header-cell-style"{text-align: center}" />方式二 <template><el-table :header-cell-style"tableHeaderColor" /> </template> <script> export default {methods: {tableHeaderColor ({row, column…

驱动开发(三):内核层控制硬件层

驱动开发系列文章&#xff1a; 驱动开发&#xff08;一&#xff09;&#xff1a;驱动代码的基本框架 驱动开发&#xff08;二&#xff09;&#xff1a;创建字符设备驱动 驱动开发&#xff08;三&#xff09;&#xff1a;内核层控制硬件层​​​​​​​ ←本文 目录…

一般简单的功能使用GIS 服务器工具还需要进行扩展开发吗?

有网友困惑怎么使用了我们的 GIS 服务器工具&#xff0c;一些简单的功能需不需要对服务器进行扩展开发&#xff1f;下面我们首先看一下标准GIS WEB服务器例如GEOSERVER&#xff0c;QGISSERVER、GIS数据快捷共享发布工具&#xff08;建立自己的地图网站&#xff09;及其它一些商…

技术转管理,是灾难还是奇迹?

深耕技术or转战管理&#xff1f;this is a question! 如果你还没有想好&#xff0c;那请继续往下看&#xff01; 技术专家&#xff1a;技术前瞻者、方案构建者、难题破解者、团队聚核者 管理专家&#xff1a;战略规划者、高效组织者、变革引领者、团队建设者 特点和重心都不在…

还在用Flex布局?OUT了 快来看看grid布局吧!

还在用Flex布局&#xff1f;OUT了 快来看看grid布局吧&#xff01; 之前我在写布局的时候就喜欢用flex&#xff0c;有一次我需要实现四个方块占一行的需求 &#xff0c;But 一共有七个方块到了第二行很Egg疼 &#xff0c;第二行它直接三个方块居中排布&#xff0c; 这三兄弟直…

什么是GPT-4

什么是GPT-4 ChatGPT 可以说&#xff0c;ChatGPT的发展&#xff0c;主要的分水岭在GPT-4&#xff0c;GPT-4主要是文本对话&#xff0c;且训练度也不够完善。GPT-4之后不但训练度得到了巨大提升&#xff0c;模型支持的参数量更是预计有1万亿参数&#xff0c;在这之后出现的GPT-4…

电机控制安全:PWM 直通

在 H 桥中使用互补 PWM 时的一个主要考虑因素是短路的可能性&#xff0c;也称为“击穿”。 如图 5 所示&#xff0c;如果同一支路上的两个开关同时打开&#xff0c;H 桥配置可能会导致电源和接地之间发生直接短路。 如果同一条腿上的两个开关同时打开&#xff0c;则可能会发生…

【Kafka】Kafka Producer 分区-05

【Kafka】Kafka Producer 分区-05 1. 分区的好处2. 分区策略2.1 默认的分区器 DefaultPartitioner 3. 自定义分区器 1. 分区的好处 &#xff08;1&#xff09;便于合理使用存储资源&#xff0c;每个Partition在一个Broker上存储&#xff0c;可以把海量的数据按照分区切割成一块…

sslyze一键检查服务器检查服务器的 SSL/TLS 安全性(KALI工具系列二十五)

目录 1、KALI LINUX 简介 2、sslyze工具简介 3、信息收集 3.1 目标主机IP&#xff08;服务器&#xff09; 3.2 KALI的IP 4、操作示例 4.1 扫描主机和端口 4.2 批量扫描 4.3 插件扫描 4.4 输出结果 5、总结 1、KALI LINUX 简介 Kali Linux 是一个功能强大、多才多艺…

【会议征稿,ACM出版】2024年云计算与大数据国际学术会议(ICCBD 2024,7月26-28)

2024年云计算与大数据国际学术会议(ICCBD 2024)将于2024年7月26-28日在中国大理召开。ICCBD 2024将围绕“云计算与大数据”的最新研究领域, 旨在为从事研究的专家、学者、工程师和技术人员提供一个国际平台&#xff0c;分享科研成果和尖端技术&#xff0c;了解学术发展趋势&…

潮玩宇宙大逃杀APP系统开发成品案例分享指南

这是一款多人游戏&#xff0c;玩家需要选择一个房间躲避杀手。满足人数后&#xff0c;杀手会随机挑选一个房间杀掉里面所有的参与者&#xff0c;其他房间的幸存者将平均瓜分被杀房间的元宝。玩家在选中房间后&#xff0c;倒计时结束前可以自由切换不同房间。 软件项目开发成品…

B3981 [信息与未来 2024] 图灵完备

题目描述 &#xff08;你不需要看懂这张图片&#xff1b;但如果你看懂了&#xff0c;会觉得它很有趣。&#xff09; JavaScript 是一种功能强大且灵活的编程语言&#xff0c;也是现代 Web 开发的三大支柱之一 (另外两个是 HTML 和 CSS)。灵活的 JavaScript 包含“自动类型转换…

python-jupyter notebook安装教程

&#x1f308;所属专栏&#xff1a;【python】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的…