基于FFmpeg和Qt实现简易视频播放器
生活随笔
收集整理的這篇文章主要介紹了
基于FFmpeg和Qt实现简易视频播放器
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
VideoPlay001
記得一鍵三連哦
- 使用qt+ffmpeg開發(fā)簡單的視頻播放器,無聲音
- 視頻解碼使用的是軟解碼即只用CPU進(jìn)行QPainter繪制每一幀圖像,CPU占用過高
- 簡單易學(xué),適合小白入門學(xué)習(xí)FFMpeg視頻解析的基本API
遺留問題
- 視頻播放時間的處理,基勻速播放的實(shí)現(xiàn)原理
項目代碼
videoPlay001分支
項目警告
- 注:博主本人學(xué)習(xí)過程的分享,引用他人的文章皆會標(biāo)注原作者
- 注:點(diǎn)名某初生DN,未來是屬于開源的
- 注:本人文章非盈利性質(zhì),若有侵權(quán)請聯(lián)系我刪除
- 注:聯(lián)系方式Q:2950319782
- 注:博主本人很菜,文章基本是二次創(chuàng)作,大佬請忽略我的隨筆
- 注:我會一步步分享實(shí)現(xiàn)的細(xì)節(jié),若仍有問題請留言,還可以問ChatGPT
項目引用
- Qt-FFmpeg開發(fā)-視頻播放(1)_qt如何實(shí)現(xiàn)播放.mp4視頻_mahuifa的博客-CSDN博客
- Qt使用QPainter繪制方式顯示圖片_qpainter繪制圖片-CSDN博客
問題解決
- .qri工程創(chuàng)建
- qt創(chuàng)建子工程
- 條件編譯指令
- 多文件編程
- qt自定義控件
- QImage轉(zhuǎn)QPixmap原因
- [FFmpeg基本模塊](FFmpeg 是什么? - fengMisaka - 博客園 (cnblogs.com))
- FFmpeg錯誤處理函數(shù)
- AVDictionary使用
- FFmpeg的基本API
- FFmpeg的基本結(jié)構(gòu)體
- qreal
- FFmpeg時間戳
- QThread
開發(fā)環(huán)境
- 系統(tǒng):Win10
- Qt:5.14.2
- 編譯器:qtcreator 4.11.1, minGW64
- ffmpeg: 5.12
實(shí)現(xiàn)功能
- 使用ffmpeg音視頻庫軟解碼實(shí)現(xiàn)視頻播放器
- 支持打開多種本地視頻文件(如mp4,mov,avi等)
- 支持解析多種網(wǎng)絡(luò)視頻流(如rtsp,rtmp,http等)
- 支持視頻勻速播放
- 采用QPainter進(jìn)行圖像顯示,支持自適應(yīng)窗口縮放
- 視頻播放支持實(shí)時開始,暫停,繼續(xù)播放
- 采用模塊化編程,視頻解碼,線程控制,圖像顯示各功能分離,低耦合
- 多線程編程
實(shí)現(xiàn)邏輯
- 程序主邏輯
- ffmpeg軟解碼流程
項目實(shí)現(xiàn)
項目結(jié)構(gòu)
項目思路
頁面搭建
- 需要實(shí)現(xiàn)視頻的播放,那么要先要有個頁面,使用qtcreator設(shè)計界面
- 不是很復(fù)雜的頁面我們直接使用自帶的ui界面即可
- 博主使用的是minGW64編譯
- 我們要有一個combo box來獲取網(wǎng)絡(luò)視頻流的URL或者本地視頻流的地址
- 還需要一個打開文件的按鈕,來打卡文件對話框,選擇視頻文件
- 還需要一個開始播放的按鈕和一個暫停播放的按鈕
- 至于QPainter繪制解碼出來的每一幀圖片我們自定義一個PlayImage控件,來顯示視頻
- PlayImage繼承自Widget,記得把ui文件中的PlayImage控件提升為自定義的控件
- 最終的ui圖
自定義控件
- 一步步來,我們先實(shí)現(xiàn)自定義的控件來解決視頻的功能
- 先創(chuàng)建一個CPP類PlayImage繼承自QWidget
- 為什么不用QLabel顯示圖片呢,因為顯示靜態(tài)的圖片還可以,但是如果像視頻這樣頻繁的更新圖片,會使程序變得異常卡頓,因此使用QPainter重繪每一幀圖像來實(shí)現(xiàn)視頻播放的功能
- 這個Demo圖片數(shù)據(jù)量比較小,完全可以實(shí)現(xiàn),基本的邏輯就是不斷更新圖像路徑,一直重繪,直到?jīng)]有圖像傳進(jìn)來
- 其實(shí)這里自定義控件應(yīng)該是單獨(dú)封裝的,作為外部文件引入,方便復(fù)用,但這里為了簡單,還是直接寫入代碼吧
- 在這里封裝了兩個主要的方法updateImage和updatePixmap,解碼出的每一幀圖片只需要調(diào)用對應(yīng)的圖像更新方法就可以實(shí)現(xiàn)視頻顯示
視頻解碼實(shí)現(xiàn)
- 到這里,已經(jīng)有視頻播放的功能了,現(xiàn)在需要把視頻的解碼完成出來
- 到這里呢,其實(shí)建議把視頻解碼封裝成一個單獨(dú)的功能,使用pri引入即可
- 這里呢,直接創(chuàng)建一個不帶ui文件的pri就可以,我是直接在源文件目錄下新建了一個play文件了,新建一個videoplay.pri文件,再修改一下主工程的pro文件,引入即可
- 在這個子工程中,添加一個純cpp類,videoDocode,實(shí)現(xiàn)視頻解碼主要功能
- 視頻解碼按照上面的流程圖實(shí)現(xiàn)即可,當(dāng)然需要先引入FFMpeg的l相關(guān)文件,這里建議以外部文件引入,我是放在videoplay.pri目錄下,新建一個ffmpeg文件夾,再更改一下pri文件,引入即可
視頻解碼
- 引入avformat解封裝模塊,先來把封裝的格式剝?nèi)?/li>
- 這里呢因為使用了FFmpeg,建議還是寫c風(fēng)格的代碼,省的報錯
- 先定義一個通用的處理錯誤的函數(shù)errHandle
- 然后在open函數(shù)中實(shí)現(xiàn)解析視頻流,剝?nèi)シ庋b格式,然后讀取視頻流獲取信息
- 然后我們發(fā)現(xiàn)需要手動釋放一些資源,自己定義一個free函數(shù),先釋放解封裝上下文,后續(xù)還需要釋放什么資源自己添加到free函數(shù)里就可以了
- 下面的小邏輯都在代碼里以注釋的形式表示了,不寫了,太累了
- 這里完了之后,其實(shí)就是把視頻解碼的功能封裝好,供下面的讀取線程調(diào)用,因為都寫在子線程的run函數(shù)里太復(fù)雜了,所以這里單獨(dú)處理視頻解碼
視頻解碼線程
- 這里為什么需要有一個線程類呢,因為在qt設(shè)計中,窗口的控制和各種功能的后臺實(shí)現(xiàn)應(yīng)該是不同線程處理的,否則都給窗口線程處理,這個程序會變得異常卡頓
- 直接創(chuàng)建一個readThread類繼承自QThread類,這里基本是按照流程圖調(diào)用視頻解碼的函數(shù)即可,并返回給窗口線程相應(yīng)的值,下面要定義幾個public的接口供窗口線程調(diào)用
- 主要是處理重寫run函數(shù),在cpp文件中引入videoDocode,并實(shí)例化對象,調(diào)用視頻解碼功能
- 先調(diào)用videoDocode的open函數(shù),
- 需要一個自定義信號playState來與窗口線程傳遞信息,處理播放狀態(tài)
- open成功后開始調(diào)用videoDocode的read函數(shù)
- 還需要處理視頻暫停pause的功能,這里需要先實(shí)現(xiàn)sleep延時操作
- 視頻解碼是一個相對耗時的操作,不能影響窗口線程,因此解碼線程應(yīng)該是非阻塞延時
- 成功open和read后,需要關(guān)閉線程close了
- 下面我們來處理窗口線程
窗口線程
- 在ui文件中綁定控件的槽函數(shù)
- 通過將獲取的文件路徑顯示在combox上,其他控件通過文本值調(diào)用,其實(shí)是不安全的
- 頁面的具體狀態(tài)通過自定義的信號與槽與視頻解碼線程交互
總結(jié)
以上是生活随笔為你收集整理的基于FFmpeg和Qt实现简易视频播放器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机银行的登录密码是什么
- 下一篇: 4G打猎摄像机拆机分析