Debug和Release載入不同動態庫:
//將lib文件放到對應工程目錄下,在.pro添加存放lib的路徑
LIBPATH += $$PWD/Library/Lib
//debug為active時處理LIBS += -L$$LIB_PATH -lOpengl32...
CONFIG(debug, debug|release){
LIBS += -L$$LIBPATH -lOpengl32...}
else{
LIBS += -L$$LIBPATH -lOpengl32 -lavcodec...}
或
CONFIG(debug, debug|release):LIBS += -L$$LIBPATH -lOpengl32...
CONFIG(release, debug|release):LIBS += -L$$LIBPATH -lOpengl32 -lavcodec..
//在對應的debug或release目錄下添加使用的.dll文件
//本例中用到的库文件:
INCLUDEPATH += $$PWD/Dev/include
LIBPATH += $$PWD/Dev/lib
LIBS += -L$$LIBPATH -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale
屏蔽QDebug()提示信息:在pro文件中添加:DEFINES+=QT_NO_DEBUG_OUTPUT
FFmpeg:
靜態庫版本:Static,只包含三個應用程式,不依賴動態庫可單獨運行;
動態庫版本:Shared,除應用程式外還包含dll動態庫;
開發者版本:Dev,包含lib文件和.h文件,但不包含dll文件。
使用ffmpeg要注意對應版本(如編譯器32位則使用32位的FFmpeg版本),ffmpeg庫為C文件,導入需在頭文件添加關鍵詞extetn “C”。
可將dll拷貝進lib,發佈時再拷貝dll進運行目錄或將dll拷貝進運行目錄。
檢查環境配置是否搭建成功:
unsigned version = avcodec_version();
QString ch = QString::number(version,10);
qDebug()<<"version: "<<version<<"\n配置信息:"<<avcodec_configuration();
注册FFmpeg组件:注册和初始化FFmpeg封装器和网络设备
av_register_all();
avformat_network_init();
QAudioOutput
是Qt中播放音频的类,要使用它,需要在pro中加入 QT += multimedia
程序代码:
(1)设置继承线程继承QThread
basicthread.h
#ifndef BASICTHREAD_H
#define BASICTHREAD_H
#include <QThread>
#include <QDebug>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavdevice/avdevice.h>
#include <libavformat/version.h>
#include <libavutil/time.h>
#include <libavutil/mathematics.h>
#include "libswresample/swresample.h"
}
class basicthread:public QThread
{
Q_OBJECT
public:
basicthread(QObject * parent = nullptr);
~basicthread();
};
#endif // BASICTHREAD_H
basicthread.cpp
#include "basicthread.h"
basicthread::basicthread(QObject * parent):QThread(parent)
{
}
basicthread::~basicthread(){
quit();
wait();
qDebug()<<"~BasicThread";
}
(2)初始化视频流线程:
initthread.h
#ifndef INITTHREAD_H
#define INITTHREAD_H
#include "basicthread.h"
class initthread : public basicthread
{
Q_OBJECT
public:
initthread(QObject*parent=nullptr);
void closeinitthread();
SwrContext*swrContext;
AVCodecContext*audioCodecContext;
signals:
void sendcontext(AVFormatContext*,AVCodecContext*,AVCodecContext*,SwrContext*);
protected:
//重写虚函数run(),只有在此函数在新线程里,运行完毕后该线程生命周期结束
virtual void run();
};
#endif // INITTHREAD_H
initthread.cpp
#include "initthread.h"
initthread::initthread(QObject*parent):basicthread(parent)
{
}
void initthread::run(){
int videoStreamIndex=-1;int audioStreamIndex=-1;uint i;
//注册库中所有可用的文件格式和解码器
av_register_all();
//初始化网络流格式,使用RTSP网络流时必须先执行
avformat_network_init();
//申請一個AVFormatContext結構的内存,並進行簡單初始化
AVFormatContext* avFormatContext = avformat_alloc_context();
//打開視頻流
int ret=avformat_open_input(&avFormatContext,"C:\\Users\\shelly\\Desktop\\guitar.mp4",NULL,NULL);
if(ret!=0){
qDebug()<<"打開視頻流失敗";
avformat_free_context(avFormatContext);
}
//讀取流數據包並獲取相關信息
if(avformat_find_stream_info(avFormatContext,NULL)<0){
qDebug()<<"獲取視頻流信息失敗";
avformat_close_input(&avFormatContext);
}
for(i=0;i<avFormatContext->nb_streams;i++){
//確定流格式是否為視頻
if(avFormatContext->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){
videoStreamIndex=i;
}
if(videoStreamIndex==-1){
avformat_close_input(&avFormatContext);
qDebug()<<"獲取視頻流索引失敗";
}
//確定流格式是否為音頻
if(avFormatContext->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO){
audioStreamIndex=i;
}
}
//视频部分处理
//根據編碼器ID獲取視頻劉解碼器
AVCodec*videoCodec = avcodec_find_decoder(avFormatContext->streams[videoStreamIndex]->codecpar->codec_id);
if(videoCodec==NULL){
qDebug()<<"尋找视频解碼器失敗";
}
//获取视频编解码器上下文信息
AVCodecContext*videoCodecContext = avcodec_alloc_context3(videoCodec);
if(videoCodecContext==NULL){
avformat_close_input(&avFormatContext);
qDebug()