gstreamer中如何使用fakesink获取帧数据(预览+截图)

系列文章

Gstreamer中获取帧数据的方式
gstreamer中如何使用probe(探针)获取帧数据
gstreamer拉流rtsp使用appsink获取帧数据(预览+截图)
gstreamer中如何使用fakesink获取帧数据(预览+截图)
gstreamer中tee如何实现可控连接(预览+截图+录像)




前言

前面已经介绍了两种在gstreamer实际使用中获取帧数据的例子probe和appsink。本文主要讲用fakesink的方式获取帧数据


fakesink介绍

简单来说fakesink会吞下任何馈送它的数据。在调试时很有用,可以替换您的普通接收器并将它们排除在等式之外。官网有更详细的介绍
当上游的element和fakesink 元素协商大小时,它会收到一个 NULL 缓冲池,因为 fakesink 不提供缓冲池。然后它会选择自己的自定义缓冲池来开始数据传输。利用fakesink不提供缓冲池,将它放放入管道中tee一个支路专门用来获取少量我们想要的帧数据。也算是避免浪费性能。

管道结构

还是先直接上本次演示示例的管道结构图
在这里插入图片描述
此次管道是使用tee的方式videotestsrc(gstreamer的视频测试源)流分为两路,一路为显示预览,一路为fakesink用来获取帧数据并保存图片。为了演示使用的是videotestsrc。当然也可以将source用摄像头(linux下为v4l2src)或者其他网络流rtmp,rtsp来代替,都是一样的效果。

fakesink定义

代码如下(示例):

	
	GstElementf *akesink = gst_element_factory_make ("fakesink", "fsink");
	g_object_set(date.fsink, "signal-handoffs", TRUE, NULL); //信号开启
	
	/* state-error 设置
	none( 0 ) – 没有状态改变错误
	null-to-ready( 1 ) – 失败状态从 NULL 变为 READY
	ready-to-paused( 2 ) – 失败状态从 READY 变为 PAUSED
	paused-to-playing( 3 ) – 失败状态从暂停变为播放
	playing-to-paused( 4 ) – 失败状态从 PLAYING 变为 PAUSED
	paused-to-ready( 5 ) – 故障状态从暂停变为就绪
	ready-to-null( 6 ) – Fail 状态从 READY 变为 NULL
	
	因为实际使用中应该想要获取实时帧数据 所以选4   */ 
	g_object_set(date.fsink, "state-error", 4, NULL);
	
	gulong uret = g_signal_connect(G_OBJECT(fakesink), "handoff", G_CALLBACK(fakesink_handoff_handler), gpointer user_data);
	if (0 == uret) {
	    g_printerr("Error connect signal handoff! \n");
	    return -1;
	}

fakesink回调函数

回调中获取帧数据的方式和appsink有些类似。代码如下(示例):

static void
fakesink_handoff_handler(GstElement *object,
                         GstBuffer *buffer,
                         GstPad *pad,
                         CustomData * date) {	//这里data是一个全局变量的结构体 主要将所要用到的相关变量都放在里面
    if (true == date->capture_flag) {	//这里是qwidget中按键触发采集开始标志       
      
        GstSample *sample = nullptr;
        GstStructure *s;
        gint width, height;	//图片的尺寸
        
        GstCaps *videosink_caps =gst_pad_get_current_caps(pad);
        s = gst_caps_get_structure (videosink_caps, 0);
        
        if(s){
            gboolean res;
            res = gst_structure_get_int (s, "width", &width);		//获取图片的宽
            res |= gst_structure_get_int (s, "height", &height);	//获取图片的高
            if (!res) {
                g_print ("gst_structure_get_int fail\n");
                return ;
            }
            if(!buffer){
                g_print ("gst_sample_get_buffer fail\n");
                gst_sample_unref (sample);
                return ;
            }
 		// 使用mapinfo获取图像数据
            GstMapInfo map;
            if (gst_buffer_map (buffer, &map, GST_MAP_READ)){		//把buffer映射到map,这样我们就可以通过map.data取到buffer的数据            

                g_print("jpg size = %ld \n", map.size);

                QImage img(map.data, width, height, width * 3, QImage::Format_RGB888);

                QString strFile = QString("Capture-%0.jpg").arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmssz"));
                img.save(strFile, "jpg");
                g_print("save  %s succese\n",strFile.toStdString().c_str());

                gst_buffer_unmap (buffer, &map);	//解除映射
            }
            date->capture_flag = false;		//停止采集
            GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(date->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "capture");
            return ;
        }
        return ;
    }
    return ;
}

还是和前面一样用Qimage来保存图片。


总结

当然获取帧数据方式还有很多。在使用中只需要选和所我们创建的管道结构相适应的一种方式就行。暂时就先介绍这几种方式,后面将此基础上介绍如何实现可控的录像。


附 linux qt 工程链接

gstreamer中如何使用fakesink获取帧数据(预览+截图)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

此心安处是吾鄕

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值