gstreamer中tee如何实现动态增减支路(预览+截图+录像)

2023-11-18

系列文章目录

Gstreamer中获取帧数据的方式

gstreamer中如何使用probe(探针)获取帧数据
gstreamer拉流rtsp使用appsink获取帧数据(预览+截图)
gstreamer中如何使用fakesink获取帧数据(预览+截图)


前言

前面已经介绍过多种方式实现在显示预览的同时如何获取帧数据用来截图。本文就继续研究在此前的基础上利用tee如何实现可控的录像的支路。


Tee

Tee有一个 sink pad 而没有初始的 source pads:需要请求tee它们然后 添加它们。通过这种方式,输入流可以被复制任意次。缺点是使用 Request Pads 链接元素不像链接 Always Pads 那样自动连接。同时tee的支路阻塞会响应其他所有支路,导致整个管道阻塞。我们可以利用Request Pad特性就可以实现下游支路有需求时连接tee,不需要时可以断开tee。这样就可以实现控制单个支路的同时不影响其他支路。下面来看演示。

管道结构

  1. 录像前playing

  2. 开始录像(tee和录像支路连接)在这里插入图片描述

  3. 录像结束后(tee只断开录像支路)end-record
    这里演示的管道截图功能使用的是前面介绍的fakesink方式。几种方式截图都是可行的。使用fakesink和appsink会在tee后面多一条支路。而使用probe的方式可以在pipeline中我们想要的element位置任意选择。
    为了方便演示还是使用videotestsrc作为测试源。通过管道图能够看到开始录像后tee多了一条用来录像的支路。录像支路的连接和断开都不会影响其他支路。从管道图可以知道录像使用先编码再封装的方式保存为视频文件。gstreamer插件中提供了多种视频的编码方式。有h264、h265、vp8、vp9等等可供选择。下面介绍tee如何实现动态连接和断开。

qt程序界面

test
除了录制和截图功能外。还有可选择播放源的分辨率以及暂停和播放功能。录像按钮S_Record使用SIGNAL(toggled(bool))方式触发,开始和结束录制由同一个按钮的两种状态控制。为了避免意外,录制时关闭更改分辨率和暂停功能。

Tee的request方式连接和断开(录像)

代码如下(示例):

typedef struct _CustomData {
	GstElement *pipeline;
	 GstElement *vsrc, *capsfilter, *tee, *play_queue, *vconvert, *scale, *vsink ;
	 GstElement r*record_queue, *h264enc, *recordcapsfilte *h264parse, *qtmux, *filesink;
	 GstElement *fake_queue, *fconvert, *fakecapsfilter, *fsink;
	
	 GstPad *tee_record_pad;
	 GstPad *queue_record_pad;
	 GstPad *fsink_pad;
	 GstCaps *filter_caps,*filter_caps2;
	 GstCaps *x264enc_caps;
	
	 GstMapInfo  map_info;
	 int Width = 640, Height = 480;
	
	 // 截图和录像标志
	 bool capture_flag = false;
	 bool record_flag = false;
} CustomData;	

//下面用的相关变量都在结构体里创建
CustomData *date;

void PlayerWindow::onRecordClicked(bool checked) {	//这里使用qt中的按键slots函数

    if(checked){
		.........................................................
		.........................................................
		.........................................................
		
		//这里只列出关键代码  完整代码可见qt工程链接
		
		//先将支路element放入bin中
        gst_bin_add_many(GST_BIN (date->pipeline), date->record_queue, date->h264enc, date->recordcapsfilter,
                         date->h264parse, date->qtmux, date->filesink, NULL);

        gst_element_sync_state_with_parent(date->record_queue);
		
		// link element
        if(gst_element_link_many(date->record_queue, date->h264enc, date->recordcapsfilter,
                            date->h264parse, date->qtmux, date->filesink, NULL) != TRUE){
            g_printerr ("Elements could not be linked.\n");
            gst_object_unref (date->pipeline);
              return ;
        }
		
		//这里是关键
        date->tee_record_pad = gst_element_get_request_pad (date->tee, "src_%u");
        g_print ("Obtained request pad %s for capture branch.\n", gst_pad_get_name (date->tee_record_pad));
        date->queue_record_pad = gst_element_get_static_pad (date->record_queue, "sink");

        if(gst_pad_link (date->tee_record_pad, date->queue_record_pad) != GST_PAD_LINK_OK){
            g_printerr ("Tee capture could not be linked.\n");
            gst_object_unref (date->pipeline);
            return ;
        }
        gst_object_unref (date->queue_record_pad);
        g_print ("start record \n");
        date->record_flag = true;

        gst_element_set_state (date->pipeline, GST_STATE_PLAYING);
    }else{
        //stop record
        .........................................................
		.........................................................
		.........................................................		
		//这里只列出关键代码  完整代码可见qt工程链接


        // 发送eos通知支路的qtmux视频封装结束 。异常结束会导致视频文件没有结尾导致文件不能正常播放
        if(FALSE == gst_element_send_event(date->qtmux, gst_event_new_eos()))
        {
            g_print("send eos fail\n");
        }		
		//要结束录像则先断开(tee的srcpad)与录像支路的(queue的sinkpad)连接
        date->queue_record_pad = gst_element_get_static_pad (date->record_queue, "sink");
        if(gst_pad_unlink(date->tee_record_pad, date->queue_record_pad) != TRUE){
            g_printerr ("Tee capture could not be unlinked.\n");
            gst_object_unref (date->pipeline);
            return ;
        }
        gst_object_unref (date->queue_record_pad);
        
        gst_element_release_request_pad (date->tee, date->tee_record_pad);
        gst_object_unref (date->tee_record_pad);	//销毁teepad



        .........................................................
		.........................................................
		.........................................................		
		//这里只列出关键代码  完整代码可见qt工程链接

    }

}

总结

通过tee机制的学习和了解后,不仅仅只是实现可控录像的功能。在其他媒体流中能用到它的地方有很多。比如前面说到的显示的同时tee一条支路appsink来将数据写入文件。或者播放音乐和连接可视化模块。那了解tee如何动态连接后我们就能做更多灵活的处理。

附 ubuntu20.04 qt5.14 工程链接

