当前位置: 首页 > news >正文

gst_pad_query_default以及gst_pad_event_default

我们知道event和query可以在管道中流动(上游/下游),但是元件内部是如何流动的呢?也就是

如何从元件的srcpad流动到sinpad?

1.gst_pad_event_default函数

/*** gst_pad_event_default:* @pad: a #GstPad to call the default event handler on.* @parent: (allow-none): the parent of @pad or %NULL* @event: (transfer full): the #GstEvent to handle.** Invokes the default event handler for the given pad.** The EOS event will pause the task associated with @pad before it is forwarded* to all internally linked pads,** The event is sent to all pads internally linked to @pad. This function* takes ownership of @event.** Returns: %TRUE if the event was sent successfully.*/
gboolean
gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event)
{gboolean result, forward = TRUE;g_return_val_if_fail (GST_IS_PAD (pad), FALSE);g_return_val_if_fail (event != NULL, FALSE);GST_LOG_OBJECT (pad, "default event handler for event %" GST_PTR_FORMAT,event);switch (GST_EVENT_TYPE (event)) {case GST_EVENT_CAPS:forward = GST_PAD_IS_PROXY_CAPS (pad);result = TRUE;break;default:break;}if (forward) {EventData data;data.event = event;data.dispatched = FALSE;data.result = FALSE;gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data);/* for sinkpads without a parent element or without internal links, nothing* will be dispatched but we still want to return TRUE. */if (data.dispatched)result = data.result;elseresult = TRUE;}gst_event_unref (event);return result;
}

关键流程:

1.对于GST_EVENT_CAPS事件,需要判断是否是GST_PAD_IS_PROXY_CAPS(pad)

2.gst_pad_forward,这里就是event在元件内部流动的函数

static gboolean
event_forward_func (GstPad * pad, EventData * data)
{/* for each pad we send to, we should ref the event; it's up* to downstream to unref again when handled. */GST_LOG_OBJECT (pad, "Reffing and pushing event %p (%s) to %s:%s",data->event, GST_EVENT_TYPE_NAME (data->event), GST_DEBUG_PAD_NAME (pad));data->result |= gst_pad_push_event (pad, gst_event_ref (data->event));data->dispatched = TRUE;/* don't stop */return FALSE;
}

 注册的event_forward_func函明确就是,push事件到对应的pad.

/*** gst_pad_forward:* @pad: a #GstPad* @forward: (scope call): a #GstPadForwardFunction* @user_data: user data passed to @forward** Calls @forward for all internally linked pads of @pad. This function deals with* dynamically changing internal pads and will make sure that the @forward* function is only called once for each pad.** When @forward returns %TRUE, no further pads will be processed.** Returns: %TRUE if one of the dispatcher functions returned %TRUE.*/
gboolean
gst_pad_forward (GstPad * pad, GstPadForwardFunction forward,gpointer user_data)
{gboolean result = FALSE;GstIterator *iter;gboolean done = FALSE;GValue item = { 0, };GList *pushed_pads = NULL;iter = gst_pad_iterate_internal_links (pad);if (!iter)goto no_iter;while (!done) {switch (gst_iterator_next (iter, &item)) {case GST_ITERATOR_OK:{GstPad *intpad;intpad = g_value_get_object (&item);/* if already pushed, skip. FIXME, find something faster to tag pads */if (intpad == NULL || g_list_find (pushed_pads, intpad)) {g_value_reset (&item);break;}GST_LOG_OBJECT (pad, "calling forward function on pad %s:%s",GST_DEBUG_PAD_NAME (intpad));done = result = forward (intpad, user_data);pushed_pads = g_list_prepend (pushed_pads, intpad);g_value_reset (&item);break;}case GST_ITERATOR_RESYNC:/* We don't reset the result here because we don't push the event* again on pads that got the event already and because we need* to consider the result of the previous pushes */gst_iterator_resync (iter);break;case GST_ITERATOR_ERROR:GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");done = TRUE;break;case GST_ITERATOR_DONE:done = TRUE;break;}}g_value_unset (&item);gst_iterator_free (iter);g_list_free (pushed_pads);no_iter:return result;
}

顾名思义 Calls @forward for all internally linked pads of @pad,如何实现的呢?

关键流程:gst_pad_iterate_internal_links

/*** gst_pad_iterate_internal_links:* @pad: the GstPad to get the internal links of.** Gets an iterator for the pads to which the given pad is linked to inside* of the parent element.** Each #GstPad element yielded by the iterator will have its refcount increased,* so unref after use.** Free-function: gst_iterator_free** Returns: (transfer full) (nullable): a new #GstIterator of #GstPad*     or %NULL when the pad does not have an iterator function*     configured. Use gst_iterator_free() after usage.*/
GstIterator *
gst_pad_iterate_internal_links (GstPad * pad)
{GstIterator *res = NULL;GstObject *parent;g_return_val_if_fail (GST_IS_PAD (pad), NULL);GST_OBJECT_LOCK (pad);ACQUIRE_PARENT (pad, parent, no_parent);GST_OBJECT_UNLOCK (pad);if (GST_PAD_ITERINTLINKFUNC (pad))res = GST_PAD_ITERINTLINKFUNC (pad) (pad, parent);RELEASE_PARENT (parent);return res;/* ERRORS */
no_parent:{GST_DEBUG_OBJECT (pad, "no parent");GST_OBJECT_UNLOCK (pad);return NULL;}
}

也就是获取当前pad的内部linked的pad,这里可以看到是调用pad的GST_PAD_ITERINTLINKFUNC

函数。这个函数是可以被重写的,我们以multiqueue插件为例

  gst_pad_set_chain_function (sinkpad,GST_DEBUG_FUNCPTR (gst_multi_queue_chain));gst_pad_set_activatemode_function (sinkpad,GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));gst_pad_set_event_full_function (sinkpad,GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));gst_pad_set_query_function (sinkpad,GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));gst_pad_set_iterate_internal_links_function (sinkpad,GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); //设置了iterate_internal_links函数GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS);
