添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

qt中如何不打开文件 不用url 直接接收udp发过来的码流 然后送到ffmpeg解码并且通过ui文件中的QOpenGLWidget播放视频完整代码

以下是一个简单的示例代码,演示如何使用Qt接收UDP数据流并将其发送到FFmpeg进行解码,然后在QOpenGLWidget中播放视频。

main.cpp

#include "udpstreamreceiver.h"
#include "videoplayer.h"
#include <QApplication>
#include <QObject>
int main(int argc, char *argv[])
    QApplication a(argc, argv);
    // 创建UDP数据流接收器
    UdpStreamReceiver receiver;
    // 创建视频播放器
    VideoPlayer player;
    // 将接收器的信号连接到播放器槽函数
    QObject::connect(&receiver, &UdpStreamReceiver::receivedData,
                     &player, &VideoPlayer::processVideoData);
    player.show();
    return a.exec();

udpstreamreceiver.h

#ifndef UDPSTREAMRECEIVER_H
#define UDPSTREAMRECEIVER_H
#include <QUdpSocket>
class UdpStreamReceiver : public QObject
    Q_OBJECT
public:
    explicit UdpStreamReceiver(QObject *parent = nullptr);
signals:
    void receivedData(const QByteArray& data);
private slots:
    void readPendingDatagrams();
private:
    QUdpSocket m_udpSocket;
#endif // UDPSTREAMRECEIVER_H

udpstreamreceiver.cpp

#include "udpstreamreceiver.h"
UdpStreamReceiver::UdpStreamReceiver(QObject *parent) : QObject(parent)
    // 绑定端口,开始监听UDP数据包
    m_udpSocket.bind(12345);
    connect(&m_udpSocket, &QUdpSocket::readyRead,
            this, &UdpStreamReceiver::readPendingDatagrams);