gstreamer+qt实现照相机功能(显示预览+可控录像+拍照截图)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gstreamer中tee如何实现动态增减支路(预览+截图+录像) 的相关文章

  • 来自无符号字符缓冲区的 QImage(jpg 格式)

    我有类型的缓冲区unsigned char 我用JPG图像填充 我想使用此缓冲区将图像绘制到 QLabel 中的应用程序屏幕上 我已经这样做了 但图像不正确 谁能告诉我最好的方法是什么 QPixmap pix QPixmap fromIma
  • 学习 GObject 和 Glib 的材料 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我对 C 很满意 但需要学习GObject and Glib for gstreamer 我在网上找到
  • 如何管理返回到 QML 的动态分配的 QObject 的生命周期?

    我有这个代码 QVariant componentFromCode QString code QQmlComponent component new QQmlComponent engine engine gt setObjectOwner
  • QT“找不到 Qt 平台插件“xcb””

    我出于学术原因安装了QT everywhere 5 15开源版 但无法运行程序 首先 我编译了必要的源文件make并安装了QT Creator 然后我选择qmake来运行其中的程序 当我尝试运行示例程序时 遇到以下错误 qt qpa plu
  • 关于 GUI 计时器显示后台线程已用时间的建议?

    Issue 我有一个 PyQt GUI 用户按下按钮即可启动后台线程 workerThread 它是从QThread 我想要一个计时器显示 以QLabel 显示自此以来已经过去了多少时间workerThread开始 我希望这个计时器在wor
  • 如何设置 Xcode 来代替 Qt Creator 工作?

    我不使用 Qt Creator 的 UI 设计功能 对于一个新项目 我想体验一下使用 Xcode 的工作 这将是一个常规的 Qt 项目 使用 C 和 Qt 库开发 就像在 Qt Creator 中一样 我没有使用 OS X 尤其是 Xcod
  • Qt 远程文件浏览器

    我想知道是否有人使用过 Qt 远程文件浏览器 根据我的理解 我有两个选择 当涉及到远程文件时 将 QFileDilaog 与自定义代理模型结合使用 该模型将负责提供远程文件 目录结构 使用自定义对话框 并为本地文件提供标准文件系统模型 为远
  • 将项目添加到自定义组件的布局

    我有一个习惯Footer Component我想在 QML 应用程序的不同位置重用它 Rectangle color gold height 50 anchors bottom parent bottom left parent left
  • 通过对 XmlHttpRequest (REST) 的响应在 QML 中显示图像

    我需要从 REST API 调用中获取 jpeg 图像 我使用 XMLHttpRequest 因为请求需要身份验证标头 即我不能只创建一个图像并将源设置为带有 user passwd url 的 URL 我认为我可以通过将 REST 数据设
  • 获取小部件的背景颜色 - 真的

    我无法获取小部件的实际背景颜色 在我的特殊情况下 我在使用 QTabWidget 中的小部件时遇到问题 这是在Windows7上 因此 经典的小部件有一些灰色背景 而选项卡内的小部件通常用白色背景绘制 I tried def bgcolor
  • QT 中的应用程序->处理消息?

    在 Borland 6 中 我经常使用它来解除程序操作的卡住 Application gt Processmessages 现在 对于 QT 4 8 1 我在这个外国 对我来说 QT 文档中找不到 谁能帮我 在 Qt 中 您可以使用静态函数
  • 如何获取 QIcon 的文件/资源​​路径

    假设我做了这样的事情 QIcon myIcon resources icon ico 我稍后如何确定该图标的路径 例如 QString path myIcon getPath 问题是 没有getPath 会员 我找不到类似的东西 但肯定有办
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • 当 QML 对象不可见时防止 QML 属性绑定?

    我正在开发一个具有大量属性绑定的 QML 应用程序 数百个对象被跟踪并以不同的形式显示 例如 Qt3D QCanvas 当我在应用程序的单独页面上时 x y 位置和相对大小的属性绑定仍在发生 我怎样才能阻止他们 我知道我可以根据属性是否可视
  • Qt/c++ 随机字符串生成[重复]

    这个问题在这里已经有答案了 我正在创建一个应用程序 需要生成多个随机字符串 几乎就像一个由一定长度的 ASCII 字符组成的唯一 ID 这些字符混合有大写 小写 数字字符 有没有 Qt 库可以实现这一点 如果没有 在纯 C 中生成多个随机字
  • 如何创建QWidget的屏幕截图?

    我在 Qt Creator 中做作业 在其中绘制 QWidget 并且需要保存此 QWdiget 的某些部分 我试图解决这个问题 QPixmap pixmap pixmap copy rectangle rectangle is part
  • QT/QML Android App,点击通知栏时打开应用程序

    我为 Android 应用程序制作了一个 QT 当我单击平板电脑中上面看到的按钮通知栏时 但是 如果单击通知 我的应用程序将打开 聚焦 不知道 并显示黑色窗口 简单来说怎么做呢 我的代码是 package org ays operation
  • (如何)我可以抑制未找到包配置文件的警告吗?

    我正在尝试创建一个CMakeLists txt尝试查找的文件Qt5 如果失败 则尝试回退到Qt4安装 该脚本到目前为止有效 但如果出现以下情况我总会收到警告Qt5未安装 注意FindQt5 cmake是由提供Qt5并且仅当以下情况时才可用Q
  • Qt中如何获取鼠标在屏幕上的位置?

    我想获取屏幕上的鼠标坐标 我怎样才能在 Qt 中做到这一点 在 Windows 上 使用 C 我正在做类似答案中建议的事情对于这个问题 https stackoverflow com q 11737665 1420197 正如文档所述 QC
  • 如何在带有预编译头的项目中使用google protobuf

    我有一个包含多个项目的解决方案 我的项目 但不是全部 使用预编译头 我决定使用 protobuf 但遇到了一个问题 在 protoc exe 从 proto 生成 pb h 后 我尝试包含标头并收到错误 预编译标头未包含在 pb h 中 我