gst_multi_queue_iterate_internal_links (GstPad * pad, GstObject * parent)
{GstIterator *it = NULL;GstPad *opad, *sinkpad, *srcpad;GstSingleQueue *squeue;GstMultiQueue *mq = GST_MULTI_QUEUE (parent);GValue val = { 0, };GST_MULTI_QUEUE_MUTEX_LOCK (mq);squeue = GST_MULTIQUEUE_PAD (pad)->sq;if (!squeue)goto out;srcpad = g_weak_ref_get (&squeue->srcpad);sinkpad = g_weak_ref_get (&squeue->sinkpad);if (sinkpad == pad && srcpad) {opad = srcpad;gst_clear_object (&sinkpad);} else if (srcpad == pad && sinkpad) {opad = sinkpad;gst_clear_object (&srcpad);} else {gst_clear_object (&srcpad);gst_clear_object (&sinkpad);goto out;}g_value_init (&val, GST_TYPE_PAD);g_value_set_object (&val, opad);it = gst_iterator_new_single (GST_TYPE_PAD, &val);g_value_unset (&val);gst_object_unref (opad);out:GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);return it;
}

可以知道如果参数sinkpad会返回对应的scrpad。反之亦然。 

那我们再看下默认函数gst_pad_iterate_internal_links_default

/*** gst_pad_iterate_internal_links_default:* @pad: the #GstPad to get the internal links of.* @parent: (allow-none): the parent of @pad or %NULL** Iterate the list of pads to which the given pad is linked to inside of* the parent element.* This is the default handler, and thus returns an iterator of all of the* pads inside the parent element with opposite direction.** The caller must free this iterator after use with gst_iterator_free().** Returns: (nullable): a #GstIterator of #GstPad, or %NULL if @pad* has no parent. Unref each returned pad with gst_object_unref().*/
GstIterator *
gst_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent)
{GstIterator *res;GList **padlist;guint32 *cookie;GMutex *lock;gpointer owner;GstElement *eparent;g_return_val_if_fail (GST_IS_PAD (pad), NULL);if (parent != NULL && GST_IS_ELEMENT (parent)) {eparent = GST_ELEMENT_CAST (gst_object_ref (parent));} else {GST_OBJECT_LOCK (pad);eparent = GST_PAD_PARENT (pad);if (!eparent || !GST_IS_ELEMENT (eparent))goto no_parent;gst_object_ref (eparent);GST_OBJECT_UNLOCK (pad);}if (pad->direction == GST_PAD_SRC)padlist = &eparent->sinkpads;elsepadlist = &eparent->srcpads;GST_DEBUG_OBJECT (pad, "Making iterator");cookie = &eparent->pads_cookie;owner = eparent;lock = GST_OBJECT_GET_LOCK (eparent);res = gst_iterator_new_list (GST_TYPE_PAD,lock, cookie, padlist, (GObject *) owner, NULL);gst_object_unref (owner);return res;/* ERRORS */
no_parent:{GST_OBJECT_UNLOCK (pad);GST_DEBUG_OBJECT (pad, "no parent element");return NULL;}
}

逻辑可以获取到该元件的padlist,这里就会出现一个问题。如果该元件有多个srcpad或者sinkpad

那么内部流动就会出现问题了?因为gst_pad_forward只要有一个push成功就会跳出循环了,

所以这种场景就需要我们自定义gst_pad_iterate_internal_links函数了

  if (pad->direction == GST_PAD_SRC)padlist = &eparent->sinkpads;elsepadlist = &eparent->srcpads;

=========================================================================

2.在看下gst_pad_query_default基本逻辑是一样的,注意下某些事件的forward条件限制。

