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

上篇写到如何搭建gstreamer在Windows和linux下的环境,以及新建VS工程解码视频流。gstreamer 配置+解析编解码

本篇主要讲述c++源码移植到QT工程。

一. QT工程配置

gstreamer环境参考上面链接。

在项目的.pro文件中加入如下代码。(以linux项目为例,Windows项目需要修改对应路径)

bash 复制代码
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视频流,别的代码为新建工程自动生成原样未动。

cpp 复制代码
#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

相关推荐
sali-tec32 分钟前
C# 基于halcon的视觉工作流-章32-线线测量
开发语言·人工智能·算法·计算机视觉·c#
little_xianzhong1 小时前
Java 日期字符串万能解析工具类(支持多种日期格式智能转换)
java·开发语言
Dersun1 小时前
python学习进阶之异常和文件操作(三)
开发语言·python·学习·json
我好喜欢你~1 小时前
C#---Expression(表达式)
开发语言·c#
Tiger_shl2 小时前
【.Net技术栈梳理】01-核心框架与运行时(CLR)
开发语言·.net
Tiger_shl2 小时前
【.Net技术栈梳理】02-核心框架与运行时(GC管理)
开发语言·.net
阿里matlab建模师2 小时前
【直流电机鲁棒控制】matlab实现H无穷大控制的直流电机鲁棒控制研究
开发语言·数学建模·matlab·全国大学生数学建模竞赛·美赛·科研项目
MediaTea2 小时前
Python 第三方库:SymPy(符号计算工具)
开发语言·python·数学建模
他们都不看好你,偏偏你最不争气2 小时前
【iOS】UIViewController
开发语言·macos·ios·objective-c·cocoa
Pocker_Spades_A2 小时前
Python快速入门专业版(二十二):if语句进阶:嵌套if与条件表达式(简洁写法技巧)
开发语言·python