本部分總結了一下界面繪製和OpenGL繪製視頻,由於使用的是Qt的openGL,功能上沒有那麼複雜,實現起來也比較簡單,畢竟人家已經給封好的,完整的代碼中使用OpenGL繪製視頻,對數據的頂點shader、片元shader着色,對yuv材質的綁定,分配材質內存空間、創建材質顯卡空間、紋理以及顯卡繪製每幀視頻時如何對齊等等一些內容,這部分內容是OpenGL中的,較爲複雜,待繼續學習後有一定收穫再來總結,現在我們繼續看這裏。
一、基於QT的播放器界面繪製
在做opengl繪製視頻前,我們先需要設計一個界面,打開vs2013中該項目中的ui,進入Qt設計界面,設置好界面的屬性後,在我們繪製視頻時,可以選擇3D引擎UX,或者OpenGL,但在這裏我們用Qt自帶的OpenGL。選擇Qt的控件Open GL Widget,在界面中繪製一片區域,設置大小以及屬性,之後加入兩個按鈕控件爲打開文件和播放視頻,加入相對應的圖標,如何加入,網上有很多方法,這裏就不囉嗦了,主要得知道這裏兩個按鈕的變量名爲openButton和playButton,後面需要用到的。
二、通過QT顯示轉碼後的RGB數據
現在我們需要將FFMpeg解碼後的視頻播放出來,如何播放?在上面中我們創建了窗口openGLWidget,這裏我們重載這個類(是對象openGLWidget的類QOpenGLWidget,重載的是這個類),然後使用我們自己的方法來控制這個窗口。這裏我將QOpenGLWidget類提升爲VideoWidget類。
然後我們在VS2013中用類嚮導創建該類進行實現(要繼承自QOpenGLWidget)。首先在VideoWidget.h中申明定時器和窗口的重新繪製的函數。
#pragma once
#include <QtWidgets/qwidget.h>
#include <QOpenGLWidget>
class VideoWidget:public QOpenGLWidget
{
public:
VideoWidget(QWidget *parent = NULL);
void paintEvent(QPaintEvent *event);//窗口的重新繪製
void timerEvent(QTimerEvent *event);//定時器
virtual ~VideoWidget();
};
對於paintEvent的定義,我們知道繪製時需要FFMpeg解碼出來的視頻幀,而對於解封裝、解碼我們都在XFFMpeg類中完成,這裏我們需要使用它。而在VideoWidget的構造函數裏需要打開視頻,同時設置定製器來顯示播放,目前這是測試階段,我們就先考慮單線程,播放時有些卡頓,當然後面我們會使用多線程解決這一問題,現在我們看下paintEvent的定義。
void VideoWidget::paintEvent(QPaintEvent *e)
{//繪製
static QImage *image = NULL;
if (image == NULL)
{
uchar *buf = new uchar[width()*height() * 4];//存放解碼後的視頻空間
image = new QImage(buf, width(), height(), QImage::Format_ARGB32);
}
AVPacket pkt = XFFmpeg::Get()->Read();//讀取視頻幀
if (pkt.stream_index != XFFmpeg::Get()->videoStream)
{//不爲視頻幀,釋放pkt的空間
av_packet_unref(&pkt);
return;
}
if (pkt.size == 0) return;
AVFrame *yuv = XFFmpeg::Get()->Decode(&pkt);//解碼讀取到的視頻幀
av_packet_unref(&pkt);//解碼成後也需要釋放空間
if (yuv == NULL) return;
//將解碼後的視頻幀轉化爲RGB
XFFmpeg::Get()->ToRGB(yuv, (char *)image->bits(),width(),height());
QPainter painter;//hua
painter.begin(this);
painter.drawImage(QPoint(0, 0), *image);//繪製FFMpeg解碼後的視頻
painter.end();//
}
XFFMpeg的讀取、解碼、轉換爲RGB在之前我們也都說明過。這裏要說下的可能就是
if (image == NULL)
{
uchar *buf = new uchar[width()*height() * 4];//存放解碼後的視頻空間
image = new QImage(buf, width(), height(), QImage::Format_ARGB32);
}
這裏的buf用來後面對於解碼後的視頻幀繪製時用到的,開闢的空間後*4是RGB有三個色彩同時這裏還有一個通道數,共佔用了四個字節,後面的image 的格式 QImage::Format_ARGB32也選擇了32位的設置,都對應了在XFFMPeg中解碼以及轉化RGB格式時所設置的一些參數。
後面就是它的構造函數以及定時器函數,裏面也都比較簡單。
VideoWidget::VideoWidget(QWidget *parent) :QOpenGLWidget(parent)
{
XFFmpeg::Get()->Open("1080.mp4");//打開視頻
startTimer(10);//設置定時器
}
void VideoWidget::timerEvent(QTimerEvent *event)
{
this->update();//定時器更新
}
對於這部分內容大概就這麼多,繪製基本如此,下一篇中我們進行視頻播放進度控制,處理之前的卡頓現象。
下一篇鏈接:https://blog.csdn.net/hfuu1504011020/article/details/82705890