当前位置: 首页 > 工具软件 > GStreamer > 使用案例 >

GStreamer学习笔记

乜元魁
2023-12-01

目录

前言

一、GStreamer编程接口介绍

二、gst-launch-1.0工具使用

总结

前言

GStreamer 是用来构建流媒体应用的开源多媒体框架(framework),其目标是要简化音/视频应用程序的开发,GStreamer的程序通过连接数字媒体处理的元素注入管道(pipeline)。每个元素是由一个插件提供 。 元素可组合为箱(bins),箱可以进一步聚合,从而形成架构图。GStreamer采用基于插件(plugin)和管道(pipeline)的体系结构,框架中的所有的功能模块都被实现成可以插拔的组件(component),能够很方便地安装到任意管道上。GStreamer使用插件架构并造就了大量的GStreamer的共享库。本文主要介绍GStreamer的编程与gst-launch工具使用。

一、GStreamer编程接口介绍

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`

二、gst-launch-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 等多种格式的多媒体数据,方便开发者更容易使用。

 类似资料: