1 代码

#include <gst/gst.h>/* Structure to contain all our information, so we can pass it to callbacks */
/* 这里存下了所有需要的局部变量,因为本教程中会有回调函数,使用struct比较方便 */
typedef struct _CustomData
{GstElement *pipeline;GstElement *source;GstElement *convert;GstElement *resample;GstElement *sink;
} CustomData;/* Handler for the pad-added signal */
static void pad_added_handler (GstElement * src, GstPad * pad,CustomData * data);int
main (int argc, char *argv[])
{CustomData data;GstBus *bus;GstMessage *msg;GstStateChangeReturn ret;gboolean terminate = FALSE;/* Initialize GStreamer */gst_init (&argc, &argv);/* Create the elements *//* 我的理解是:uridecodebin创建的时候,没有初始化内部source pad,是因为内部带有demuxer */data.source = gst_element_factory_make ("uridecodebin", "source");data.convert = gst_element_factory_make ("audioconvert", "convert");data.resample = gst_element_factory_make ("audioresample", "resample");data.sink = gst_element_factory_make ("autoaudiosink", "sink");/* Create the empty pipeline */data.pipeline = gst_pipeline_new ("test-pipeline");if (!data.pipeline || !data.source || !data.convert || !data.resample|| !data.sink) {g_printerr ("Not all elements could be created.\n");return -1;}/* Build the pipeline. Note that we are NOT linking the source at this* point. We will do it later. */gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert,data.resample, data.sink, NULL);/* 这儿没有吧source连接上,因为这个时候还没有source pad */if (!gst_element_link_many (data.convert, data.resample, data.sink, NULL)) {g_printerr ("Elements could not be linked.\n");gst_object_unref (data.pipeline);return -1;}/* Set the URI to play */g_object_set (data.source, "uri","https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm",NULL);/* Connect to the pad-added signal *//* 在这里把回调函数的src data变量指定参数*/g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler),&data);/* Start playing */ret = gst_element_set_state (data.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 (data.pipeline);return -1;}/* Listen to the bus */bus = gst_element_get_bus (data.pipeline);do {msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,GST_MESSAGE_STATE_CHANGED | 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);terminate = TRUE;break;case GST_MESSAGE_EOS:g_print ("End-Of-Stream reached.\n");terminate = TRUE;break;case GST_MESSAGE_STATE_CHANGED:/* We are only interested in state-changed messages from the pipeline */if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {GstState old_state, new_state, pending_state;gst_message_parse_state_changed (msg, &old_state, &new_state,&pending_state);g_print ("Pipeline state changed from %s to %s:\n",gst_element_state_get_name (old_state),gst_element_state_get_name (new_state));}break;default:/* We should not reach here */g_printerr ("Unexpected message received.\n");break;}gst_message_unref (msg);}} while (!terminate);/* Free resources */gst_object_unref (bus);gst_element_set_state (data.pipeline, GST_STATE_NULL);gst_object_unref (data.pipeline);return 0;
}/* This function will be called by the pad-added signal */
static void
pad_added_handler (GstElement * src, GstPad * new_pad, CustomData * data)
{GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");GstPadLinkReturn ret;GstCaps *new_pad_caps = NULL;GstStructure *new_pad_struct = NULL;const gchar *new_pad_type = NULL;g_print("1\n");g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad),GST_ELEMENT_NAME (src));/* If our converter is already linked, we have nothing to do here */if (gst_pad_is_linked (sink_pad)) {g_print ("We are already linked. Ignoring.\n");goto exit;}/* Check the new pad's type */new_pad_caps = gst_pad_get_current_caps (new_pad);new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);new_pad_type = gst_structure_get_name (new_pad_struct);if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {g_print ("It has type '%s' which is not raw audio. Ignoring.\n",new_pad_type);goto exit;}/* Attempt the link */ret = gst_pad_link (new_pad, sink_pad);if (GST_PAD_LINK_FAILED (ret)) {g_print ("Type is '%s' but link failed.\n", new_pad_type);} else {g_print ("Link succeeded (type '%s').\n", new_pad_type);}exit:/* Unreference the new pad's caps, if we got them */if (new_pad_caps != NULL)gst_caps_unref (new_pad_caps);/* Unreference the sink pad */gst_object_unref (sink_pad);
}