随机推荐

  • 在react项目中,使用craco插件进行mobx配置解决方案

    在使用react项目中 不可避免的要使用蚂蚁金服出品的ant desgin前端UI组件 ant desgin推荐使用 craco 一个对 create react app 进行自定义配置的社区解决方案 对 create react app
  • 一台服务器如何部署多个tomcat和项目(最详细的图文教程!!!)

    前言 提示 部署多个项目的方法有很多种 本文记载的是在Windows下 安装多个tomcat通过修改端口来部署项目 Linux部署方式大同小异 第一步 解压tomcat安装包后 复制一份并且重命名 多个tomcat就多复制一份 没有tomc
  • 【测试开花】五、项目管理-前端-实现查询、新增功能

    基于 springboot vue 的测试平台开发继续更新 一 查询功能 在之前的项目列表接口里 支持使用项目名称模糊查询 现在来实现前端 1 input 输入框 到组件库里找个输入框 复制代码 修改代码 v model 绑定了下面 dat
  • 服务器架构的演进

    服务器端的架构随着公司以及业务的发展 它不断演进 其演进的过程如下 https www cnblogs com joelan0927 p 10425530 html https blog csdn net daogla article de
  • 【数电】如何通俗地理解锁存器和触发器

    目录 一 相关知识 1 三极管和MOS管 2 TTL电路和CMOS电路 3 门电路 4 双稳态电路 二 锁存器 触发器 1 锁存器 2 触发器 1 电平触发的SR触发器 2 电平触发的D触发器 3 边沿触发的D触发器 4 脉冲触发的SR触发
  • java环境搭建图解_Windows7下的Java运行环境搭建过程图解

    单击 Java Download 按钮 选中 Accept License Agreement 单选按钮 我们以Windows 64位操作系统为例 下载Windows X64版的jdk 单击 jdk 8u5 windows x64 exe
  • vue-video-player 一款vue的前端视频播放插件 支持m3u8

    项目进行时 对视频模块需要进行组件开发 结合当前使用的开发框架是vuecli 于是寻找到vue video player 根据github上的文档进行开发 发现并不能实现播放功能 于是在网站上进行寻找发现 vue video player依
  • 3.爬虫之Scrapy框架的安装与使用

    1 Scrapy框架 1 1 介绍 Scrapy是一个开源和协作框架 可以用于数据挖掘 监测 自动化测试 获取API所有返回的数据或网络爬虫 Scrapy是基于twisted框架开发的 twisted是一个流行的事件驱动的python网络框
  • 不用导入animate库,也能实现animate的动画

    1 基础公共代码 animated animation duration 8s 持续时间 animation fill mode both 2 在animate官网 Animate css A cross browser library o
  • Django快速开发(精简版)

    1 使用虚拟环境 workon 虚拟环境名 2 退出虚拟环境 deactivate dajngo框架开发的大体流程 1 创建环境 mkvirtualenv 虚拟环境名 删除 rmvirtualenv 虚拟环境名 virtualenv p u
  • SMTP发送邮件

    SMTP是发送邮件的协议 Python内置对SMTP的支持 可以发送纯文本邮件 HTML邮件以及带附件的邮件 Python对SMTP支持有smtplib和email两个模块 email负责构造邮件 smtplib负责发送邮件 首先 我们来构
  • vue +C# mvc 坑

    1 把input标签放入到form表单中后 再将input中的值新增到数据库后 界面会刷新 解决 删除form 标签 原因待查
  • win11 安装opencv-python

    首先下载python3 7以上版本 installer版本 选择安装pip 添加环境 cmd 打开终端 pip install i https pypi tuna tsinghua edu cn simple opencv python p
  • List集合给另一个List集合赋值问题(即浅拷贝与深拷贝)

    问题 java中将一个list的内容复制给另一个list之后 去新的list进行操作的时候 原来的list也会发生变化 解决方案 直接采用 进行的复制属于浅层赋值 两者指向的使用一个地址 所以操作一个时另一个也会发生变化 如果不想出现这样的
  • 搜索插入位置 JavaScript

    在有序数组中查找 无则插入 元素 返回索引 题目详情 https leetcode cn com problems search insert position description 遍历数组查找 插入 查找比较简单 插入时会麻烦一些 如
  • Java中的String用法

    新手Java程序员了解String类型 1 String是什么数据类型 String在定义上是java lang包下的一个类 它不是基本的数据类型 String是不可变的 JVM使用字符串池来存储所有的字符串对象 2 创建String对象的
  • 阅读书源最新2020在线导入_最最最最最好用的小说神器,全网书源免费用!

    今天给大家分享的是小说软件 为了满足所有小伙伴的需求 今天安卓和苹果都安排上了 一款Android应用 一款iOS应用 两款应用都十分相似 都是可以自行添加书源的软件 几乎覆盖全网小说 阅读 Android 软件本身是没有任何资源的 如果不
  • elasticsearch心得体会

    1 聚合搜索的字段如果是求和的情况下 字段不能为string类型 那么排序时字段要求是不是也一样呢
  • Qt中带token的Http请求

    详细代码 get请求 QTimer timer timer setInterval 5000 设置超时时间 timer setSingleShot true 单次触发 if m pGetManager delete m pGetManage
  • gstreamer中tee如何实现动态增减支路(预览+截图+录像)

    系列文章目录 Gstreamer中获取帧数据的方式 gstreamer中如何使用probe 探针 获取帧数据 gstreamer拉流rtsp使用appsink获取帧数据 预览 截图 gstreamer中如何使用fakesink获取帧数据 预