国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

FFMpeg-3、基于QT實現(xiàn)音視頻播放顯示

這篇具有很好參考價值的文章主要介紹了FFMpeg-3、基于QT實現(xiàn)音視頻播放顯示。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

1、音視頻播放的基礎(chǔ)知識

內(nèi)容來自雷神博客

1、在Windows平臺下的視頻播放技術(shù)主要有以下三種:GDI,Direct3D和OpenGL;音頻播放技術(shù)主要是DirectSound。

SDL本身并不具有播放顯示的功能,它只是封裝了底層播放顯示的代碼

記錄三種視頻顯示技術(shù):GDI,Direct3D,OpenGL。其中Direct3D包含簡單和復(fù)雜的兩種顯示方式:使用Surface和使用Texture;OpenGL也包含簡單和復(fù)雜的兩種顯示方式:直接畫像素和使用Texture。

GDI 微軟顯示窗口提供的一套顯示機(jī)制,他工作的主要流程就是構(gòu)建BMP文件(原始的RGB數(shù)據(jù),構(gòu)建bmp文件頭),調(diào)用接口將bmp文件繪制到屏幕上。注意都需要轉(zhuǎn)換為RGB格式數(shù)據(jù)。

Direct3D微軟開發(fā)的一套3D繪圖API,Direct3D的抽象概念包括:Devices(設(shè)備),Swap Chains(交換鏈)和Resources(資源)。

Device(設(shè)備)用于渲染3D場景。例如單色設(shè)備就會渲染黑白圖片,而彩色設(shè)備則會渲染彩色圖片。

每一個Device至少要有一個Swap Chain(交換鏈)。一個Swap Chain由一個或多個Back Buffer Surfaces(后臺緩沖表面)組成。渲染在Back Buffer中完成。

Device包含了一系列的Resources(資源),用于定義渲染時候的數(shù)據(jù)

Direct3D API定義了一組Vertices(頂點(diǎn)), Textures(紋理), Buffers(緩沖區(qū))轉(zhuǎn)換到屏幕上的流程。這樣的流程稱為Rendering Pipeline(渲染流水線),具體就是從應(yīng)用程序里讀取vertex頂點(diǎn)數(shù)據(jù),對每個頂點(diǎn)屬性進(jìn)行著色,最后將著色器處理的數(shù)據(jù)輸出給使用者。

2、視頻顯示的基礎(chǔ)知識

三角形;在繪圖中所有平面都可以用三角形繪制出來的,并且顯卡的性能強(qiáng)弱都是比較單位時間內(nèi)畫三角形的個數(shù)的。

后臺緩沖表面,前臺表面,交換鏈,離屏表面。

后臺緩沖表面和前臺表面的概念總是同時出現(xiàn)的。簡單解釋一下它們的作用。當(dāng)我們進(jìn)行復(fù)雜的繪圖操作時,畫面可能有明顯的閃爍。這是由于繪制的東西沒有同時出現(xiàn)在屏幕上而導(dǎo)致的?!扒芭_表面”+“后臺緩沖表面”的技術(shù)可以解決這個問題,就是一個緩沖的作用。

交換鏈;其實就是一個后臺緩沖表面,一個前臺表面。所謂的“交換”,即是在需要呈現(xiàn)后臺緩沖表面中的內(nèi)容的時候,交換這兩個表面的“地位”。即前臺表面變成后臺緩沖表面,后臺緩沖表面變成前臺表面。如此一來,后臺緩沖表面的內(nèi)容就呈現(xiàn)在屏幕上了。原先的前臺表面,則扮演起了新的后臺緩沖表面的角色,準(zhǔn)備進(jìn)行新的繪圖操作。當(dāng)下一次需要顯示畫面的時候,這兩個表面再次交換,如此循環(huán)往復(fù),永不停止。

離屏表面、離屏表面是永遠(yuǎn)看不到的表面(所謂“離屏”),它通常被用來存放位圖,并對其中的數(shù)據(jù)做一些處理。通常的做法是把離屏表面上的位圖復(fù)制到后臺緩沖表面,后臺緩沖表面再顯示到前臺表面。

使用Direct3D的Surface播放視頻一般情況下需要如下步驟:

創(chuàng)建一個窗口(不屬于D3D的API)

初始化

創(chuàng)建一個Device

基于Device創(chuàng)建一個Surface(離屏表面)

循環(huán)顯示畫面

清理

一幀視頻數(shù)據(jù)拷貝至 Surface

開始一個Scene

Surface數(shù)據(jù)拷貝至 后臺緩沖表面

結(jié)束Scene

顯示( 后臺緩沖表面-> 前臺表面)

3、OpenGL開放圖形庫,定義了一個跨編程語言、跨平臺的應(yīng)用程序接口(API)的規(guī)范,它用于生成二維、三維圖像。

OpenGL渲染管線(OpenGL Pipeline)按照特定的順序?qū)D形信息進(jìn)行處理,這些圖形信息可以分為兩個部分:頂點(diǎn)信息(坐標(biāo)、法向量等)和像素信息(圖像、紋理等)。圖形信息最終被寫入幀緩存中,存儲在幀緩存中的數(shù)據(jù)(圖像),可以被應(yīng)用程序獲得(用于保存結(jié)果,或作為應(yīng)用程序的輸入等。

關(guān)鍵就是頂點(diǎn)操作和紋理操作。

通過openGL的紋理顯示圖片

注意通過紋理顯示則;輸入的YUV420P像素數(shù)據(jù)通過Shader轉(zhuǎn)換為YUV數(shù)據(jù),傳送給OpenGL播放。像素的轉(zhuǎn)換YUV到RGB是通過顯卡上的GPU完成的,則效率更高視頻播放性能更好。

使用Shader通過OpenGL的紋理(Texture)播放視頻一般情況下需要如下步驟:

初始化

初始化

創(chuàng)建窗口

設(shè)置繪圖函數(shù)

設(shè)置定時器

初始化Shader

初始化Shader的步驟比較多,主要可以分為3步:創(chuàng)建Shader,創(chuàng)建Program,初始化Texture。

(1) 創(chuàng)建一個Shader對象;Shader有點(diǎn)類似于一個程序的編譯器

1)編寫Vertex Shader和Fragment Shader源碼。

