【GStreamer开发】GStreamer基础教程02——GStreamer概念
上一个教程演示了如何自动生成一个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, charchar *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");
- ;
- }
- /* 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);
- ;
- }
- /* Modify the source's properties */
- , 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);
- ;
- }
- /* 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);
- ;
- }
工作流程
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);
- ;
- }
一个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 */
- , 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);
- ;
- }
我们调用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开发】GStreamer基础教程02——GStreamer概念的更多相关文章
- GStreamer基础教程02 - 基本概念
摘要 在 Gstreamer基础教程01 - Hello World中,我们介绍了如何快速的通过一个字符串创建一个简单的pipeline.为了能够更好的控制pipline中的element,我们需要单 ...
- (转)OpenLayers3基础教程——OL3基本概念
http://blog.csdn.net/gisshixisheng/article/details/46756275 OpenLayers3基础教程——OL3基本概念 从本节开始,我会陆陆续续的更新 ...
- Android程序开发0基础教程(一)
程序猿学英语就上视觉英语网 Android程序开发0基础教程(一) 平台简单介绍 令人激动的Google手机操作系统平台-Android在2007年11月13日正式公布了,这是一个开放源码的操 ...
- RabbitMq基础教程之基本概念
RabbitMq基础教程之基本概念 RabbitMQ是一个消息队列,和Kafka以及阿里的ActiveMQ从属性来讲,干的都是一回事.消息队列的主要目的实现消息的生产者和消费者之间的解耦,支持多应用之 ...
- 【GStreamer开发】GStreamer基础教程10——GStreamer工具
目标 GStreamer提供了一系列方便使用的工具.这篇教程里不牵涉任何代码,但还是会讲一些有用的内容: 如何在命令行下建立一个pipeline--完全不使用C 如何找出一个element的Capab ...
- OpenLayers3基础教程——OL3基本概念
从本节開始,我会陆陆续续的更新有关OL3的相关文章--OpenLayers3基础教程,欢迎大家关注我的博客,同一时候也希望我的博客可以给大家带来一点帮助. 概述: OpenLayers 3对OpenL ...
- Python基础教程-02
<Python基础教程> 第3章 使用字符串 字符串方法find返回的并非布尔值.如果find像这样返回0,就意味着它在索引0处找到 了指定的子串 join可合并一个字符串列表,不能合并数 ...
- 【Gstreamer开发】TI嵌入式处理器GStreamer pipeline
Example GStreamer Pipelines From Texas Instruments Embedded Processors Wiki Jump to: navigation, sea ...
- Java基础教程(4)--面向对象概念
如果你之前从来没有使用过面向对象编程语言,那么在学习Java之前需要先理解几个有关面向对象编程的基本概念.这篇教程将会向你介绍对象.类.集成.接口和包的概念,以及这些概念是如何与现实世界相关联,并 ...
随机推荐
- Linux 检测出口IP地址
找了几个 linux 下检测出口地址的(前提是能访问外网). curl ifconfig.me curl ipinfo.io/ip curl ipecho.net/plain
- WAMP 403 Forbidden禁止访问,别的电脑访问不了;
直接上图: 1:修改httpd.conf; deny from all 改成------ allow from all 重启服务就好了: 2:如果搜不到deny from all 就按照下面的方法来 ...
- pcl-qt使用QVTKWidget 与PCLVisualizer 显示雷达点云
#ifndef PCLVIEWER_H #define PCLVIEWER_H #include "defines.h" #include <iostream> #in ...
- Linux安装配置JDK与卸载
最近在Linux系统部署门户,安装Oracle,导入dmp,JDK等等,遇到一大堆问题,解决后特有一番小小成就感,哇哈哈!在这里记录一下遇到问题: 官网下载JDK压缩包( .tar.gz ):http ...
- Pro自定义数据源原理
1. 概念 Connector:定义连接到一个数据源的连接信息,用于创建datastore. Datastore:代表一个数据源的实例,用于打开一个或多个tables或feature class. ...
- SDOI2015做题记录
由于我懒,并且这里面除了D2T3恶心以外都不难写,所以很多代码都没写-- 排序 对于某一个合法的操作序列(操作序列定义为每次交换的两组数),可以随意交换顺序,仍然合法.所以对于一个操作集合,答案就加\ ...
- 实现一个简易版webpack
现实 webpack 的打包产物 大概长这样(只把核心代码留下来): 实现一个简版的webpack 依葫芦画瓢,实现思路分2步: 1. 分析入口文件,把所有的依赖找出来(包括所有后代的依赖) 2. 拼 ...
- JS-选项卡制作解释部分
<!DOCTYPE html> <html> <head> <meta name="author" content "郭菊锋,7 ...
- CF1203F2 Complete the Projects (hard version)(结论+背包+贪心)
题目 做法 对于加分的直接贪心 而掉分的用排序后的背包动规 假设有两个物品\((a_1,b_1)(a_2,b_2)\) 选第一个物品后无法选择第二个物品,假设开始值为\(r\):\(r>a_1, ...
- [Shell]MySql慢查询日志GetShell
通过开启慢查询日志,配置可解析日志文件GETSHELL. MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句. long_query_time的默认值 ...
