目录
GStreamer 是用来构建流媒体应用的开源多媒体框架(framework),其目标是要简化音/视频应用程序的开发,GStreamer的程序通过连接数字媒体处理的元素注入管道(pipeline)。每个元素是由一个插件提供 。 元素可组合为箱(bins),箱可以进一步聚合,从而形成架构图。GStreamer采用基于插件(plugin)和管道(pipeline)的体系结构,框架中的所有的功能模块都被实现成可以插拔的组件(component),能够很方便地安装到任意管道上。GStreamer使用插件架构并造就了大量的GStreamer的共享库。本文主要介绍GStreamer的编程与gst-launch工具使用。
1、创建管道
pipeline = gst_pipeline_new ("my_pipeline");
2、创建bin
bin = gst_bin_new ("my_bin");
3、创建元素
player = gst_element_factory_make ("oggvorbisplayer", "player");
4、设置元素属性
g_object_set (player, "location", "helloworld.ogg", NULL);
5、设置元素状态
gst_element_set_state (GST_ELEMENT (player), GST_STATE_PLAYING);
6、从管道获取总线
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
7、创建Glib主循环
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
8、箱柜bin添加元件,元件添加到管道中
gst_bin_add_many (GST_BIN (pipeline),
source, demuxer, decoder, conv, sink, NULL);
9、元件连接必须在把元件添加到管道后,并且只有同一bin下的元件才能link
gst_element_link (source, demuxer);
10、自定义元件属性
g_object_set (source, "pattern", 0, NULL);
11、查询流的位置或长度
(gst_element_query_position()
12、改变事件
seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, -1);
13、发送事件
gst_element_send_event (data->video_sink, seek_event);
14、在代码中动态设置debug等级
gst_debug_set_default_threshold(level) //控制全局(所有类别)的log等级
gst_debug_set_threshold_for_name(name, level) //控制某一个类别的log等级,如:xxx(“videodecoder”, 5)
gst_debug_set_threshold_from_string(list, reset)//和GST_DEBUG类似,也是支持同时设置多个元组的log信息,后面一个reset参数: TRUE:清除之前的log输出设置信息,FALSE:将设置信息添加到现有的log信息设置当中
如下是在imx8平台上使用GStreamer编程接口编写c程序实现拉取rtsp摄像头数据实现265硬件解码操作,具体代码如下所示:
#include <gst/gst.h>
#include <stdio.h>
typedef struct _CustomData {
GstElement *pipeline;
GstElement *appSrc;
GstElement *rtpDepay;
GstElement *rtph265Parse;
GstElement *vpuDecode;
GstElement *imxShowG2d;
GstElement *waySink;
GMainLoop *loop;
GstBus *bus;
} CustomData;
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("Stream Ends\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR: {
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
/* Dynamically link */
static void on_pad_added (GstElement *element, GstPad *pad, gpointer data)
{
GstPad *sinkpad;
GstPadLinkReturn ret;
GstElement *decoder = (GstElement *) data;
/* We can now link this pad with the rtsp-decoder sink pad */
g_print ("Dynamic pad created, linking source/demuxer\n");
sinkpad = gst_element_get_static_pad (decoder, "sink");
/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sinkpad)) {
g_print("*** We are already linked ***\n");
gst_object_unref (sinkpad);
return;
} else {
g_print("proceeding to linking ...\n");
}
ret = gst_pad_link (pad, sinkpad);
if (GST_PAD_LINK_FAILED (ret)) {
//failed
g_print("failed to link dynamically\n");
} else {
//pass
g_print("dynamically link successful\n");
}
gst_object_unref (sinkpad);
}
int main(int argc, char *argv[])
{
CustomData data;
gchar *urlVedio1 = "rtsp://admin:cx123456@192.168.60.67:554/cam/realmonitor?channel=1\&subtype=0\&unicast=true\&proto=Onvif";
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Create the empty pipeline */
data.pipeline = gst_pipeline_new ("decode_pipe");
if (!data.pipeline)
{
g_printerr ("pipeline created error.\n");
return -1;
}
/* Create the elements */
data.appSrc = gst_element_factory_make ("rtspsrc", "rtspsrc0");
data.rtpDepay = gst_element_factory_make ("rtph265depay", "rtph265depay0"); /* H265 */
data.rtph265Parse = gst_element_factory_make ("h265parse", "h265parse0");;
data.vpuDecode = gst_element_factory_make ("vpudec", "vpudec0");
data.imxShowG2d = gst_element_factory_make ("imxvideoconvert_g2d", "imxvideoconvert_g2d0");
//Video Sink
data.waySink = gst_element_factory_make ("waylandsink", "waylandsink0");
/* Make sure: Every elements was created ok */
if( !data.pipeline || !data.appSrc || !data.rtpDepay || !data.rtph265Parse || !data.vpuDecode || !data.imxShowG2d || !data.waySink )
{
g_printerr ("One of the elements wasn't created... Exiting\n");
return -1;
}
/* element属性设置 */
//g_object_set (G_OBJECT (data.waySink), "sync", FALSE, NULL);
g_object_set (data.appSrc, "location", urlVedio1,
"latency" , 300, NULL);
/* Add Elements to the Bin */
gst_bin_add_many (GST_BIN (data.pipeline), data.appSrc, data.rtpDepay, data.rtph265Parse, data.vpuDecode, data.imxShowG2d, data.waySink, NULL);
/* Link confirmation */
if (!gst_element_link_many (data.rtpDepay, data.rtph265Parse, data.vpuDecode, data.imxShowG2d, data.waySink, NULL))
{
g_warning ("Linking part (A)-1 Fail...");
return -1;
}
if(! g_signal_connect (data.appSrc, "pad-added", G_CALLBACK (on_pad_added), data.rtpDepay))
{
g_warning ("Linking part (1) with part (A)-1 Fail...");
}
data.loop = g_main_loop_new (NULL, FALSE);
data.bus = gst_pipeline_get_bus (GST_PIPELINE (data.pipeline));
gst_bus_add_watch (data.bus, bus_call, data.loop);
gst_object_unref (data.bus);
/* Run the pipeline */
gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
g_main_loop_run (data.loop);
/* Free resources */
g_main_loop_unref (data.loop);
gst_object_unref (data.bus);
gst_element_set_state (data.pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (data.pipeline));
}
编译命令如下所示,需添加`pkg-config --cflags --libs gstreamer-1.0`参数
$CC PlayCamera.c -o PlayCameraH265 `pkg-config --cflags --libs gstreamer-1.0`
以下命令均在NXP IMX8核心板上实现,不同的平台上gstreamer的插件略微有所不同,所以还是得根据具体的平台环境适配,以下仅供参考:
1、播放本地H265视频文件
gst-launch-1.0 filesrc location=/home/root/1080p_30fps_h265.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=1024, height=600 ! waylandsink
2、播放本地H264视频文件
gst-launch-1.0 filesrc location=H264_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=1024, height=600 ! waylandsink
3、测试源
gst-launch-1.0 videotestsrc ! video/x-raw,format=NV12 ! imxvideoconvert_g2d ! video/x-raw,format=RGB16 ! waylandsink
gst-launch-1.0 videotestsrc ! video/x-raw,format=NV12,width=1280,height=720 ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=640, height=480 ! waylandsink window-height=300 window-width=512
4、设置4视频同屏显示
gst-launch-1.0 imxcompositor_g2d name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=512 sink_0::height=300 sink_1::xpos=0 sink_1::ypos=300 sink_1::width=512 sink_1::height=300 sink_2::xpos=512 sink_2::ypos=0 sink_2::width=512 sink_2::height=300 sink_3::xpos=512 sink_3::ypos=300 sink_3::width=512 sink_3::height=300 ! video/x-raw,format=RGB16 ! waylandsink \
filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_0 \
filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_1 \
filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_2 \
filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_3
5、多视频显示
//一视频
gst-launch-1.0 imxcompositor_g2d name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=512 sink_0::height=300 sink_0::keep-ratio=true ! video/x-raw, format=RGB16, width=512, height=300 ! waylandsink filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! comp.sink_0
//两视频
gst-launch-1.0 imxcompositor_g2d name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=512 sink_0::height=300 sink_1::xpos=512 sink_1::ypos=0 sink_1::width=512 sink_1::height=300 ! video/x-raw,format=RGB16 ! waylandsink filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_0 filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_1
//三视频
gst-launch-1.0 imxcompositor_g2d name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=512 sink_0::height=300 sink_1::xpos=0 sink_1::ypos=300 sink_1::width=512 sink_1::height=300 sink_2::xpos=512 sink_2::ypos=0 sink_2::width=512 sink_2::height=300 ! video/x-raw,format=RGB16 ! waylandsink filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_0 filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_1 filesrc location=H265_1080.mp4 typefind=true ! video/quicktime ! aiurdemux ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_2
6、图片显示
//显示1图片
gst-launch-1.0 filesrc location=image.png ! pngdec ! imagefreeze ! videoconvert ! autovideosink
7、rtsp拉流播放
gst-launch-1.0 rtspsrc location=rtsp://admin:cx123456@192.168.60.64 latency=300 ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=1024, height=600 ! waylandsink
gst-launch-1.0 -v rtspsrc location=rtsp://admin:cx123456@192.168.60.67:554/cam/realmonitor?channel=1\&subtype=0\&unicast=true\&proto=Onvif ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=1024, height=600 ! waylandsink
8、playbin播放
// playbin播放
gst-launch-1.0 playbin uri=rtsp://admin:cx123456@192.168.60.64
gst-launch-1.0 playbin uri=rtsp://admin:cx123456@192.168.60.67/cam/realmonitor?channel=1\&subtype=0\&unicast=true\&proto=Onvif
gst-launch-1.0 playbin uri=rtsp://admin:cx123456@192.168.60.67:554/cam/realmonitor?channel=1\&subtype=1\&unicast=true\&proto=Onvif
gst-launch-1.0 rtspsrc location=rtsp://192.168.60.109///home/data/RECORD/hd00/part00/ch3/1233_01_03_20201118_1933.MP4 ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=1024, height=600 ! waylandsink
gst-launch-1.0 playbin uri=rtsp://192.168.60.109///home/data/RECORD/hd00/part00/ch3/1233_01_03_20201118_1933.MP4
gst-launch-1.0 playbin uri=rtsp://192.168.30.19:8554/test
// playbin播放本地文件
gst-launch-1.0 playbin uri=file:unit_tests/VPU/hantro/H264_1080.mp4
9、rtsp视频多窗体显示:
//视频多窗体显示:
gst-launch-1.0 imxcompositor_g2d name=comp
sink_0::xpos=0 sink_0::ypos=0 sink_0::width=512 sink_0::height=300
sink_1::xpos=0 sink_1::ypos=300 sink_1::width=512 sink_1::height=300
sink_2::xpos=512 sink_2::ypos=0 sink_2::width=512 sink_2::height=300
sink_3::xpos=512 sink_3::ypos=300 sink_3::width=512 sink_3::height=300
! video/x-raw,format=RGB16 ! waylandsink
rtspsrc location=rtsp://admin:cx123456@192.168.60.64 latency=300 ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_0
rtspsrc location=rtsp://admin:cx123456@192.168.60.64 latency=300 ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_1
rtspsrc location=rtsp://admin:cx123456@192.168.60.64 latency=300 ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_2
rtspsrc location=rtsp://admin:cx123456@192.168.60.64 latency=300 ! rtph264depay ! queue max-size-time=0 ! vpudec ! imxvideoconvert_g2d ! video/x-raw, format=RGB16, width=512, height=300 ! comp.sink_3
gstreamer其目标是要简化音/视频应用程序的开发,已经能够被用来处理像 MP3、Ogg、MPEG1、MPEG2、AVI、Quicktime 等多种格式的多媒体数据,方便开发者更容易使用。