2)創(chuàng)建兩個shader 實例 。

3)給Shader實例指定源碼。

4)在線編譯shaer源碼。

(2) 創(chuàng)建一個Program對象

1)創(chuàng)建program。

2)綁定shader到program。

3)鏈接program。

4)使用porgram。

(3) 初始化Texture??梢苑譃橐韵虏襟E。

1)定義定點(diǎn)數(shù)組

2)設(shè)置頂點(diǎn)數(shù)組

3)初始化紋理

進(jìn)入消息循環(huán)

循環(huán)顯示畫面

設(shè)置紋理

繪制

顯示

2、QT的音頻錄制 QAudioFormat

QAudioFormat記錄音頻參數(shù)的格式

setSampleRate 樣本率

setSampleSize 設(shè)置的位數(shù),S16,S8等,這里不區(qū)分layout,設(shè)置的是位數(shù)而不是字節(jié)數(shù),則這樣要根據(jù)不同的樣本類型進(jìn)行轉(zhuǎn)換。

setChannelCount 設(shè)置通道數(shù)量

setCodec(“audio/pcm”)設(shè)置編碼格式,暫時可能只支持pcm格式的,與聲卡硬件有關(guān)的。

setByteOrder(QAudioFormat::LittleEndian)設(shè)置大小端模式,注意網(wǎng)絡(luò)傳輸一般是采用大端的(低字節(jié)在高位),x86windows一般都是小端的(低位在低字節(jié))。

setSampleType(QAudioFormat::UnSignedInt) 設(shè)置樣本類型

QAudioOutput 打開播放音頻設(shè)備

其構(gòu)造函數(shù)創(chuàng)建是傳入一個設(shè)置好的QAudioFormat對象的

QIODevice *start();創(chuàng)建成功后調(diào)用開始函數(shù),會返回QIODevice ,這個是QT內(nèi)部的一個類,做IO輸入輸出設(shè)備的類。

suspend() 掛起暫停

resume() 恢復(fù)播放

因為音頻不像視頻,如果音頻丟幀了那么現(xiàn)象會有很嚴(yán)重的失真的,因此需要存在緩沖機(jī)制的。

bufferSize() 緩沖的大小

bytesFree() 得到緩沖內(nèi)部還有多少內(nèi)存

bufferSize() - bytesFree() 可以得到我們緩沖區(qū)里面還有多少內(nèi)存沒有釋放的,在做音視頻同步的時候需要考慮。

periodSize() 內(nèi)部硬件讀取多大才寫入,

QIODevice 音頻設(shè)備的抽象

qint64 write(const char *data, qint64 len) 寫入,這個就是我們解碼出來重采樣后直接把數(shù)據(jù)通過write寫入就可以播放了。返回的大小才是真正寫入的大小,也可以重載一下保證把傳入的len都寫入進(jìn)去,還可以采用判斷bytesFree緩沖空間足夠大的時候才把他寫入進(jìn)去,保證都能寫入。

代碼實戰(zhàn)

//注意如果在QT CRTEAT下編寫的話要在pro文件加入QT += multimediawidgets
#include <QCoreApplication>
#include <QAudioFormat>
#include <QAudioOutput>
#include <QThread>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QAudioFormat fmt;
    fmt.setSampleRate(44100);//樣本率
    fmt.setSampleSize(16);  //樣本大小 S16
    fmt.setChannelCount(2); //雙通道
    fmt.setCodec("audio/pcm"); //設(shè)置pcm編碼器
    fmt.setByteOrder(QAudioFormat::LittleEndian);//這是字節(jié)序
    fmt.setSampleType(QAudioFormat::UnSignedInt);//設(shè)置樣本類型
    QAudioOutput *out = new QAudioOutput(fmt);//創(chuàng)建QAudioOutput
    QIODevice *io = out->start(); //開始播放

    int size = out->periodSize();//一個周期的大小,硬件設(shè)備一次讀多大
    char *buf = new char[size];

    FILE *fp = fopen("out.pcm", "rb");
    while (!feof(fp))
    {
        //如果緩沖空間剩余內(nèi)存不夠size,硬件還沒取走
        if (out->bytesFree() < size)
        {
            QThread::msleep(1);
            continue;
        }
        int len = fread(buf, 1, size, fp);
        if (len <= 0)break;
        io->write(buf, len);
    }
    fclose(fp);
    delete buf;
    buf = 0;

    return a.exec();
}

總結(jié);QT音頻播放基于三個類進(jìn)行操作

先設(shè)置QAudioFormat音頻格式,

再通過設(shè)置的音頻格式創(chuàng)建QAudioOutput 音頻輸出設(shè)備啟動設(shè)備和設(shè)置緩沖,

最后通過QAudioOutput 的啟動得到具體聲卡設(shè)備的抽象對象QIODevice ,通過向QIODevice 進(jìn)行寫入音頻數(shù)據(jù)實現(xiàn)音頻播放的。

3、QT視頻繪制 QT openGL編程

雷神博客介紹OpenGL基于紋理顯示的流程

因為視頻顯示存在像素格式的轉(zhuǎn)換問題,要從解碼出來的YUV格式轉(zhuǎn)化為顯示需要的RGB格式,視頻的每一幀圖像這么多像素點(diǎn)都需要轉(zhuǎn)換,這是一個很大的開銷,如果這一部分效率不高,那么對整體的視頻播放性能都是十分有影響的,而QTopenGL也是效率很高的,直接操作顯卡。

Shader有點(diǎn)類似于一個程序的編譯器,

1)編寫Vertex Shader和Fragment Shader源碼。GLSL語言編寫類似與C語言的一樣的代碼,它可以放在GPU里面被并行運(yùn)行。

Vertex Shader(如果要存放到文件中就在.vsh)負(fù)責(zé)搞定像素位置,填寫gl_Posizion;

