Gstreamer从管道命令转为代码的注意事项

概述

gstreamer提供了gst-launch工具,使用该工具我们可以很方便的搭建各种管道,比如gst-launc-1.0 videotestsrc ! autovideosink输入上述命令,我们就能测试视频通路是否OK。但有些场景需要我们提供代码形式,而在gst-launch的管道转换为代码时,经常会遇到管道间连接失败的问题。本文主要总结gst元素不同pad类型间如何连接。

Always pad类型

以videotestsrc元素为例,该元素的Pad Templates类型为Always,该类型表示此gst元素一直存在pad,无需动态创建。同是这种类型的两个元素连接时,直接使用gst_element_linkgst_element_link_many进行连接即可。
在这里插入图片描述

Sometimes Pad类型

这种类型的pad我们以rtspsrc元素为例,如下是该元素的pad信息。这种类型的元素在连接时则不能直接使用gst_element_link等接口,而是需要用到该元素的pad-added的signal来实现。
在这里插入图片描述
比如管道命令:

gst-launch-1.0 rtspsrc location="rtsp://b1.dnsdojo.com:1935/live/sys3.stream"  ! rtph264depay ! video/x-h264, stream-format=avc ! h264parse ! avdec_h264  ! video/x-raw,formate=NV12,width=1280,height=720 ! videoconvert ! autovideosink

如果使用gst_element_link(rtspsrc, rtph264depay),则会连接失败。此时应该用rtspsrc元素的pad-added Signal处理函数通过Pad进行连接。

rtsp_source = gst_element_factory_make ("rtspsrc", "rtsp_source");
rtp_h264depay = gst_element_factory_make ("rtph264depay", "rtp_h264depay");
......
g_object_set (rtsp_source, "location", "rtsp://b1.dnsdojo.com:1935/live/sys3.stream", NULL);
......
g_signal_connect(rtsp_source, "pad-added", G_CALLBACK(cb_new_rtspsrc_pad), rtp_h264depay);

cb_new_rtspsrc_pad的实现如下两种方式均可行:
方式一:

static void cb_new_rtspsrc_pad(GstElement *element, GstPad *pad, gpointer data)
{
	gchar *name;
	GstCaps * p_caps;
	gchar * description;
	GstElement *p_rtph264depay;

	g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));

	name = gst_pad_get_name(pad);
	p_caps = gst_pad_get_pad_template_caps (pad);
	description = gst_caps_to_string(p_caps);
	g_print("%s\n", description);
	g_free(description);

	p_rtph264depay = GST_ELEMENT(data);

	// try to link the pads then ...
	if(!gst_element_link_pads(element, name, p_rtph264depay, "sink")) {
		g_print("Failed to link elements 3\n");
	}

	g_free(name);
}

方式二:

static void cb_new_rtspsrc_pad(GstElement *element, GstPad *pad, gpointer data)
{
	GstPad *sink_pad = gst_element_get_static_pad (GST_ELEMENT(data), "sink");
	GstPadLinkReturn ret;
	GstCaps *pad_caps = NULL;
	GstStructure *pad_caps_struct = NULL;
	const gchar *pad_caps_type = NULL;

	g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));

	/* 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;
	}

	/* Get the new pad's type */
	pad_caps = gst_pad_get_current_caps (pad);
	pad_caps_struct = gst_caps_get_structure (pad_caps, 0);
	pad_caps_type = gst_structure_get_name (pad_caps_struct);

	/* Attempt the link */
	ret = gst_pad_link (pad, sink_pad);
	if (GST_PAD_LINK_FAILED (ret)) {
		g_print ("Type is '%s' but link failed.\n", pad_caps_type);
	} else {
		g_print ("Link succeeded (type '%s').\n", pad_caps_type);
	}

exit:
	/* Unreference the new pad's caps, if we got them */
	if (pad_caps != NULL)
		gst_caps_unref (pad_caps);

	/* Unreference the sink pad */
	gst_object_unref (sink_pad);
}

Request Pad类型

典型的gst元素就是tee。获取元素的Request Pad接口为gst_element_get_request_pad,而获取Always Pad的接口为gst_element_get_static_pad。如下展示了tee元素与后端的两个queue元素的连接方法。

    tee = gst_element_factory_make ("tee", "tee");
	play_queue = gst_element_factory_make ("queue", "play_queue");
	file_queue = gst_element_factory_make ("queue", "file_queue");
    
	.........
   
    /* Manually link the Tee, which has "Request" pads */
	tee_play_pad = gst_element_get_request_pad (tee, "src_%u");
	g_print ("Obtained request pad %s for play branch.\n", gst_pad_get_name (tee_play_pad));
	queue_play_pad = gst_element_get_static_pad (play_queue, "sink");

	tee_file_pad = gst_element_get_request_pad (tee, "src_%u");
	g_print ("Obtained request pad %s for video branch.\n", gst_pad_get_name (tee_file_pad));
	queue_file_pad = gst_element_get_static_pad (file_queue, "sink");
	
	/* Begin to connect */
	if (gst_pad_link (tee_play_pad, queue_play_pad) != GST_PAD_LINK_OK ||
		gst_pad_link (tee_file_pad, queue_file_pad) != GST_PAD_LINK_OK) {
		g_printerr ("Tee could not be linked.\n");
		gst_object_unref (pipeline);
		return -1;
	}

在这里插入图片描述

Caps Filter 的创建

管道命令:gst-launch-1.0 rtspsrc location="rtsp://b1.dnsdojo.com:1935/live/sys3.stream" ! rtph264depay ! video/x-h264, stream-format=avc ! h264parse ! avdec_h264 ! video/x-raw,formate=NV12,width=1280,height=720 ! videoconvert ! autovideosink

上述管道命令中的video/x-h264, stream-format=avc是一个过滤器,该过滤器仅允许满足需求的数据通过。过滤器创建和连接的方法如下:

caps_h264_byte = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "avc", NULL);
	caps_video_format = gst_caps_new_simple("video/x-raw", "stream-format", G_TYPE_STRING,"NV12",
						"alignment", G_TYPE_STRING, "au",
						"width", G_TYPE_INT, 1280,
						"height", G_TYPE_INT, 720, NULL);

	if (!gst_element_link_filtered (rtp_h264depay, h264_parse, caps_h264_byte)) {
		g_warning ("Failed to link rtp_h264depay and h264_parse!");
	}

	if (!gst_element_link_filtered (play_queue, video_convert, caps_video_format)) {
		g_warning ("Failed to link play_queue and video_convert!");
	}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值