QT ubuntu下开发视频播放 FFmpeg

ubuntu 安装FFmpeg

T113VideoDemo.pro

bash 复制代码
#-------------------------------------------------
#
# Project created by QtCreator 2023-07-28T11:45:22
#
#-------------------------------------------------

QT       += core gui


greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = T113VideoDemo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui


INCLUDEPATH += /usr/local/ffmpeg/include \

LIBS += /usr/local/ffmpeg/lib/libavcodec.so \
        /usr/local/ffmpeg/lib/libavdevice.so \
        /usr/local/ffmpeg/lib/libavfilter.so \
        /usr/local/ffmpeg/lib/libavformat.so \
        /usr/local/ffmpeg/lib/libavutil.so \
        /usr/local/ffmpeg/lib/libpostproc.so \
        /usr/local/ffmpeg/lib/libswresample.so \
        /usr/local/ffmpeg/lib/libswscale.so \

mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private slots:
    void slotOpenFile();

    void on_pushButton_clicked();

    void on_close_clicked();

    void on_screen_clicked();

private:
    Ui::MainWindow *ui;
    QString currentFileName;

};

#endif // MAINWINDOW_H

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTime>
#include <QFileDialog>
#include <QScreen>
// 调用FFmpeg的头文件
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
// 延时函数
void delay(int msec){
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("hello");//设置窗口的标题
    QObject::connect(ui->open,SIGNAL(clicked()),this,SLOT(slotOpenFile()));

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slotOpenFile()//打开文件键
{
    currentFileName = QFileDialog::getOpenFileName(this, tr("open-file"), tr(""),
                                                   tr("Video files(*.rmvb *.rm *.avi *.wmv *.mkv *.asf *.3gp *.mov *.mp4 *.ogv* )"));
    if( !currentFileName.isEmpty() )
    {
        on_pushButton_clicked();
    }
}


void MainWindow::on_pushButton_clicked(){
    AVFormatContext *pFormatCtx; // 存储音视频封装格式中包含的信息
    int videoIndex = -1; // 视频帧索引,初始化为-1
    AVCodecContext *pCodecCtx; // 视频流编码结构
    AVCodec *pCodec; // 视频解码器
    AVFrame *pFrame, *pFrameRGB;
    unsigned char *out_buffer;
    AVPacket *packet;
    int ret, got_picture;
    struct SwsContext *img_convert_ctx; // 主要用于视频图像的转换

    char file_path[1280] = {0};
    strcpy(file_path,currentFileName.toUtf8().data());

    // 注册FFMpeg的库
    av_register_all();

    /*** (一)打开音视频流并获取音视频流信息 ***/
    // 初始化AVFormatContext
    pFormatCtx = avformat_alloc_context();
    // 打开音视频流
    /*avformat_open_input函数*/
    //打开一个文件并解析。可解析的内容包括:视频流、音频流、视频流参数、音频流参数、视频帧索引。
    //参数一:AVFormatContext **ps, 格式化的上下文(由avformat_alloc_context分配)的指针。
    //参数二:要打开的流的url,地址最终会存入到AVFormatContext结构体当中。
    //参数三:指定输入的封装格式。一般传NULL,由FFmpeg自行探测。
    //参数四:包含AVFormatContext和demuxer私有选项的字典。返回时,此参数将被销毁并替换为包含找不到的选项
    if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0)
    {
        printf("Couldn't open input stream.\n");
        return;
    }
    // 获取音视频流数据信息
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
    {
        printf("Couldn't find stream information.\n");
        return;
    }

    /*** (二)查找视频流位置以及查找并打开视频解码器 ***/
    // 查找视频流的起始索引位置(nb_streams表示视音频流的个数)
    for (int i = 0; i < (int)pFormatCtx->nb_streams; i++)
    {
        // 查找到视频流时退出循环
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) // 判断是否为视频流
        {
            videoIndex = i;
            break;
        }
    }
    if (videoIndex == -1)
    {
        printf("Didn't find a video stream.\n");
        return ;
    }
    // 查找视频解码器
    pCodecCtx = pFormatCtx->streams[videoIndex]->codec; // 获取视频流编码结构
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL)
    {
        printf("Codec not found.\n");
        return ;
    }
    // 打开解码器
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        printf("Could not open codec.\n");
        return ;
    }

    // 打印视频信息
    printf("--------------- File Information ----------------\n");
    av_dump_format(pFormatCtx, 0, file_path, 0); // 此函数打印输入或输出的详细信息
    printf("-------------------------------------------------\n");

    /*** (三)视频解码的同时处理图片像素数据 ***/
    // 创建帧结构,此函数仅分配基本结构空间,图像数据空 间需通过av_malloc分配
    pFrame = av_frame_alloc();
    pFrameRGB = av_frame_alloc();
    // 创建动态内存,创建存储图像数据的空间(av_image_get_buffer_size获取一帧图像需要的大小)
    out_buffer = (unsigned char *)av_malloc((size_t)av_image_get_buffer_size(AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1));
    // 存储一帧像素数据缓冲区
    av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer,
                         AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1);
    packet = (AVPacket *)av_malloc(sizeof(AVPacket));

    // 初始化img_convert_ctx结构
    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                                     pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
    // av_read_frame读取一帧未解码的数据
    while (av_read_frame(pFormatCtx, packet) >= 0)
    {
        // 如果是视频数据
        if (packet->stream_index == videoIndex)
        {
            // 解码一帧视频数据
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
            if (ret < 0)
            {
                printf("Decode Error.\n");
                return ;
            }
            if (got_picture)
            {
                sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
                          pFrameRGB->data, pFrameRGB->linesize);
                QImage img((uchar*)pFrameRGB->data[0],pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
                ui->label->setPixmap(QPixmap::fromImage(img)); // 在label上播放视频图片
                delay(40);
            }
        }
        av_free_packet(packet);
    }

    /*** (四)最后要释放申请的内存空间 ***/
    sws_freeContext(img_convert_ctx); // 释放一个SwsContext
    av_frame_free(&pFrameRGB);
    av_frame_free(&pFrame);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
}