Fragment Shader(Fragment Shader fsh)負(fù)責(zé)搞定像素外觀,填寫 gl_FragColor;

Program有點(diǎn)類似于一個程序的鏈接器。

program對象提供了把需要做的事連接在一起的機(jī)制,在一個program中,shader對象可以連接在一起。

QTopenGL顯示的幾個關(guān)鍵點(diǎn)

QOpenGLWidget (與界面如何交互)

Program GLSL 頂點(diǎn)與片元(如何與顯卡交互的,GLSL 是跑在顯卡上面的)

材質(zhì)紋理Texture (如何寫入ffmpeg數(shù)據(jù)的)

頂點(diǎn)和紋理材質(zhì)

下面有相關(guān)介紹

為什么要采用QT的OpenGL三維的來繪制,直接使用QopenWidget、QWight也是可以的,但是如果使用后面的那么其實圖像顯示和界面的按鈕是一套東西,當(dāng)點(diǎn)擊按鈕刷新的時候就會存在閃屏的情況。因此采用三維的,QTOpenGL這種就是提供三維繪制,就可以自動在界面上疊加了。

使用的時候需要重載這些函數(shù)
void paintGL();//具體繪制在這里面實現(xiàn)
void initializeGL();//初始化
void resizeGL(int width,int height)//當(dāng)窗口發(fā)生變化的時候調(diào)用,這個函數(shù)

還提供了很大的便利,如如果需要視頻放縮的時候就可以直接調(diào)用OpenGL里面的函數(shù),不然就需要在ffmpeg進(jìn)行像素尺寸的轉(zhuǎn)換效率就比較低了并且采用不同的算法效果可能也不一定好。而openGL中就是采用差值的算法來放縮,整體界面就減少失真的情況。

封裝了操作OpenGL對象的函數(shù)類QOpenGLFunctions

QOpenGL相關(guān)的函數(shù)是單獨(dú)有一個類來封裝的,是QOpenGLFunctions

類,這里面就有很多與openGL相關(guān)的函數(shù)了,因此也可以進(jìn)行QOpenGLFunctions繼承來獲取操作openGL的相關(guān)函數(shù)。

QGLShaderProgram編譯運(yùn)行shader和shader交互

shader 著色器

這個程序最終是在顯卡上運(yùn)行的,是通過QGLShaderProgram 來與顯卡進(jìn)行交互的。

QGLShaderProgram 主要封裝的函數(shù)有

編譯運(yùn)行shader

addShaderFromSourceCode 把shader的源代碼加載進(jìn)來,有兩部分代碼,是頂點(diǎn)shader和片元shader(又稱為像素shader)

bindAttributeLocation 設(shè)置傳入的屬性,只要是設(shè)置頂點(diǎn)坐標(biāo)的屬性和材質(zhì)紋理Texture坐標(biāo)的屬性,后面可以傳入頂點(diǎn)坐標(biāo)或材質(zhì)坐標(biāo)然后對應(yīng)坐標(biāo)設(shè)置什么變量是通過他來設(shè)置的。

uniformLocation 獲取shader變量 就是將顯卡當(dāng)中變量的一塊地址取出來

總結(jié);就是編譯運(yùn)行shader、傳入shader程序,設(shè)置變量,獲取變量

GLSL著色器語言 基于openGL設(shè)計的,給顯卡用的語言

OpenGL Shader Language,簡稱GLSL。它是一種類似于C語言的專門為GPU設(shè)計的語言,它可以放在GPU里面被并行運(yùn)行。

頂點(diǎn)著色器,就是針對每個頂點(diǎn)執(zhí)行一次,用于確定頂點(diǎn)的位置,因為在三維空間中要將所有頂點(diǎn)的參數(shù)都獲取。一般頂點(diǎn)著色器都是畫三角形,如計算顯卡的能力都是看他能畫出多少個三角形,這里圖片的顯示我們采用畫矩形,也就是兩個三角形組合。因此我們這里頂點(diǎn)著色器的代碼就是畫兩個三角形組成矩形。

qt如何使用音視頻,ffmpeg,qt,音視頻

代碼填充就是

float *vertexData = new float[12]{
	-1.0f,-1.0f,0.0f,
    1.0f,-1.0f,0.0f,
     -1.0f, 1.0f,0.0f,
     1.0f,1.0f,0.0f
}
//也可以第三維的0這里不傳入。再傳入的時候告訴他填充的是二維的要他在內(nèi)部填充

片元著色器,就是針對一個平面的,針對每個片元(可以理解為每個像素)執(zhí)行一次,用于確定每個片元(像素)的顏色 。傳入YUV的數(shù)據(jù)過來,至于至于轉(zhuǎn)換可以到顯卡自己那邊轉(zhuǎn)換。片元著色器他有一個內(nèi)置變量gl_FragColor,就是在遍歷像素點(diǎn)的時候?qū)⑦@個值進(jìn)行改變,那么他的顏色一會跟著變化的。

流程就是通過頂點(diǎn)著色器獲取頂點(diǎn)的位置,再通過片元著色器對這些頂點(diǎn)構(gòu)成的片元像素進(jìn)行填充顏色。

GLSL基本語法與C基本相同,這里只是做簡單圖像顯示,真正的GLSL是用來做特效的,涉及算法的,

GLSL 完美支持向量和矩陣操作,因此在像素格式的轉(zhuǎn)換方面十分適合選用,并且提供了大量的內(nèi)置函數(shù)來提供豐富的擴(kuò)展功能的,

他是通過限定符操作來管理輸入輸出類型的,例如傳入頂點(diǎn)坐標(biāo),傳出材質(zhì)紋理等。

材質(zhì)坐標(biāo)信息

qt如何使用音視頻,ffmpeg,qt,音視頻

與頂點(diǎn)不同的是他是二維的并且坐標(biāo)都是正數(shù)。

代碼設(shè)置;

float *textureVertexData = new float[8]{
	0.0f, 1.0f,
	1.0f, 1.0f,
	0.0f, 0.0f,
	1.0f, 0.0f
}
//也可以第三維的0這里不傳入。再傳入的時候告訴他填充的是二維的要他在內(nèi)部填充

