Gstreamer初见
来源:互联网 发布:毒品网络 电影 编辑:程序博客网 时间:2024/06/11 18:05
项目相关:网络视频播放器
系统: meego-1.2
应用: Qt + Gstreamer
应用使用的Gstreamer playbin2 控件。
(1) 概述
(1.1) Element, Pad, Caps 之间的关系。
+-------------------------------------+ | ELEMENT | |--------------+ +-------| |sinkpad | | | | +---------+ | | | | | caps | | |srcpad | | | caps | | | | | +---------+ | | | |--------------+ +-------| +-------------------------------------+这里列举实例如:qtdemux (quicktime demux)
这里简单列出,详细部分参考源码:gst-plugins-good-0.10.27/gst/qtdemux/qtdemux.c
static GstStaticPadTemplate gst_qtdemux_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; " "application/x-3gp") );static voidgst_qtdemux_init (GstQTDemux * qtdemux, GstQTDemuxClass * klass){ qtdemux->sinkpad = gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink"); gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);}static gbooleanqtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak){ stream->caps = qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec); qtdemux->streams[qtdemux->n_streams] = stream;}(1.2) playbin内部
+------------------------------------------------------------+ | playbin2 | | +---------------------------------------------------+ | | |uridecodebin | | | | +----------+ +----------+ +-----------+ | | | | | typefind | | queue2 | | decodebin | | | | |->| |>--->| |>--->| |> | | | | | | | | | | | | | | +----------+ +----------+ +-----------+ | | | +---------------------------------------------------+ | +------------------------------------------------------------+
(2) 链接(link)
gstreamer中,element, pad 都是通过gst_element_link_pads, 或gst_pad_link链接起来的。并且显然,pad嵌在element元件内部,当将两个element link起来时,真正发生的改变是什么呢?
(2.1) gst_element_lin_pads 与 gst_pad_link 对比
gbooleangst_element_link_pads (GstElement * src, const gchar * srcpadname, GstElement * dest, const gchar * destpadname){ return gst_element_link_pads_full (src, srcpadname, dest, destpadname, GST_PAD_LINK_CHECK_DEFAULT);}gbooleangst_element_link_pads_full (GstElement * src, const gchar * srcpadname, GstElement * dest, const gchar * destpadname, GstPadLinkCheck flags){ result = pad_link_maybe_ghosting (srcpad, destpad, flags);}static gbooleanpad_link_maybe_ghosting (GstPad * src, GstPad * sink, GstPadLinkCheck flags){ ret = (gst_pad_link_full (src, sink, flags) == GST_PAD_LINK_OK);}/* 和 gst_pad_link 一样 */GstPadLinkReturngst_pad_link (GstPad * srcpad, GstPad * sinkpad){ return gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_DEFAULT);}(2.2) pad link 到底做什么了?
GstPadLinkReturngst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags){ /* 这个参考 GstPad 的 structure, 这里就是互相将peer设置为对端 */ GST_PAD_PEER (srcpad) = sinkpad; GST_PAD_PEER (sinkpad) = srcpad; /* 如果有link func那么执行函数,大部分element中没有设置link func函数 */ if (GST_PAD_LINKFUNC (srcpad)) { result = GST_PAD_LINKFUNC (srcpad) (srcpad, sinkpad); } else if (GST_PAD_LINKFUNC (sinkpad)) { result = GST_PAD_LINKFUNC (sinkpad) (sinkpad, srcpad); } else { result = GST_PAD_LINK_OK; }}
这里就将两个element链接起来了,post message等操作,就可以发送消息,数据了
(3) 在element内/间,消息/数据是如何路径呢,下面我们分析下数据,事件原理与数据类似。
以queue2为例子,看看如何从sinkpad收到消息,以及从srcpad发送到对端的sinkpad中。
/* gstreamer-0.10.32/plugins/elements/gstqueue2.c */static voidgst_queue2_init (GstQueue2 * queue, GstQueue2Class * g_class){ /*创建sinkpad*/ queue->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); /* 设置sinkpad的chain function, 这个函数后面会用到, 也是sinkpad数据的入口*/ gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue2_chain)); queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); /* 这里是用srcpad开始向外推送数据 */ gst_pad_set_activatepush_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue2_src_activate_push));}/*我们从chain function开始看,为什么chain function是入口函数? 往下看*/static GstFlowReturngst_queue2_chain (GstPad * pad, GstBuffer * buffer){ gst_queue2_locked_enqueue (queue, buffer, TRUE); }static voidgst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, gboolean isbuffer){ if (isbuffer) { if (QUEUE_IS_USING_QUEUE (queue)) { queue->cur_level.buffers++; } } else if (GST_IS_EVENT (item)) { } if (item) { if (QUEUE_IS_USING_QUEUE (queue)) { /* 这里把buffer放在queue里 */ g_queue_push_tail (queue->queue, item); } }}/* 接收数据完成了,下面看srcpad向外推送数据 */static gbooleangst_queue2_src_activate_push (GstPad * pad, gboolean active){ if (active) { result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, pad); }}static voidgst_queue2_loop (GstPad * pad){ ret = gst_queue2_push_one (queue);}static GstFlowReturngst_queue2_push_one (GstQueue2 * queue){ data = gst_queue2_locked_dequeue (queue, &is_buffer); if (is_buffer) { /* 发送数据 */ result = gst_pad_push (queue->srcpad, buffer); } else if (GST_IS_EVENT (data)) { /* 这里是发送事件,会获取srcpad的peerpad,然后调用eventfunc,原理与发送数据类似 */ gst_pad_push_event (queue->srcpad, event); }}/* gstreamer/gst/gstpad.c */GstFlowReturngst_pad_push (GstPad * pad, GstBuffer * buffer){ /* 这个看起来很复杂,... 初一见,都觉得头疼,这么多层。 * 实际上并不复杂,他的作用就是,此前如果该gstpad,有过push操作,并建立好了路径,那么直接使用, * 否则跳到slow_path执行。 */ cache_ptr = (gpointer *) & pad->abidata.ABI.priv->cache_ptr; cache = pad_take_cache (pad, cache_ptr); if (G_UNLIKELY (cache == NULL)) goto slow_path; peer = cache->peer; ret = GST_PAD_CHAINFUNC (peer) (peer, buffer); return ret;slow_path: GstPadPushCache scache = { NULL, }; /* 实际上这里面一样是调用了srcpad的peer端的chain_func [注:与我们开始从chain_func分析吻合] */ ret = gst_pad_push_data (pad, TRUE, buffer, &scache); if (scache.peer) { /* 这里就将cache_ptr 赋值到pad->abidata.ABI.priv->cache_ptr 这么长的里面了 */ pad_put_cache (pad, ncache, cache_ptr); }}/* 贯彻到底,我们将srcpad最后的调用对端的chainfunc挖出来 */static GstFlowReturngst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data, GstPadPushCache * cache){ if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) goto not_linked; ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, cache); }static inline GstFlowReturngst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, GstPadPushCache * cache){ if (G_LIKELY (is_buffer)) { if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL)) goto no_function; /* 这里调用了srcpad的peer端的 chainfunc 开始执行。 queue2的chainfunc一样的开始道理 */ ret = chainfunc (pad, GST_BUFFER_CAST (data)); }}
- Gstreamer初见
- Gstreamer初见
- 初见
- 初见
- 初见
- 初见
- 初见
- gstreamer
- Gstreamer
- gstreamer
- gstreamer
- GStreamer
- 初见 Catalyst
- Hadoop初见
- 初见端倪
- 初见面
- 初见python
- usb初见
- 反编译工具jad的使用
- 注解类是什么
- 理解IIS中的Host Header
- 使用java命令行执行依赖外部jar包的class文件
- c++编码规范
- Gstreamer初见
- 强大的开发工具 pry
- [WebService Test]: 3. SOAP
- 设计模式--迭代器模式
- Aspnetpager+GridView+oracle实现分页功能
- 对象的创建方法一之------工厂模式
- vc注册表函数大全
- 计算机软件之母
- 关于URL编码