/*** gst_pad_query_default:* @pad: a #GstPad to call the default query handler on.* @parent: (allow-none): the parent of @pad or %NULL* @query: (transfer none): the #GstQuery to handle.** Invokes the default query handler for the given pad.* The query is sent to all pads internally linked to @pad. Note that* if there are many possible sink pads that are internally linked to* @pad, only one will be sent the query.* Multi-sinkpad elements should implement custom query handlers.** Returns: %TRUE if the query was performed successfully.*/
gboolean
gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query)
{gboolean forward, ret = FALSE;switch (GST_QUERY_TYPE (query)) {case GST_QUERY_SCHEDULING:forward = GST_PAD_IS_PROXY_SCHEDULING (pad);break;case GST_QUERY_ALLOCATION:forward = GST_PAD_IS_PROXY_ALLOCATION (pad);break;case GST_QUERY_ACCEPT_CAPS:ret = gst_pad_query_accept_caps_default (pad, query);forward = FALSE;break;case GST_QUERY_CAPS:ret = gst_pad_query_caps_default (pad, query);forward = FALSE;break;case GST_QUERY_LATENCY:ret = gst_pad_query_latency_default (pad, query);forward = FALSE;break;case GST_QUERY_BITRATE:/* FIXME: better default handling */forward = TRUE;break;case GST_QUERY_POSITION:case GST_QUERY_SEEKING:case GST_QUERY_FORMATS:case GST_QUERY_JITTER:case GST_QUERY_RATE:case GST_QUERY_CONVERT:default:forward = TRUE;break;}GST_DEBUG_OBJECT (pad, "%sforwarding %p (%s) query", (forward ? "" : "not "),query, GST_QUERY_TYPE_NAME (query));if (forward) {QueryData data;data.query = query;data.dispatched = FALSE;data.result = FALSE;gst_pad_forward (pad, (GstPadForwardFunction) query_forward_func, &data);if (data.dispatched) {ret = data.result;} else {/* nothing dispatched, assume drained */if (GST_QUERY_TYPE (query) == GST_QUERY_DRAIN)ret = TRUE;elseret = FALSE;}}return ret;
}
static gboolean
query_forward_func (GstPad * pad, QueryData * data)
{GST_LOG_OBJECT (pad, "query peer %p (%s) of %s:%s",data->query, GST_QUERY_TYPE_NAME (data->query), GST_DEBUG_PAD_NAME (pad));data->result |= gst_pad_peer_query (pad, data->query);data->dispatched = TRUE;/* stop on first successful reply */return data->result;
}

整理:

1、GST_QUERY_SCHEDULING,条件forward = GST_PAD_IS_PROXY_SCHEDULING (pad);

2、GST_QUERY_ALLOCATION,条件GST_PAD_IS_PROXY_ALLOCATION (pad);

3、GST_QUERY_ACCEPT_CAPS、GST_QUERY_CAPS、GST_QUERY_LATENCY、

GST_QUERY_BITRATE 这些时间无法进行forward查询

4、其他无限制,默认是可以进行forward查询

http://www.xdnf.cn/news/736867.html

相关文章:

  • 2024PLM系统实施案例:天水天轲零部件
  • Sigma-Aldrich3D细胞培养支架有哪些类型?
  • LoRA:高效微调预训练模型的利器
  • DeepSeek-R1 重磅升级,智能体验再进化!
  • shell脚本的两种循环及状态返回值的区别及对比
  • 软件架构基础
  • ollama国内安装使用
  • 时间序列数据如何转化为动态图实践笔记
  • XSS跨站脚本攻击
  • 特伦斯 S75:重塑钢琴体验的数码钢琴之选
  • 基于教育数字化背景:人工智能技术支持下的教师专业发展路径
  • Baklib智能推荐赋能内容中台升级
  • 低频 500kHz vs 高频 1MHz,FP6291C与FP6291升压芯片应用在不同场景该怎么选择?
  • Spring生命周期中织入代理逻辑
  • 大模型-attention汇总解析之-MHA
  • 电工基础【2】自锁、互锁、正反转电路
  • leetcode动态规划—完全背包系列
  • 【论文阅读】DanceGRPO: Unleashing GRPO on Visual Generation
  • ✨1.1.1 按位与运算替代求余运算优化场景
  • 在 Android 上备份短信:保护您的对话
  • N2语法 状態
  • win7怎么关闭开机自启动程序?
  • 深入理解 MySQL 隔离级别:理论与实战
  • 百年陈韵,三代匠心——陈汇堂新会陈皮的传承与新生
  • linux 中路由解决方案1
  • Cross-Encoder(交叉编码器)和 Bi-Encoder(双编码器)
  • 页面表格、模型、脚本这三者之间的数据是如何传输的?尤其是模型(Model)到底是怎样的运作原理与数据流转?
  • 判断质数的基础方法
  • Maven高级篇
  • Selenium操作指南(全)