三種GLSL變量類型

varying頂點(diǎn)與片元共享,就是有兩部分代碼頂點(diǎn)著色器代碼計算出來的頂點(diǎn)坐標(biāo)通過這個變量傳給片元著色器那段代碼,然后就可以獲取到材質(zhì)位置。可見代碼理解。

atrribute 頂點(diǎn)使用 由bindAttributeLocation傳入,就是我們創(chuàng)建的數(shù)組通過他傳入過去進(jìn)行計算

uniform 程序傳入 uniformLocation獲取地址,就是我們ffmpeg解碼出來的YUV數(shù)據(jù)要傳入進(jìn)去變成uniform。

最后再通過glUniform1i(textureUniformY,0)傳入與材質(zhì)層進(jìn)行綁定

//自動加雙引號 定義常量串都可以使用
#define GET_STR(x) #x
//頂點(diǎn)著色器的shader代碼
const char *vString = GET_STR(
	attribute vec4 vertexIn;
	attribute vec2 textureIn;
	varying vec2 textureOut;
	void main(void)
	{
		gl_Position = vertexIn;//傳入的頂點(diǎn)坐標(biāo)記錄
		textureOut = textureIn;//傳入的材質(zhì)坐標(biāo)保存到textureOut
	}
);
//自動加雙引號 定義常量串都可以使用
#define GET_STR(x) #x
//片元著色器的shader代碼
const char *tString = GET_STR(
	varying vec2 textureOut;//剛剛頂點(diǎn)著色器算出來的坐標(biāo)
	uniform sampler2D tex_y;//uniform是外部傳入的變量
	uniform sampler2D tex_u;
	uniform sampler2D tex_v;
	void main(void)
	{
	//420P是平面存儲的,最后都是要轉(zhuǎn)換為每個像素都是有yuv再方便轉(zhuǎn)換
	//用的是灰度圖的形式存儲的
	//如安裝那邊硬解碼出來的都是yuv420sp,uv是打包存在一起的,則不能使用這套shader代碼了,要增加透明度存儲方式。
		vec3 yuv;
		vec3 rgb;
		//根據(jù)那個坐標(biāo)把材質(zhì)坐標(biāo)計算出來
		//傳入材質(zhì),和坐標(biāo)   返回材質(zhì)當(dāng)中的顏色rgb,但是用灰度圖存儲的,都是一樣的。
		//三個材質(zhì)就可以拼出一個yuv的數(shù)據(jù)
		yuv.x = texture2D(tex_y, textureOut).r;//獲取材質(zhì)當(dāng)中的顏色 
		yuv.y = texture2D(tex_u, textureOut).r - 0.5;
		yuv.z = texture2D(tex_v, textureOut).r - 0.5;
		//轉(zhuǎn)換公式
		rgb = mat3(1.0, 1.0, 1.0,
			0.0, -0.39465, 2.03211,
			1.13983, -0.58060, 0.0) * yuv;
		gl_FragColor = vec4(rgb, 1.0);//轉(zhuǎn)換成顯示的顏色,再設(shè)置一下
	}

);

創(chuàng)建材質(zhì)

shader其實就是繪制某一個材質(zhì),那么就要看創(chuàng)建材質(zhì)了。qt也有創(chuàng)建材質(zhì)的函數(shù),但是openGL這邊要簡單一點(diǎn)。

glGenTextures(1,t);創(chuàng)建幾個材質(zhì),傳入二維數(shù)組存放創(chuàng)建的材質(zhì)地址

glBindTexture(GL_TEXTURE_2D *t)進(jìn)行綁定 綁定為2d的圖像

glTexPatameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)設(shè)置屬性  放大的屬性  
glTexPatameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)設(shè)置屬性  縮小的屬性
GL_TEXTURE_2D操作的是2D紋理
GL_TEXTURE_MAG_FILTER  放大過濾
GL_TEXTURE_MIN_FILTER  縮小過濾
GL_LINEAR用線性差值的方式進(jìn)行縮放 使用距離當(dāng)前渲染像素中心最近的四個紋素加權(quán)平均值,則最后的圖像變化就比較榮和

寫入和繪制材質(zhì)

glActiveTexture(GL_TEXTURE0);激活材質(zhì) 序號0
glBindTexture(GL_TEXTURE_2D,id_y);綁定之前創(chuàng)建的材質(zhì)
在顯存當(dāng)中創(chuàng)建材質(zhì) 
//將openGL里面的創(chuàng)建的材質(zhì)設(shè)置傳入到內(nèi)存當(dāng)中,就是顯存到內(nèi)存的操作
//GL_LUMINANCE,pixel_w,pixel_h 這個就表示已灰度圖的形式存放的,傳入寬高
glTexImage2D(GL_TEXTURE_2D,//創(chuàng)建為了
 0, //細(xì)節(jié)顯示 0默認(rèn) 是拉遠(yuǎn)拉近攝像機(jī)相關(guān)的顯示
 GL_LUMINANCE,//gpu顯卡內(nèi)部的格式,就是創(chuàng)建的材質(zhì)是存放到顯卡當(dāng)中,這是灰度圖
 pixel_w,pixel_h,
 0,
 GL_LUMINANCE, 數(shù)據(jù)格式,內(nèi)存到顯存的格式,但是無法轉(zhuǎn)換因此要一致
 GL_UNSIGNED_BYTE,//單個像素的存放格式
 plane[0])
 //因為創(chuàng)建紋理有很大的開銷,因此提供了一個修改紋理的函數(shù)
 glTexSubImage2D()  修改紋理  存在偏移值的變量就是表示從當(dāng)前的紋理當(dāng)中只取一部分

glUniform1i(textureUniformY, 0);材質(zhì)設(shè)完之后與shaeder相關(guān)聯(lián),通過uniform變量出入到材質(zhì)0層
glDrawArrays(GL_TRINGLE_STRIP,0,4)//繪制矩形,四個頂點(diǎn)

顯示播放整體流程分析

重載QOpenGLWidget的三個函數(shù)

