上一个教程演示了如何自动生成一个pipeline。这次我们打算用一个个element来手动搭建一个pipeline。我们这个教程会演示:

1. 什么是GStreamer的element以及如何建立一个element

2. 如何在element直接建立连接

3. 如何客制化element的行为

4. 如何监视总线上的错误并获得相关的信息

手动建立Hello World

把下面的代码copy到basic-turtorial-2.c文件

#include <gst/gst.h>int 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;
}

工作流程

GStreamer的基本组成是elements,这些elements把数据从source经过filter传到sink。

建立element

因为上一篇教程以及介绍过了初始化这段内容,所以我们这次略过这一段。

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

新的element的建立可以使用gst_element_factory_make()。这个API的第一个参数是要创建的element的类型(后面第14讲会介绍一些常见的类型,第10讲会介绍如何获得可用的类型列表),第二个参数是我们想创建的element的名字,这个名字并非是必须的,但在调试中会非常有用,如果你传入的时NULL,那么GStreamer会自动创建一个名字。

在本教程内我们创建了2个elements:videotestsrc和autovideosink.

vieotestsrc是一个source element(生产数据),会创建一个video模式。这个element常用在调试中,很少用于实际的应用。

autovideosink是一个sink element(消费数据),会在一个窗口显示收到的图像。在不同的操作系统中,会存在多个的video sink,autovideosink会自动选择一个最合适的,所以你不需要关心更多的细节,代码也会有更好的移植性。

建立pipeline

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

因为要统一处理时钟和一些信息,GStreamer中的所有elements都必须在使用之前包含到pipeline中。我们用gst_pipeline_new()来创建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就是一个特定类型的可以包含其他element的bin,而且所以可以用在bin上的方法也都可以用在pipeline上。在这个例子中,我们调用了gst_bin_add_many()方法在pipeline中加入element。这个方法会接受一系列的element作为输入参数,最后由NULL来终止。增加单个element的方法是gst_bin_add()。

这个时候,这些刚增加的elements还没有互相连接起来。我们用gst_element_link()方法来把element连接起来,这个方法的第一个参数是源,第二个参数是目标,这个顺序不能搞错,因为这确定了数据的流向。记住只有在同一个bin里面的element才能连接起来,所以一定要把element在连接之前加入到pipeline中。

属性

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

绝大部分的GStreamer elements有可以定制化的属性:只读的属性会显示element的内部状态,可写的属性会影响element的行为。我们用g_object_get()方法来获得属性,用g_object_set()方法来设置属性。

g_object_set()方法接受一个用NULL结束的属性名称/属性值的组成的对,所以可以一次同时修改多项属性。

上面的代码修改了videotestsrc的“pattern”属性,这个属性控制了视频的输出,大家可以试试不同的值看一下效果。

关于一个element的名字和取值范围,使用gst-inspect工具可以查询到。

错误检查