2 代码分析

  主要分析一些官方手册这一节没有介绍到的函数。

2.1 通过element和pad名字检索到已存在的GstPad

GstPad* gst_element_get_static_pad (GstElement *element, const gchar *name);

  这是通过 gst-inspect-1.0 audioconvert 命令查看Pad,由图片信息可知道,pad的名字是sink和src。所以通过该函数可以得到Pad。只能查找Availability:Always的元素的Pad。name等于sink或者src。

2.2 查看Pad类型

/* 获得pad的Capabilities地址 */
GstCaps * gst_pad_get_current_caps (GstPad *pad);
/* 获得Capabilities中包含结构体信息 */
GstStructure * gst_caps_get_structure (const GstCaps *caps,guint index);
/* 读出type */
const gchar * gst_structure_get_name (const GstStructure *structure);struct _GstStructure {GType type;/*< private >*/GQuark name;
};

2.4 Message和Cap都继承于mini_object

struct _GstCaps {GstMiniObject mini_object;
};struct _GstMessage
{GstMiniObject   mini_object;/*< public > *//* with COW */GstMessageType  type;guint64         timestamp;GstObject      *src;guint32         seqnum;/*< private >*//* with MESSAGE_LOCK */GMutex          lock;                 /* lock and cond for async delivery */GCond           cond;
};

  释放资源函数

static inline void
gst_caps_unref (GstCaps * caps)
{gst_mini_object_unref (GST_MINI_OBJECT_CAST (caps));
}static inline void
gst_message_unref (GstMessage * msg)
{gst_mini_object_unref (GST_MINI_OBJECT_CAST (msg));
}

3 函数总结

/*1.查看Message信息是那个element发出*/
GST_MESSAGE_SRC(message) /*2.从message读取管道状态*/
void gst_message_parse_state_changed (GstMessage *message, GstState *oldstate,GstState *newstate, GstState *pending);
/*3.获得状态字符串*/
const gchar* gst_element_state_get_name (GstState state);/*4.*/
GstPad* gst_element_get_static_pad(GstElement *element, const gchar *name);

4. 继承关系

4.1 GstObject

GObject╰──GInitiallyUnowned╰──GstObject╰──GstAllocator╰──GstBufferPool╰──GstBus╰──GstClock╰──GstControlBinding╰──GstControlSource╰──GstDevice╰──GstDeviceMonitor╰──GstDeviceProvider╰──GstElement╰──GstPad╰──GstPadTemplate╰──GstPlugin╰──GstPluginFeature╰──GstRegistry╰──GstStream╰──GstStreamCollection╰──GstTask╰──GstTaskPool╰──GstTracer╰──GstTracerRecord

4.2 GstMiniObject

  GstMiniObject是一个种简单的,能够实现可计数类型结构。查看该结构并没有继承GObject对象,所以,任何继承于GstMiniObject的类都不可以使用GObject类的功能。主要要区别GstObject和GstMiniObject。GstObject中有属性、信号,后者没有。

struct _GstMiniObject {GType   type;/*< public >*/ /* with COW */gint    refcount; gint    lockstate;guint   flags;GstMiniObjectCopyFunction copy;GstMiniObjectDisposeFunction dispose;GstMiniObjectFreeFunction free;/* < private > *//* Used to keep track of weak ref notifies and qdata */guint n_qdata;gpointer qdata;
};
GstMiniObject╰──GstBuffer /*缓冲*/╰──GstCaps /*Pad的相关信息*/╰──GstMessage /*管道的消息*/╰──GstEvent╰──GstQuery

5. 获得name宏和函数总结

#define GST_PAD_NAME(pad)          (GST_OBJECT_NAME(pad))
#define GST_ELEMENT_NAME(elem)    (GST_OBJECT_NAME(elem))#define gst_pad_get_name(pad)       gst_object_get_name(GST_OBJECT_CAST (pad))
#define gst_element_get_name(elem)  gst_object_get_name(GST_OBJECT_CAST(elem))
gchar*  gst_object_get_name         (GstObject *object);

  从上面不难发现,无论Pad还是Element得到对象名称的时候,宏定义后面使用的函数都是相同的。