//重載那三個函數(shù)

//刷新初始化

void paintGL();//具體繪制在這里面實現(xiàn)

//初始化gl

void initializeGL();//初始化

//窗口大小變化

void resizeGL(int width,int height);//當(dāng)窗口發(fā)生變化的時候調(diào)用,這個函數(shù)

initializeGL 在OPenGL創(chuàng)建的時候就會調(diào)用
初始化OpenGL函數(shù)
	initializeOpenGLFunctions()
調(diào)用著色器program添加shader代碼
QGLShaderProgram.addShaderFromSourceCode(QGLShader::Fragment,tString);
QGLShaderProgram.addShaderFromSourceCode(QGLShader::Vertex,vString);
	//QGLShader::Fragment  紋理材質(zhì)類型   tString,vString常量串是Shader具體源代碼
	//這個addShader還可以從文件獲取 Fragment是fsh文件,Vertex是vsh文件
	
//給shader綁定屬性 給頂點(diǎn)shader的attribute賦值,A_VER、T_VER這個只是標(biāo)記作用
	program.bindAttributeLocation("vertexIn", A_VER);
	program.bindAttributeLocation("textureIn",T_VER);
	
//編譯,綁定shader
	program.link();
	program.bind();
	
//定義頂點(diǎn)和材質(zhì)紋理的坐標(biāo)
	static const GLfloat ver[] = {}
	static const GLfloat tex[] = {}

//將頂點(diǎn)和材質(zhì)紋理的坐標(biāo)設(shè)置到shader當(dāng)中去,A_VER、T_VER就是之前賦值屬性的時候綁定的flag
	glVertexAttribPointer(A_VER,2,GL_FLOAT,0,0,ver);
	glEnableVertexAttribArray(A_VER);
	glVertexAttribPointer(T_VER,2, GL_FLOAT, 0,0,tex);
	glEnableVertexAttribArray(T_VER);

//從shader當(dāng)中獲取uniform sampler2D的位置,之后好傳入
	unis[0] = program.uniformLocation("tex_y");
    unis[1] = program.uniformLocation("tex_u");
    unis[2] = program.uniformLocation("tex_v");
	
//創(chuàng)建材質(zhì),并綁定類型,屬性及創(chuàng)建空間,對yuv都進(jìn)行操作,注意uv的大小變化
	glGenTextures(3,texs);
	//Y
    glBindTexture(GL_TEXTURE_2D, texs[0]);//綁定2D
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
	glTexImage2D(GL_TEXTURE_2D,0,GL_RED,width,height,0,GL_RED,GL_UNSIGNED_BYTE,0);//創(chuàng)建材質(zhì)顯卡的空間 ,與內(nèi)存的空間是不一樣的
	//width/2 height/2根據(jù)yuv420的特性來的 uv是y的四分之一
    //U
    glBindTexture(GL_TEXTURE_2D, texs[1]);//綁定2D
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,width/2,height/2,0,GL_RED,GL_UNSIGNED_BYTE,0);//創(chuàng)建材質(zhì)顯卡的空間 ,與內(nèi)存的空間是不一樣的
    //V
    glBindTexture(GL_TEXTURE_2D, texs[2]);//綁定2D
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,width/2,height/2,0,GL_RED,GL_UNSIGNED_BYTE,0);//創(chuàng)建材質(zhì)顯卡的空間 ,與內(nèi)存的空間是不一樣的

//分配材質(zhì)的內(nèi)存空間
    datas[0] = new unsigned char[width*height];
    datas[1] = new unsigned char[width*height/4];
    datas[2] = new unsigned char[width*height/4];
	
//讀取文件
	fp = fopen("output240X128.yuv", "rb");
    if(!fp)
    {
        qDebug() << "fopen error";
    }

//啟動定時器,綁定到OPenGL的update()函數(shù)調(diào)用繪畫函數(shù)
    QTimer *ti = new QTimer(this);
    connect(ti, SIGNAL(timeout()), this, SLOT(update()));//定時器刷新到update()里面取
    ti->start(40);
	
paintGL  繪畫時調(diào)用
//讀取幀數(shù)據(jù),存放到分配材質(zhì)的內(nèi)存空間
    fread(datas[0],1,width*height, fp);
    fread(datas[1], 1, width*height/4, fp);
    fread(datas[2], 1, width*height/4, fp);
	
//在顯卡中創(chuàng)建材質(zhì)   并綁定到了0層渲染材質(zhì)
    glActiveTexture(GL_TEXTURE0);//激活第0層
    glBindTexture(GL_TEXTURE_2D, texs[0]);//把0層綁定Y材質(zhì)
//修改材質(zhì)(復(fù)制內(nèi)存內(nèi)存)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, datas[0]);
//與shader uni變量關(guān)聯(lián)起來
    glUniform1i(unis[0], 0);
	
	重復(fù)三次
	glActiveTexture(GL_TEXTURE0+1);//激活第1層
    glBindTexture(GL_TEXTURE_2D, texs[1]);//把1層綁定Y材質(zhì)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width/2, height/2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);
    glUniform1i(unis[1], 1);
	
	glActiveTexture(GL_TEXTURE0+2);//激活第0層
    glBindTexture(GL_TEXTURE_2D, texs[2]);//把0層綁定Y材質(zhì)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width/2, height/2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);
    glUniform1i(unis[2], 2);
	
最后繪畫 //畫三角形 從0開始 四個頂點(diǎn),
	 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//畫三角形 從0開始 四個頂點(diǎn),

視頻播放實踐
拿到output240X128.yuv也可以使用命令制作ffmpeg -i 1.mp4 -t 10 -s 240x128 -pix_fmt yuv420p out240x128.yuv

注意幾點(diǎn)
控件這里

qt如何使用音視頻,ffmpeg,qt,音視頻

qt工程文件.pro文件
需添加
QT += opengl
QT += openglextensions

代碼

XVideoWidget.h文件

#ifndef XVIDEOWIDGET_H
#define XVIDEOWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QGLShaderProgram>
/*
 * //引入這個需要在pro文件添加模塊
 * QT += opengl
 * QT += openglextensions
*/

class XVideoWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    //注意Q_OBJECT這個變量如果沒有添加進(jìn)來則槽函數(shù)無法調(diào)用
    Q_OBJECT

public:
    XVideoWidget(QWidget *parent);
    ~XVideoWidget();
    //從shader的yuv變量地址
    GLuint unis[3] = {0};
    //opengl的texture地址
    GLuint texs[3] = {0};

    //材質(zhì)的內(nèi)存空間
    unsigned char *datas[3] = {0};

    //寬高度
    int width = 240;
    int height = 128;
protected:
     //重載那三個函數(shù)
    //刷新初始化
    void paintGL();//具體繪制在這里面實現(xiàn)

    //初始化gl
    void initializeGL();//初始化

    //窗口大小變化
    void resizeGL(int width,int height);//當(dāng)窗口發(fā)生變化的時候調(diào)用,這個函數(shù)


private:
    QGLShaderProgram program;

};

#endif // XVIDEOWIDGET_H

XVideoWidget.cpp文件

#include "XVideoWidget.h"
#include <QDebug>
#include <QTimer>

FILE *fp = NULL;

//定義一個宏表示數(shù)組
#define A_VER 3
#define T_VER 4
//自動加雙引號 定義常量串都可以使用
#define GET_STR(x) #x
//頂點(diǎn)著色器的shader代碼
const char *vString = GET_STR(
    attribute vec4 vertexIn;
    attribute vec2 textureIn;
    varying vec2 textureOut;//varying頂點(diǎn)和片元shader共享變量
    void main(void)
    {
        gl_Position = vertexIn;//傳入的頂點(diǎn)坐標(biāo)記錄
        textureOut = textureIn;//傳入的材質(zhì)坐標(biāo)保存到textureOut,從而傳出去了
    }
);
//片元著色器的shader代碼
const char *tString = GET_STR(
    varying vec2 textureOut;//剛剛頂點(diǎn)著色器算出來的坐標(biāo)  共享的
    uniform sampler2D tex_y;//uniform是外部傳入的變量
    uniform sampler2D tex_u;//sampler2D是一個2d圖像
    uniform sampler2D tex_v;
    void main(void)
    {
    //420P是平面存儲的,最后都是要轉(zhuǎn)換為每個像素都是有yuv再方便轉(zhuǎn)換
    //用的是灰度圖的形式存儲的
    //如安裝那邊硬解碼出來的都是yuv420sp,uv是打包存在一起的,則不能使用這套shader代碼了,要增加透明度存儲方式。
        vec3 yuv;
        vec3 rgb;
        //根據(jù)那個坐標(biāo)把材質(zhì)坐標(biāo)計算出來
        //傳入材質(zhì),和坐標(biāo)   返回材質(zhì)當(dāng)中的顏色rgb,但是用灰度圖存儲的,都是一樣的。
        //三個材質(zhì)就可以拼出一個yuv的數(shù)據(jù)
        yuv.x = texture2D(tex_y, textureOut).r;//獲取材質(zhì)當(dāng)中的顏色
        yuv.y = texture2D(tex_u, textureOut).r - 0.5;//四舍五入
        yuv.z = texture2D(tex_v, textureOut).r - 0.5;
        //轉(zhuǎn)換公式
        rgb = mat3(1.0, 1.0, 1.0,
            0.0, -0.39465, 2.03211,
            1.13983, -0.58060, 0.0) * yuv;
        gl_FragColor = vec4(rgb, 1.0);//轉(zhuǎn)換成顯示的顏色,再設(shè)置一下
    }

);
XVideoWidget::XVideoWidget(QWidget *parent)
    :QOpenGLWidget(parent)//初始化列表調(diào)用父類構(gòu)造方法調(diào)用paint畫出OpenGLWidget
{

    int a = 1;
}
XVideoWidget::~XVideoWidget()
{

}
//刷新初始化,每次移動都會調(diào)用一次,進(jìn)行刷新
void XVideoWidget::paintGL()
{
    if(feof(fp))
    {
     fseek(fp, 0, SEEK_SET);
    }
    fread(datas[0],1,width*height, fp);
    fread(datas[1], 1, width*height/4, fp);
    fread(datas[2], 1, width*height/4, fp);

    //在顯卡中創(chuàng)建材質(zhì)   并綁定到了0層渲染材質(zhì)
    glActiveTexture(GL_TEXTURE0);//激活第0層
    glBindTexture(GL_TEXTURE_2D, texs[0]);//把0層綁定Y材質(zhì)
    //修改材質(zhì)(復(fù)制內(nèi)存內(nèi)存)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, datas[0]);
    //與shader uni變量關(guān)聯(lián)起來
    glUniform1i(unis[0], 0);

    glActiveTexture(GL_TEXTURE0+1);//激活第1層
    glBindTexture(GL_TEXTURE_2D, texs[1]);//把1層綁定Y材質(zhì)
    //修改材質(zhì)(復(fù)制內(nèi)存內(nèi)存)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width/2, height/2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);
    //與shader uni變量關(guān)聯(lián)起來
    glUniform1i(unis[1], 1);

    glActiveTexture(GL_TEXTURE0+2);//激活第0層
    glBindTexture(GL_TEXTURE_2D, texs[2]);//把0層綁定Y材質(zhì)
    //修改材質(zhì)(復(fù)制內(nèi)存內(nèi)存)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width/2, height/2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);
    //與shader uni變量關(guān)聯(lián)起來
    glUniform1i(unis[2], 2);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//畫三角形 從0開始 四個頂點(diǎn),

    qDebug() << "paintGL";
}