void MainWindow::on_close_clicked(){
    close();

}

void MainWindow::on_screen_clicked(){
//    static bool max = false;
//    static QRect location = this->geometry();
//    if (max) {
//        this->setGeometry(location);
//    } else {
//        location = this->geometry();
//        this->setGeometry(qApp->desktop()->availableGeometry());
//    }

//    this->setProperty("canMove", max);
//    max = !max;

}
相关推荐
EasyDSS1 分钟前
视频推流平台EasyDSS无人机推流直播在应急抢险可视化指挥中的实践
音视频·无人机
大模型实验室Lab4AI10 分钟前
Qwen-Video-8B与LLaMA-Factory联动实现垂类视频理解
人工智能·音视频·llama
石像鬼₧魂石7 小时前
内网渗透靶场实操清单(基于 Vulhub+Metasploitable 2)
linux·windows·学习·ubuntu
木千9 小时前
Qt中关于eventFilter函数无法过滤QTableWidget鼠标事件的处理方式
qt
Likeadust14 小时前
视频直播点播平台EasyDSS助力阳光政务直播体系建设
音视频·政务
知识分享小能手14 小时前
Ubuntu入门学习教程,从入门到精通,Linux操作系统概述(1)
linux·学习·ubuntu
我只会发热15 小时前
Ubuntu 20.04.6 根目录扩容(图文详解)
linux·运维·ubuntu
奇树谦16 小时前
【Qt实战】实现图片缩放、平移与像素级查看功能
开发语言·qt
木子欢儿16 小时前
Ubuntu 24 安装 fcitx5 + rime + 雾凇配置
linux·运维·服务器·ubuntu