三、动态构建GStreamer管道相关推荐

  1. 07 Confluent_Kafka权威指南 第七章: 构建数据管道

    文章目录 CHAPTER 7 Building Data Pipelines 构建数据管道 将数据集成到上下文 Considerations When Building Data Pipelines ...

  2. Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑

    原文:Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必 ...

  3. Vue动态构建混合数据Treeselect选择树及巨树问题的解决方法

    今天在项目中需要通过行政区域选择,然后选择该行政区域下面的景区,也就是要构建行政区划.景区两表数据表的树. 全国的行政区域到县已经3500多了,再加上景区会有几万个点,这棵选择树不论是在后台还是在前台 ...

  4. VUE 动态构建混合数据Treeselect选择树,同时解决巨树问题

    今天在项目中需要通过行政区域选择,然后选择该行政区域下面的景区,也就是要构建行政区划.景区两表数据表的树.全国的行政区域到县已经3500多了,再加上景区会有几万个点,这棵选择树不论是在后台还是在前台构 ...

  5. LINQ to SQL 运行时动态构建查询条件

    原文地址:http://msdn.microsoft.com/zh-cn/dd567295.aspx 在进行数据查询时,经常碰到需要动态构建查询条件.使用LINQ实现这个需求可能会比以前拼接SQL语句 ...

  6. 多个客户端抢夺命名管道_使用Kafka构建数据管道

    目标:使用Kafka和使用Redis的服务层编写数据管道. 先决条件 请根据您的操作系统安装以下组件: · Kafka · Zookeeper · Redis · Java 目标观众 本文针对的是正在 ...

  7. python 机器学习管道_构建机器学习管道-第1部分

    python 机器学习管道 Below are the usual steps involved in building the ML pipeline: 以下是构建ML管道所涉及的通常步骤: Imp ...

  8. jenkins部署三种构建方式的详细步骤

    部署背景: jenkins:                     CentOS 7.4C         IP:172.16.3.74 gitlab-11.5.3:             Cen ...

  9. devops 开源工具链_使用开源工具构建DevOps管道的初学者指南

    devops 开源工具链 DevOps已成为修复缓慢,孤立或其他功能不正常的软件开发流程的默认答案. 但是,当您不熟悉DevOps并且不确定从哪里开始时,这并不意味着什么. 本文探讨了什么是DevOp ...

  10. h5select动态加载数据_HTML5+中动态构建列表并填充数据

    部分代码参考demo----<历史上的今天>. 感谢作者的分享,愿好人一生平安,虽然只有两个页面,但是通过这个示例让我学会了5+中如何动态构建列表并填充数据,非常实用. html部分: 历 ...

最新文章

  1. SpringBoot整合Swagger测试api构建
  2. android 计算运动速度,android – 计算参考真北的加速度
  3. tomcat改项目的访问路径 ROOT
  4. 扩展SpringMVC WebMvcConfigurerAdapter ||全面接管SpringMVC @EnableWebMvc
  5. Spring boot其他框架日志
  6. XCTF_Web_新手练习区:command_execution
  7. C++(20)--类型自动转换
  8. Java环境的正确配置你会了吗?
  9. javascript编写_如何在JavaScript中使用解构来编写更简洁,功能更强大的代码
  10. Intel保护机制:特权级别:Protection Rings
  11. echarts 报错问题 is null 或者未定义等问题
  12. [Java][Android][Process] Process 创建+控制+分析 经验浅谈
  13. 防止各大网盘下载限速解决方案--idman
  14. yum源配置的三种方法
  15. 【PyTorch教程】P30 GPU加速
  16. 简单三招,设计复杂ERP报表
  17. win7 efi安装(个人心得)
  18. 使用fsck命令检查并修复linux文件系统
  19. 地方政府留言板文本数据
  20. text/plain

热门文章

  1. ruby + cucumber环境搭建
  2. 孤独星球android app,《孤独星球》终于出了全套免费的旅行指南APP !
  3. 02.Rocky8安装KVM
  4. CyanogenMod源码下载和编译
  5. android 闪屏图片,Android的闪屏图像尺寸,以适应所有设备Android的闪屏图像尺寸,以适应所有设备(Andro...
  6. html中颜色打字机效果,Css打字机效果
  7. 【Servlet入门】一篇文章让你从没听过到了熟于心
  8. marshmallow文档
  9. CSS生日快乐:CSS之父Håkon Wium Lie访谈录
  10. VUE提示Gradient has outdated direction syntax