//初始化gl
void XVideoWidget::initializeGL()
{
    qDebug() << "initializeGL";

    //初始化 opengl(QOpenGLFunctions繼承過來的函數(shù))
    initializeOpenGLFunctions();

    //program(opengl和qt都提供了)加載shader腳本文件 頂點(diǎn)shader 片元shader
    // qt 提供的 QGLShaderProgram
    qDebug() << "addShaderFromSourceCode :" <<program.addShaderFromSourceCode(QGLShader::Fragment,tString);//在源代碼中添加好一些,從文件怕有泄露
    qDebug() << "addShaderFromSourceCode :" << program.addShaderFromSourceCode(QGLShader::Vertex,vString);

    //設(shè)置頂點(diǎn)坐標(biāo)的變量
    program.bindAttributeLocation("vertexIn", A_VER);//這個vertexIn變量對應(yīng)的本地位置 vertexIn是頂點(diǎn)shader定義的 3的位置

    //材質(zhì)坐標(biāo)
    program.bindAttributeLocation("textureIn",T_VER);//下標(biāo)四,等下往4的位置存

    //編譯shader
    qDebug() << "program.link():" << program.link();
    //綁定shader
    qDebug() << "program.link():" << program.bind();

    //傳遞頂點(diǎn)和材質(zhì)坐標(biāo),
    //這個坐標(biāo)是在這個函數(shù)中時候,之后draw的時候還要使用的,只傳入二維
    static const GLfloat ver[] = {
        -1.0f,-1.0f,
        1.0f,-1.0f,
        -1.0f, 1.0f,
        1.0f,1.0f
    };
    static const GLfloat tex[] = {
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f
    };

    //將坐標(biāo)寫入GL當(dāng)中
    glVertexAttribPointer(A_VER,//索引地址
                          2,//表示一點(diǎn)頂點(diǎn)幾個元素,
                          GL_FLOAT,//存放的類型,浮點(diǎn)數(shù)
                          0,
                          0,
                          ver //頂點(diǎn)地址
                          );
    //頂點(diǎn)坐標(biāo)生效
    glEnableVertexAttribArray(A_VER);

    //材質(zhì)  就是shader準(zhǔn)備數(shù)據(jù)
    glVertexAttribPointer(T_VER,2, GL_FLOAT, 0,0,tex);
    glEnableVertexAttribArray(T_VER);

    //從shader當(dāng)中獲取材質(zhì)
    unis[0] = program.uniformLocation("tex_y");
    unis[1] = program.uniformLocation("tex_u");
    unis[2] = program.uniformLocation("tex_v");

    //創(chuàng)建材質(zhì)
    glGenTextures(3,texs);//創(chuàng)建三個對象
    //分別對每個材質(zhì)進(jìn)行設(shè)置

    //Y
    glBindTexture(GL_TEXTURE_2D, texs[0]);//綁定2D
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,width,height,0,GL_RED,GL_UNSIGNED_BYTE,0);//創(chuàng)建材質(zhì)顯卡的空間 ,與內(nèi)存的空間是不一樣的

    //width/2 height/2根據(jù)yuv420的特性來的 uv是y的四分之一
    //U
    glBindTexture(GL_TEXTURE_2D, texs[1]);//綁定2D
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,width/2,height/2,0,GL_RED,GL_UNSIGNED_BYTE,0);//創(chuàng)建材質(zhì)顯卡的空間 ,與內(nèi)存的空間是不一樣的

    //V
    glBindTexture(GL_TEXTURE_2D, texs[2]);//綁定2D
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//設(shè)置屬性  放大 線性差值的屬性
    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,width/2,height/2,0,GL_RED,GL_UNSIGNED_BYTE,0);//創(chuàng)建材質(zhì)顯卡的空間 ,與內(nèi)存的空間是不一樣的

    //分配材質(zhì)的內(nèi)存空間
    datas[0] = new unsigned char[width*height];
    datas[1] = new unsigned char[width*height/4];
    datas[2] = new unsigned char[width*height/4];

    //讀取材質(zhì)并顯示
    //再通過opengl接口,實現(xiàn)內(nèi)存空間和顯卡空間的轉(zhuǎn)換
    fp = fopen("output240X128.yuv", "rb");
    if(!fp)
    {
        qDebug() << "fopen error";
    }

    //啟動定時器
    QTimer *ti = new QTimer(this);
    connect(ti, SIGNAL(timeout()), this, SLOT(update()));//定時器刷新到update()里面取
    ti->start(40);
}

//窗口大小變化
void XVideoWidget::resizeGL(int width,int height)
{
    qDebug() << "resizeGL width = " << width << "  height = " << height;
}

源碼:Git地址

內(nèi)容參考來自夏曹俊老師的ffmpeg和QT開發(fā)

原文?FFMpeg-3、基于QT實現(xiàn)音視頻播放顯示_雷神 博客 opengl_賣酒的小碼農(nóng)的博客-CSDN博客

?

★文末名片可以免費(fèi)領(lǐng)取音視頻開發(fā)學(xué)習(xí)資料,內(nèi)容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音視頻學(xué)習(xí)路線圖等等。

見下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓文章來源地址http://www.zghlxwxcb.cn/news/detail-770272.html