void UdpStreamReceiver::readPendingDatagrams()
     while (m_udpSocket.hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(m_udpSocket.pendingDatagramSize());
        m_udpSocket.readDatagram(datagram.data(), datagram.size());
        // 发送收到的数据
        emit receivedData(datagram);

videoplayer.h

#ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
extern "C" {
#include <libavcodec/avcodec.h>
class VideoPlayer : public QOpenGLWidget, protected QOpenGLFunctions
    Q_OBJECT
public:
    explicit VideoPlayer(QWidget *parent = nullptr);
    void processVideoData(const QByteArray& data);
protected:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;
private:
    AVCodec* m_codec = nullptr;
    AVCodecContext* m_codecCtx = nullptr;
    AVFrame* m_frame = nullptr;
    uint8_t* m_frameBuffer = nullptr;
    QOpenGLShaderProgram m_shaderProg;
#endif // VIDEOPLAYER_H

videoplayer.cpp

#include "videoplayer.h"
VideoPlayer::VideoPlayer(QWidget *parent)
   : QOpenGLWidget(parent)
void VideoPlayer::processVideoData(const QByteArray &data)
     // 初始化FFmpeg解码器,只在第一帧数据接收时执行一次。
     if (!m_codec) {
        av_register_all();
        avcodec_register_all();
        m_codec = avcodec_find_decoder(AV_CODEC_ID_H264);
        if (!m_codec) {
            qCritical() << "Failed to find decoder for H264 codec";
            return;
        m_codecCtx = avcodec_alloc_context3(m_codec);
        if (avcodec_open2(m_codecCtx, m_codec, nullptr) < 0) {
            qCritical() << "Failed to open codec";
            return;
        m_frame = av_frame_alloc();
        if (!m_frame) {
            qCritical() << "Failed to allocate frame";
            return;
        // 为解码后的图像分配内存
        int numBytes = av_image_get_buffer_size(
                            AV_PIX_FMT_RGB24,
                            m_codecCtx->width,
                            m_codecCtx->height,
        m_frameBuffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
        av_image_fill_arrays(
                    m_frame->data,
                    m_frame->linesize,
                    m_frameBuffer,
                    AV_PIX_FMT_RGB24,
                    m_codecCtx->width,
                    m_codecCtx->height,
    // 解码数据
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = (uint8_t*)data.data();
    packet.size = data.size();
    int ret = avcodec_send_packet(m_codecCtx, &packet);
    if (ret < 0) {
        qCritical() << "Error sending a packet for decoding";
        return;
     while (ret >= 0) {
         ret = avcodec_receive_frame(m_codecCtx, m_frame);
         if (ret == AVERROR(EAGAIN)) {
             break;
         } else if (ret < 0) {
             qCritical() << "Error during decoding";
             break;
         update(); // 触发paintGL函数
void VideoPlayer::initializeGL()
   initializeOpenGLFunctions();
   glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
   // 设置顶点着色器和片段着色器
   m_shaderProg.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vertex.glsl");
   m_shaderProg.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fragment.glsl");
   m_shaderProg.link();
void VideoPlayer::resizeGL(int w, int h)
    glViewport(0, 0, w, h);
void VideoPlayer::paintGL()
    // 清空屏幕
    glClear(GL_COLOR_BUFFER_BIT);
    if (!m_frame) {
        return;
    // 将YUV数据转换为RGB24格式
    struct SwsContext* swsCtx = sws_getContext(
                m_codecCtx->width,
                m_codecCtx->height,
                m_codecCtx->pix_fmt,
                m_codecCtx->width,
                m_codecCtx->height,
                AV_PIX_FMT_RGB24,
                SWS_BILINEAR,
                nullptr, nullptr, nullptr);
    sws_scale(
            swsCtx,
            (const uint8_t* const*)m_frame->data,
            m_frame->linesize,
            m_codecCtx->height,
            (uint8_t* const*)m_frameBuffer,
            (const int*)&m_frame->linesize[0]);
    // 绘制图像
    QImage img(m_frameBuffer, m_codecCtx->width, m_codecCtx->height, QImage::Format_RGB888);
    img = img.rgbSwapped(); // 需要颜色翻转
    QPainter painter(this);
    painter.drawImage(rect(), img);

其中,还需要在Qt的.pro文件中添加以下内容:

QT += opengl widgets
SOURCES += \
    main.cpp \
    udpstreamreceiver.cpp \
    videoplayer.cpp
HEADERS += \
    udpstreamreceiver.h \
    videoplayer.h
RESOURCES += \
    shaders.qrc

并在项目根目录下创建一个shaders.qrc文件,用于将顶点着色器和片段着色器嵌入到应用程序中:

<!DOCTYPE RCC>
<RCC version="1.0">
  <qresource>
    <file>shaders/vertex.glsl</file>
    <file>shaders/fragment.glsl</file>
  </qresource>

最后,需要编写两个GLSL文件(vertex.glsl和fragment.glsl),用于设置顶点着色器和片段着色器。这里我们简单地使用红蓝相间的效果:

vertex.glsl

#version 330 core
layout (location = 0) in vec3 aPos;
void main()
   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);

fragment.glsl

#version 330 core
out vec4 FragColor;
void main()
   if ((int(gl_FragCoord.x) + int(gl_FragCoord.y)) % 2 == 0)
       FragColor = vec4(1.0f, 0.5f, 0.5f, 1.0f);
       FragColor = vec4(0.5f, 0.5f, 1.0f, 1.0f);

以上就是一个简单的使用Qt接收UDP数据流并在QOpenGLWidget中播放视频的示例。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://qt.0voice.com/?id=2403

Std_ReturnType Dem_SetEventStatusWithEnvData (Dem_EventIdType EventId, Dem_EventStatusType EventStatus, Dem_DebugDataType debug0,

这段代码是一个函数Dem_SetEventStatusWithEnvData的实现。以下是对该代码的简要解析:函数的输入参数包括EventId(事件ID),EventStatus(事件状态),debug0(调试数据0),debug1(调...

void Dem_ReportErrorStatusWithEnvData( Dem_EventIdType EventId, Dem_EventStatusType EventStatus, Dem_DebugDataType debug0, Dem_DebugData...

这段代码是一个C语言函数Dem_ReportErrorStatusWithEnvData的实现。以下是对该函数的解析:函数参数包括:EventId:表示事件ID,类型为Dem_EventIdType。EventStatus:...

  • Std_ReturnType Dem_SetEventStatusWithEnvData (Dem_EventIdType EventId, Dem_EventStatusType EventStatus, Dem_DebugDataType debug0,
  • qt QRectF 设置有角度的矩形

  • void Dem_ReportErrorStatusWithEnvData( Dem_EventIdType EventId, Dem_EventStatusType EventStatus, Dem_DebugDataType debug0, Dem_DebugData...

  • qt 获取矩形旋转一定角度后绘制矩形内接椭圆

  • QFSFileEngine::open: No file name specified

  •