在这一点上,本系列的教程内容都比较相似,和第一讲没什么不同,只是我们监测更多的错误罢了。

  /* 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()方法,但这次我们检查它的返回值。状态转换是一个很微妙的过程,在下一篇教程中我们会有更多的一些细节。

  /* 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_filted()会一直等到运行结束,然后返回一个GstMessage参数。我们让gst_bus_timed_pop_filtered()方法仅在收到错误或者播放结束的消息时才返回。所以我们需要检查是哪个消息并打印出来。

GstMessage是一个非常通用的结构,它可以传递很多信息。幸好GStreamer提供了一系列的解析函数,在本教程里面,我们一旦知道message里面包含一个错误(通过使用GST_MESSAGE_TYPE宏),我们可以使用gst_message_parse_error()方法,这个方法会返回一个GLib的GError结构。

GStreamer总线

这里稍微介绍一下GStreamer总线。GStreamer总线本身也是一个对象,是创建来传递elements生成的GstMessage的对象。消息可以在总线上用gst_bus_timed_pop_filtered()方法抓出来,你的应用需要随时注意出错的信息和播放相关的其他问题。

其他的代码是释放内存的,和上一篇教程是一样的。

GStreamer基础教程02——GStreamer概念相关推荐

  1. GStreamer基础教程10——GStreamer工具

    目标 GStreamer提供了一系列方便使用的工具.这篇教程里不牵涉任何代码,但还是会讲一些有用的内容: 如何在命令行下建立一个pipeline--完全不使用C 如何找出一个element的Capab ...

  2. Gstreamer基础教程10: Gstreamer 工具

    文章目录 1. Goal 2. 介绍 3. gst-lanuch-1.0 3.1 Elements 3.2 Properties 3.3 Named elements 3.4 Pads 3.5 Cap ...

  3. Gstreamer基础教程10:GStreamer tools

    文章目录 目标 一.Introduction(简介) 二.gst-launch-1.0 1.Elements 2.Properties(属性) 3.Named elements(元素重命名) 4.Pa ...

  4. 【GStreamer开发】GStreamer基础教程07——多线程和Pad的有效性

    目标 GStreamer会自动处理多线程这部分,但在有些情况下,你需要手动对线程做解耦.本教程会教你怎样才能做到这一点,另外也展示了Pad的有效性.主要内容包括: 如何针对部分的pipeline建立一 ...

  5. (转)OpenLayers3基础教程——OL3基本概念

    http://blog.csdn.net/gisshixisheng/article/details/46756275 OpenLayers3基础教程--OL3基本概念 从本节开始,我会陆陆续续的更新 ...

  6. 【GStreamer学习】之GStreamer基础教程

    目标 没有什么比在屏幕上打印出"Hello World"更能获得对软件库的第一印象了! 但是由于我们正在学习多媒体框架,所以我们将输出"Hello World!" ...

  7. Gstreamer基础教程13:Playback Speed

    文章目录 1.Goal 2.介绍 3. A Trick mode player 3.1 Compile 3.2 Code 4.Analyze 5.讨论 1.Goal 快进.倒放和慢动作都是所谓的技巧模 ...

  8. OpenLayers3基础教程——OL3基本概念

    从本节开始,我会陆陆续续的更新有关OL3的相关文章--OpenLayers3基础教程,欢迎大家关注我的博客,同时也希望我的博客能够给大家带来一点帮助. 概述: OpenLayers 3对OpenLay ...

  9. GStreamer基础教程01 - Hello World

    摘要 在面对一个新的软件库时,第一步通常实现一个"hello world"程序,来了解库的用法.对于GStreamer,我们可以实现一个极简的播放器,来了解GStreamer的使用 ...

最新文章

  1. jacoco收集探针结果时机_滴滴开源Super-jacoco:java代码覆盖率收集平台
  2. MyEclipse搭建java Web项目开发环境
  3. [Jarvis OJ - PWN]——Typo(内涵peak小知识)
  4. 利用Photoshop减小照片景深
  5. 1476D. Journey
  6. linux内存管理之RSS和VSZ的区别
  7. 信息学奥赛C++语言:找第一个只出现一次的字符
  8. RESTful Web Services简单介绍
  9. 关于getResource和getClassLoader().getResource()
  10. [转载]PLSQL安装破解
  11. java开发常见的问题及解决办法 - java开发中遇到的难点有哪些_java开发常见的问题及解决办法
  12. 微信 android 点赞,朋友圈点赞生成器安卓-微信朋友圈点赞生成器2020安卓最新版app预约 v1.0-优盘手机站...
  13. CodeBlocks注释和替换快捷键
  14. java 保龄球游戏开发_保龄球游戏 编程
  15. 公平的席位分配(Q值方法)
  16. 《CAT NAUGHTY CARP》App Store 隱私政策網址(URL)
  17. opencv lbp 草坪_框架还是语言? 离开我的草坪!
  18. uni-app 开发微信公众号(H5)JSSDK 的使用方式
  19. 基于JAVA的机场航班起降与协调管理系统(论文+PPT+源码)
  20. 这一年,你遇见了谁?

热门文章

  1. Spring-Data-JPA EntityManager 从一次线上BUG探究Autowired和PersistenceContext的区别
  2. 安装wpa_supplicant工具
  3. tc流量控制原理和实现
  4. thingy_创建自己的手机条形码Thingy
  5. JavaScript实现图片文字识别与读取
  6. Windows10下Latex缺少sty文件时的安装方法
  7. WARN [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not
  8. 最常考的Java后台面试题(一)Java基础
  9. transform:translate
  10. EmguCV学习(二)