到了這里,關(guān)于FFMpeg-3、基于QT實現(xiàn)音視頻播放顯示的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 用Qt開發(fā)的ffmpeg流媒體播放器,支持截圖、錄像,支持音視頻播放,支持本地文件播放、網(wǎng)絡(luò)流播放

    用Qt開發(fā)的ffmpeg流媒體播放器,支持截圖、錄像,支持音視頻播放,支持本地文件播放、網(wǎng)絡(luò)流播放

    本工程qt用的版本是5.8-32位,ffmpeg用的版本是較新的5.1版本。它支持TCP或UDP方式拉取實時流,實時流我采用的是監(jiān)控攝像頭的RTSP流。音頻播放采用的是QAudioOutput,視頻經(jīng)ffmpeg解碼并由YUV轉(zhuǎn)RGB后是在QOpenGLWidget下進(jìn)行渲染顯示。本工程的代碼有注釋,可以通過本博客查看代碼或者

    2024年02月03日
    瀏覽(116)
  • Qt之基于QMediaPlayer的音視頻播放器(支持常見音視頻格式)

    Qt之基于QMediaPlayer的音視頻播放器(支持常見音視頻格式)

    Qt自帶了一個Media Player的例子,如下圖所示: 但是運(yùn)行這個例子機(jī)會發(fā)現(xiàn),連最基本的MP4格式視頻都播放不了。因為QMediaPlayer是個殼(也可以叫框架),依賴本地解碼器,視頻這塊默認(rèn)基本上就播放個MP4,甚至連MP4都不能播放,如果要支持其他格式需要下載k-lite或者LAVFilter

    2024年02月02日
    瀏覽(31)
  • 音視頻開發(fā):ffplay使用ffmpeg濾鏡實現(xiàn)倍速播放

    曾經(jīng)為實現(xiàn)倍速播放使用過ffmpeg,對音頻使用atempo濾鏡即可實現(xiàn)變速不變調(diào)。但是當(dāng)時效果并不是特別好,和soundtouch相比處理后的音質(zhì)有明顯的區(qū)別。最近用新版本的ffmpeg濾鏡重新實現(xiàn)了倍速播放,發(fā)現(xiàn)效果變好,已經(jīng)達(dá)到可接受的程度,所以在此分享具體實現(xiàn)。 ffmpeg倍速

    2024年02月03日
    瀏覽(72)
  • FFmpeg 播放器實現(xiàn)音視頻同步的三種方式

    FFmpeg 播放器實現(xiàn)音視頻同步的三種方式

    我們基于 FFmpeg 利用 OpenGL ES 和 OpenSL ES 分別實現(xiàn)了對解碼后視頻和音頻的渲染,本文將實現(xiàn)播放器的最后一個重要功能:音視頻同步。 老人們經(jīng)常說, 播放器對音頻和視頻的播放沒有絕對的靜態(tài)的同步,只有相對的動態(tài)的同步,實際上音視頻同步就是一個“你追我趕”的過

    2024年02月06日
    瀏覽(29)
  • 項目實戰(zhàn)——Qt實現(xiàn)FFmpeg音視頻轉(zhuǎn)碼器

    項目實戰(zhàn)——Qt實現(xiàn)FFmpeg音視頻轉(zhuǎn)碼器

    本文記錄使用 Qt 實現(xiàn) FFmepg 音視頻轉(zhuǎn)碼器項目的開發(fā)過程。 1、首先創(chuàng)建一個 Qt 項目,選擇 MSVC2017 32bit 作為其編譯器 2、將 FFmpeg 相關(guān)庫及源文件拷貝到當(dāng)前目錄下 3、注釋 prepare_app_arguments 函數(shù)(這里方便后面我們運(yùn)行時可以指定相應(yīng)的轉(zhuǎn)碼參數(shù)) 4、將所需的一些 dll 動態(tài)庫

    2024年01月23日
    瀏覽(27)
  • opencv+ffmpeg+QOpenGLWidget開發(fā)的音視頻播放器demo

    opencv+ffmpeg+QOpenGLWidget開發(fā)的音視頻播放器demo

    ????本篇文檔的demo包含了 1.使用OpenCV對圖像進(jìn)行處理,對圖像進(jìn)行置灰,旋轉(zhuǎn),摳圖,高斯模糊,中值濾波,部分區(qū)域清除置黑,背景移除,邊緣檢測等操作;2.單純使用opencv播放顯示視頻;3.使用opencv和openGL播放顯示視頻;4.在ffmpeg解碼后,使用opencv顯示視頻,并支持對視

    2024年02月12日
    瀏覽(36)
  • 使用Qt進(jìn)行音視頻播放

    使用Qt進(jìn)行音視頻播放

    ??Qt對音視頻的播放和控制,相機(jī)拍照,收音機(jī)等多媒體應(yīng)用提供了強(qiáng)大的支持。Qt5使用了全新的Qt Multimedia模塊來實現(xiàn)多媒體應(yīng)用,而原來Qt4中用于實現(xiàn)多媒體功能的Phonon模塊已經(jīng)被移除。 ??新的Qt Multimedia模塊提供了豐富的接口,使讀者可以輕松地使用平臺的多媒體功

    2024年02月03日
    瀏覽(21)
  • Qt音視頻開發(fā)38-ffmpeg視頻暫停錄制的設(shè)計

    Qt音視頻開發(fā)38-ffmpeg視頻暫停錄制的設(shè)計

    基本上各種播放器提供的錄制視頻接口,都是只有開始錄制和結(jié)束錄制兩個,當(dāng)然一般用的最多的也是這兩個接口,但是實際使用過程中,還有一種可能需要中途暫停錄制,暫停以后再次繼續(xù)錄制,將中間部分視頻不需要錄制,跳過這部分不需要的視頻,而且錄制的視頻文件

    2023年04月20日
    瀏覽(25)
  • Qt音視頻開發(fā)40-ffmpeg采集桌面并錄制

    之前用ffmpeg打通了各種視頻文件和視頻流以及本地攝像頭設(shè)備的采集,近期有個客戶需求要求將整個桌面屏幕采集下來,并可以錄制保存成MP4文件,以前也遇到過類似的需求,由于沒有搞過,也沒有精力去摸索和測試,所以也就一直耽擱著,近期剛好這個需求又來了,定下心

    2023年04月25日
    瀏覽(21)
  • 瀏覽器網(wǎng)頁內(nèi)嵌Qt-C++音視頻播放器的實現(xiàn),支持軟硬解碼,支持音頻,支持錄像截圖,支持多路播放等,提供源碼工程下載

    瀏覽器網(wǎng)頁內(nèi)嵌Qt-C++音視頻播放器的實現(xiàn),支持軟硬解碼,支持音頻,支持錄像截圖,支持多路播放等,提供源碼工程下載

    ????在瀏覽器中實現(xiàn)播放RTSP實時視頻流,?體上有如下?個?案: ?案一:瀏覽器插件?案 ActiveX、NPAPI、PPAPI ????ActiveX插件適用于IE瀏覽器,NPAPI與PPAPI插件適用于谷歌瀏覽器,不過這些插件都已經(jīng)不被瀏覽器所支持。 ?案二:先轉(zhuǎn)碼再轉(zhuǎn)流?案 ?????作原理是架設(shè)一

    2024年01月17日
    瀏覽(100)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包