QT FFmpeg-4.3.2最新版本 编译使用 音视频播放

1 篇文章 0 订阅

 

已经好久没写相关技术的文章了,最近视频播放很火,下载了最新的QT和FFmpeg,写了一个简单视频播放的测试程序,实验一下....

QT+FFMPEG实现视频播放
QT的安装自行百度, 不做过多介绍.

ffmpeg下载地址:


选择Windows版本下的https://www.gyan.dev/ffmpeg/builds/



选择此处下载动态库版本, 下载后的文件名为ffmpeg-4.3.2-2021-02-02-full_build-shared.zip, 将其改名为ffmpeg;
新建Qwidget工程;




将ffmpeg放入你所建的工程目录


修改pro中链接ffmpeg的静态库和动态库,如下:
 

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked 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 it uses 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

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target


INCLUDEPATH += $$PWD/ffmpeg/include

LIBS += $$PWD/ffmpeg/lib/avcodec.lib \
        $$PWD/ffmpeg/lib/avdevice.lib \
        $$PWD/ffmpeg/lib/avfilter.lib \
        $$PWD/ffmpeg/lib/avformat.lib \
        $$PWD/ffmpeg/lib/avutil.lib \
        $$PWD/ffmpeg/lib/postproc.lib \
        $$PWD/ffmpeg/lib/swresample.lib \
        $$PWD/ffmpeg/lib/swscale.lib

###################链接动态库
# -L表示路径  -l(小写的L)表示动态库名
LIBS += -L$$PWD/ffmpeg/bin -lavcodec-58
LIBS += -L$$PWD/ffmpeg/bin -lavdevice-58
LIBS += -L$$PWD/ffmpeg/bin -lavformat-58
LIBS += -L$$PWD/ffmpeg/bin -lpostproc-55
LIBS += -L$$PWD/ffmpeg/bin -lswresample-3
LIBS += -L$$PWD/ffmpeg/bin -lswscale-5

#也可以写成
#LIBS += -L$$PWD/../../ffmpeg/bin -lavcodec-58 -lavdevice-58 -lavformat-58 -lpostproc-55 -lswresample-3 -lswscale-5

代码实现播放功能

在界面上放置一个QLabel和QPushButton控件,当点击按钮时实现以下功能:


建立信号槽,编写一下函数:
 

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QTime>
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

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

void Delay(int msec)
{
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

void MainWindow::on_btnPlay_clicked()
{
    AVFormatContext    *pFormatCtx;
    int                i, videoindex;
    AVCodecContext    *pCodecCtx;
    AVCodec            *pCodec;
    AVFrame    *pFrame, *pFrameRGB;
    unsigned char *out_buffer;
    AVPacket *packet;
    int ret, got_picture;
    struct SwsContext *img_convert_ctx;

    char filepath[] = "E:\\Travel\\travel.mp4";
    //初始化编解码库
    av_register_all();//创建AVFormatContext对象,与码流相关的结构。
    pFormatCtx = avformat_alloc_context();
    //初始化pFormatCtx结构
    if (avformat_open_input(&pFormatCtx, filepath, 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 ;
    }
    videoindex = -1;
    //nb_streams视音频流的个数,这里当查找到视频流时就中断了。
    for (i = 0; i < 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 ;
    }
    //用于初始化pCodecCtx结构
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
        printf("Could not open codec.\n");
        return ;
    }
    //创建帧结构,此函数仅分配基本结构空间,图像数据空间需通过av_malloc分配
    pFrame = av_frame_alloc();
    pFrameRGB = av_frame_alloc();
    //创建动态内存,创建存储图像数据的空间
    //av_image_get_buffer_size获取一帧图像需要的大小
    out_buffer = (unsigned char *)av_malloc(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));
    //Output Info-----------------------------
    printf("--------------- File Information ----------------\n");
    //此函数打印输入或输出的详细信息
    av_dump_format(pFormatCtx, 0, filepath, 0);
    printf("-------------------------------------------------\n");
    //初始化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));
                Delay(40);
            }
        }
        av_free_packet(packet);
    }
    sws_freeContext(img_convert_ctx);
    av_frame_free(&pFrameRGB);
    av_frame_free(&pFrame);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
}


编译运行结果, 测试ok~




备注, QT的版本:



工程地址,需要的自己去拿: https://download.csdn.net/download/zxncvb/15116837

基于Linux的Qt FFmpeg音视频播放是一种使用Qt框架和FFmpeg在Linux操作系统上实现音视频播放的方法。 Qt是一种跨平台的应用程序开发框架,它提供了丰富的图形用户界面(GUI)组件和功能,便于开发人员创建各种类型的应用程序。而FFmpeg是一个开源的音视频处理,它提供了处理音视频文件、编解码和转换等功能。 在基于Linux的Qt FFmpeg音视频播放中,首先需要使用Qt提供的界面设计工具创建一个用户界面,可以包含播放按钮、进度条、音量控制等控件。然后,通过Qt的信号与槽机制将这些控件与相应的函数连接起来。 接下来,需要使用FFmpeg来解码和播放音视频文件。通过FFmpeg提供的API,可以打开音视频文件并获取其音频和视频流。然后,使用FFmpeg的解码功能将音频和视频流解码为原始的音频和视频数据。最后,使用Qt的音频和视频播放功能,将解码后的数据进行播放。 同时,基于Linux的Qt FFmpeg音视频播放还可以实现其他功能,比如暂停、快进、快退等操作。这些功能可以通过控制音频和视频的时间戳来实现。 总之,基于Linux的Qt FFmpeg音视频播放提供了一种灵活、可定制的方式来实现音视频播放功能。它可以适用于各种需求,比如嵌入式设备上的音视频播放、音频编辑和处理等。同时,Qt的跨平台特性也使得这种方法可以在其他操作系统上实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值