【QGroundControl二次开发】八. QT实现播放gstreamer视频

news2024/11/13 11:58:18

上篇写到如何搭建gstreamer在Windows和linux下的环境,以及新建VS工程解码视频流。gstreamer 配置+解析编解码
本篇主要讲述c++源码移植到QT工程。

一. QT工程配置

gstreamer环境参考上面链接。
在项目的.pro文件中加入如下代码。(以linux项目为例,Windows项目需要修改对应路径)

INCLUDEPATH += /usr/include/glib-2.0
INCLUDEPATH += /usr/lib/x86_64-linux-gnu/glib-2.0/include
INCLUDEPATH += /usr/include/gstreamer-1.0
INCLUDEPATH += /usr/lib/x86_64-linux-gnu/gstreamer-1.0/include

LIBS += -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0 -lgstvideo-1.0 -lgstapp-1.0 -lgstbase-1.0

二. 项目代码

2.1 项目结构如下图所示

在这里插入图片描述

2.2 代码

本项目为测试项目,下面为main.cpp代码,用来解析书树莓派发送的RTP视频流,别的代码为新建工程自动生成原样未动。

#include <QApplication>
#include <QWidget>
#include <QtConcurrent/QtConcurrent>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include "ui_mainwindow.h"

int main(int argc, char *argv[]) {

    QApplication a(argc, argv);

    GstElement *pipeline, *udpsrc, *capsfilter, *queue, *rtph264depay, *h264parse, *avdec_h264, *videoconvert, *vsink, *fpssink;
    GstCaps *caps;

    GstStateChangeReturn ret;

    QWidget *window = new QWidget();
    window->resize(1920, 1080);
    window->show();
    WId xwinid = window->winId();

    // 初始化 GStreamer
    gst_init(NULL, NULL);

    // 创建元素
    pipeline = gst_pipeline_new("my-pipeline");
    udpsrc = gst_element_factory_make("udpsrc", "udpsrc");
    capsfilter = gst_element_factory_make("capsfilter", "capsfilter");
    queue = gst_element_factory_make("queue", "queue");

    h264parse = gst_element_factory_make("h264parse", "h264parse");
    avdec_h264 = gst_element_factory_make("avdec_h264", "avdec_h264");
    rtph264depay = gst_element_factory_make("rtph264depay", "rtph264depay");
    videoconvert = gst_element_factory_make("videoconvert", "videoconvert");
    fpssink = gst_element_factory_make("fpsdisplaysink", "fpssink");
    vsink = gst_element_factory_make("xvimagesink", "vsink");//glimagesink

    if (!pipeline || !udpsrc || !capsfilter || !queue || !rtph264depay || !h264parse || !avdec_h264 || !videoconvert || !fpssink || !vsink)
    {
        g_printerr("Failed to create elements. Exiting.\n0000000");
        return -1;
    }

    // 设置 udpsrc 元素的参数
    g_object_set(udpsrc, "port", 14556, NULL);

    // 创建 caps    
    /*"depth", G_TYPE_STRING, "8",
       "width", G_TYPE_STRING, "1920",
    	"height", G_TYPE_STRING, "1080",*/
    caps = gst_caps_new_simple("application/x-rtp",
                               "media", G_TYPE_STRING, "video",
                               "clock-rate", G_TYPE_INT, 90000,
                               "encoding-name", G_TYPE_STRING, "H264",
                               NULL);
    g_object_set(capsfilter, "caps", caps, NULL);
    gst_caps_unref(caps);


    // 将元素添加到管道中
    gst_bin_add_many(GST_BIN(pipeline), udpsrc, capsfilter, queue, rtph264depay, h264parse, avdec_h264, videoconvert, vsink, NULL);

    // 连接元素
//    if (!gst_element_link_many(udpsrc, capsfilter, queue, rtph264depay, h264parse, avdec_h264, videoconvert, vsink, NULL)) {
//        g_printerr("Failed to link elements. Exiting.\n11111111111");
//        gst_object_unref(pipeline);
//        return -1;
//    }
    // 连接元素
    if (!gst_element_link(udpsrc, capsfilter)) {
        g_printerr("Failed to link udpsrc and capsfilter. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (!gst_element_link(capsfilter, queue)) {
        g_printerr("Failed to link capsfilter and queue. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (!gst_element_link(queue, rtph264depay)) {
        g_printerr("Failed to link queue and rtph264depay. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (!gst_element_link(rtph264depay, h264parse)) {
        g_printerr("Failed to link rtph264depay, h264parse. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (!gst_element_link(h264parse, avdec_h264)) {
        g_printerr("Failed to link qh264parse, avdec_h264. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (!gst_element_link(avdec_h264, videoconvert)) {
        g_printerr("Failed to link avdec_h264, videoconvert. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (!gst_element_link(videoconvert, vsink)) {
        g_printerr("Failed to link avideoconvert, vsink. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }


    // 链接QT界面
    gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (vsink), xwinid);

    // 设置管道状态为播放
    ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr("Failed to set pipeline state to PLAYING. Exiting.\n");
        gst_object_unref(pipeline);
        return -1;
    }


    auto res = a.exec();

    // 释放资源
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);

    return res;
}

三. 测试

配置无人机视频转发目标IP到本机,端口与上面代码中定义的一致。
运行程序:
在这里插入图片描述

四. 源码

下载本文源码


参考:
https://blog.csdn.net/Alon1787/article/details/135908723
https://blog.csdn.net/Alon1787/article/details/135107958

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1972891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python 逆向滑块】(实战四)逆向滑块,并实现用Python+Node.js 生成滑块、识别滑块、验证滑块、发送短信

逆向日期&#xff1a;2024.08.02 使用工具&#xff1a;python、Node.js 本章知识&#xff1a;逆向网易易盾【data】参数里的【d】【p】【f】【ext】参数 文章难度&#xff1a;中等&#xff08;没耐心的请离开&#xff09; 文章全程已做去敏处理&#xff01;&#xff01;&#x…

物理学是研究‘’物质一般的运动规律‘’和‘’物质基本结构‘’的自然科学

物理学是一门研究物质最一般的运动规律和物质基本结构的自然科学学科。作为自然科学的带头学科&#xff0c;物理学研究大至宇宙&#xff0c;小至基本粒子等一切物质最基本的运动形式和规律&#xff0c;因此成为其他各自然科学学科的研究基础。 以下是对物理学的详细解析&#x…

儿童安全门和围栏美国CPC认证ASTM F1004测试16CFR1239测试

什么是儿童安全门和围栏&#xff1f; ASTM F1004-22将“伸缩门”定义为“旨在安装在门口等开口处的障碍物&#xff0c;以防止儿童通过&#xff0c;但可以由能够操作锁定装置的老年人拆除”(第3.1.7节)。 ASTM F1004-22将“可扩展围栏”定义为“旨在完全包围幼儿可能被限制在其…

数据结构与算法--栈

文章目录 知识回顾顺序存储结构的优缺点链式存储结构的优缺点 数据结构的三个方面栈的定义与特点栈的基本运算栈的存储结构与实现顺序栈入栈操作出栈操作 链栈入栈操作入栈操作 栈的应用数制转换表达式求值中缀表达式向后缀表达式的转换后缀表达式的求值过程 总结 知识回顾 顺…

Telnet和SSH配置学习笔记

1. Telnet应用场景 为方便通过命令行管理设备&#xff0c;可以使用Telnet协议对设备进行管理。 Telnet协议与使用Console接口管理设备不同&#xff0c;无需专用线缆直连设备的Console接口&#xff0c;只要IP地址可达、能够和设备的TCP 23端口通信即可。 支持通过Telnet协议进…

Redis基础总结、持久化、主从复制、哨兵模式、内存淘汰策略、缓存

文章目录 Redis 基础Redis 是什么&#xff0c;有哪些特点为什么要使用 Redis 而不仅仅依赖 MySQLRedis 是单线程吗Redis 单线程为什么还这么快 Redis 数据类型和数据结构五种基本数据结构及应用场景其他数据类型Redis 底层数据结构 Redis 持久化数据不丢失的实现AOF 日志RDB 快…

如何理解复信号z的傅里叶变换在频率v<0的时候恒为0,是解析信号

考虑例子2.12.1的说法。 首先我尝试解释第二个说法。需要注意一个事实是 实函数f的傅里叶变换F的实部是偶函数&#xff0c;虚部是奇函数。如图所示&#xff1a; 注意的是这个图中虽然是离散傅里叶变换的性质&#xff0c;但是对于一般的傅里叶变换的性质是适用的。 推导过程如下…

Tecplot安装error找不到指定模块之解决方案

最近有小伙伴反应&#xff0c;在安装Tecplot 2023版本时&#xff0c;参考教程来操作很顺利&#xff0c;但是在开启软件后&#xff0c;有一个error弹窗&#xff0c;内容如下&#xff1a; 随后用中英文翻译&#xff1a;找不到指定模块 同时&#xff0c;软件内部的Tool工具栏打不…

液位传感器- 从零开始认识各种传感器【二十四期】

液位传感器|从零开始认识各种传感器 1、什么是液位传感器 &#xff1f; 液位传感器是一种用于检测和测量液体位置和高度的装置&#xff0c;广泛应用于工业、农业、环保和家庭等领域。液位传感器可以实时监测液体的水平&#xff0c;以实现自动化控制和安全防护。 2、液位传感器…

java之方法引用 —— ::

目录 一、简介 二、引用静态方法 1.格式 2.示例 ​编辑 3.条件解析 三、引用成员方法 1.格式 2.示例 四、引用构造方法 1.格式 2.示例 五、类名引用成员方法 1.格式 2.略微不同的方法引用规则 3.示例 六、引用数组的构造方法 1.格式 2.示例 一、简介 方…

C语言笔记39 •数据结构--栈队列-OJ•

栈&队列-OJ 1.给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; (1).左括号必须用相同类型的右括号闭合。 (2).左括号必须以正确的顺序闭合。 (3).每个右括…

MQ消息队列篇:三大MQ产品的必备面试种子题

MQ有什么用&#xff1f; MQ&#xff08;消息队列&#xff09;是一种FIFO&#xff08;先进先出&#xff09;的数据结构&#xff0c;主要用于实现异步通信、削峰平谷和解耦等功能。它通过将生产者生成的消息发送到队列中&#xff0c;然后由消费者进行消费。这样&#xff0c;生产…

【Kubernetes】k8s集群中kubectl的陈述式资源管理

目录 一.k8s集群资源管理方式分类 1.陈述式资源管理方式 2.声明式资源管理方式 二.陈述式资源管理方法 三.kubectl命令 四.项目生命周期 1.创建 kubectl create命令 2.发布 kubectl expose命令 3.更新 kubectl set 4.回滚 kubectl rollout 5.删除 k…

notes for datawhale summer camp chemistry task3

Transformer transformer的诞生 循环神经网络&#xff1a;由于所有的前文信息都蕴含在一个隐向量里面&#xff0c;这会导致随着序列长度的增加&#xff0c;编码在隐藏状态中的序列早期的上下文信息被逐渐遗忘。 卷积神经网络&#xff1a;受限的上下文窗口在建模长文本方面天…

木卫四发布《2024半年度汽车漏洞及威胁情报-简报》

随着智能汽车技术的飞速发展&#xff0c;其安全问题也日益成为行业关注的焦点。木卫四威胁情报中心对2024年上半年国内外智能汽车领域的漏洞情报及安全事件进行了全面研究和分析&#xff0c;发布了《2024半年度汽车漏洞及威胁情报-简报》。本报告中智能汽车威胁情报的来源多样&…

宏集方案 | 传统建筑智能化改造,迈向物联新时代

前言 智能建筑涉及多个系统的集成&#xff0c;如照明、空调、安防等&#xff0c;这些系统的兼容性和协调运作是一大挑战。然而&#xff0c;传统的工业建筑和商业楼宇受早期设计的局限&#xff0c;多个控制系统间互不兼容&#xff0c;并且难以重新部署通信线缆。 针对传统建筑…

Java:查看线程信息

示例用代码 public class Main {static class MyThread extends Thread {Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}public st…

【Canvas与艺术】九角大楼

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>九角大楼</title><style type"text/css">.cen…

“光影魔术手”:一款让照片编辑更高效的软件工具

&#x1f680;&#x1f680;&#x1f680; 摄影爱好者和技术控们&#xff0c;想要照片编辑技能更上一层楼吗&#xff1f;“光影魔术手”带你探索照片美化的高级技巧&#xff0c;这款软件不仅是工具&#xff0c;更是你的技术利器&#xff01; &#x1f308;【专业调色功能解析】…

AS400==使用COBOL写个HELLWORLD

登录后输入命令WRKOBJPDM 可以看到在我的lib下拥有的FILES列表 随便选一个&#xff0c;在OPT输入12回车打开这个FILE&#xff0c;最下面一排提示了&#xff0c;F6创建一个新的MEMBER输入这个FILE FILE相当于文件夹&#xff0c;MEMBER相当于一个代码文件test.py。 移动光标输入…