前言
由于近期項(xiàng)目用到FFmpeg庫進(jìn)行視頻解碼,涉及到視音頻的一些相關(guān)知識(shí),遂惡補(bǔ)之。
視頻像素?cái)?shù)據(jù)處理
YUV數(shù)據(jù)格式
- YUV數(shù)據(jù)格式簡介
YUV是被歐洲電視系統(tǒng)所采用的一種顏色編碼方法(屬于PAL),是PAL和SECAM模擬彩色電視制式采用的顏色空間。在現(xiàn)代彩色電視系統(tǒng)中,通常采用三管彩色攝影機(jī)或彩色CCD攝影機(jī)進(jìn)行取像,然后把取得的彩色圖像信號(hào)經(jīng)分色、分別放大校正后得到RGB,再經(jīng)過矩陣變換電路得到亮度信號(hào)Y和兩個(gè)色差信號(hào)B-Y(即U)、R-Y(即V),最后發(fā)送端將亮度和色差三個(gè)信號(hào)分別進(jìn)行編碼,用同一信道發(fā)送出去。這種色彩的表示方法就是所謂的YUV色彩空間表示。采用YUV色彩空間的重要性是它的亮度信號(hào)Y和色度信號(hào)U、V是分離的。 - 要點(diǎn)
1.如果視頻幀的寬和高分別為w和h,那么一幀YUV420P像素?cái)?shù)據(jù)一共占用w*h*3/2 Byte的數(shù)據(jù)。其中前w*h Byte存儲(chǔ)Y,接著的w*h*1/4 Byte存儲(chǔ)U,最后w*h*1/4 Byte存儲(chǔ)V。
2.如果視頻幀的寬和高分別為w和h,那么一幀YUV444P像素?cái)?shù)據(jù)一共占用w*h*3 Byte的數(shù)據(jù)。其中前w*h Byte存儲(chǔ)Y,接著的w*h Byte存儲(chǔ)U,最后w*h Byte存儲(chǔ)V。
3.如果想把YUV格式像素?cái)?shù)據(jù)變成灰度圖像,只需要將U、V分量設(shè)置成128即可。這是因?yàn)閁、V是圖像中的經(jīng)過偏置處理的色度分量。色度分量在偏置處理前的取值范圍是-128至127,這時(shí)候的無色對(duì)應(yīng)的是“0”值。經(jīng)過偏置后色度分量取值變成了0至255,因而此時(shí)的無色對(duì)應(yīng)的就是128了。
4.如果打算將圖像的亮度減半,只要將圖像的每個(gè)像素的Y值取出來分別進(jìn)行除以2的工作就可以了。圖像的每個(gè)Y值占用1 Byte,取值范圍是0至255,對(duì)應(yīng)c語言中的unsigned char數(shù)據(jù)類型。
5.PSNR- PSNR簡介
PSNR是“Peak Signal to Noise Ratio”的縮寫,即峰值信噪比,是最基本的視頻質(zhì)量評(píng)價(jià)方法,它具有局限性,一般是用于最大值信號(hào)和背景噪音之間的一個(gè)工程項(xiàng)目。PSNR取值通常情況下都在20-50的范圍內(nèi),取值越高,代表兩張圖像越接近,反映出受損圖像質(zhì)量越好。 - PSNR計(jì)算公式
對(duì)于8bit量化的像素?cái)?shù)據(jù)來說,PSNR的計(jì)算公式如下所示。
PSNR計(jì)算公式
上述公式中mse的計(jì)算公式如下所示。
MSE計(jì)算公式
其中M,N分別為圖像的寬高,xij和yij分別為兩張圖像的每一個(gè)像素值。
- PSNR簡介
RGB數(shù)據(jù)格式
- RGB數(shù)據(jù)格式簡介
RGB色彩模式是工業(yè)界的一種顏色標(biāo)準(zhǔn),是通過對(duì)紅(R)、綠(G)、藍(lán)(B)三個(gè)顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍(lán)三個(gè)通道的顏色,這個(gè)標(biāo)準(zhǔn)幾乎包括了人類視力所能感知的所有顏色,是目前運(yùn)用最廣的顏色系統(tǒng)之一。 - 要點(diǎn)
1.RGB24格式的每個(gè)像素的三個(gè)分量是連續(xù)存儲(chǔ)的。一幀寬高分別為w、h的RGB24圖像一共占用w*h*3 Byte的存儲(chǔ)空間。RGB24格式規(guī)定首先存儲(chǔ)第一個(gè)像素的R、G、B,然后存儲(chǔ)第二個(gè)像素的R、G、B…以此類推。類似于YUV420P的存儲(chǔ)方式稱為Planar方式,而類似于RGB24的存儲(chǔ)方式稱為Packed方式。
2.BMP文件是由BITMAPFILEHEADER、BITMAPINFOHEADER、RGB像素?cái)?shù)據(jù)共3個(gè)部分構(gòu)成,它的結(jié)構(gòu)如下圖所示。
BMP結(jié)構(gòu)圖
其中前兩部分的結(jié)構(gòu)如下所示。
typedef struct tagBITMAPFILEHEADER
{
unsigned short int bfType; //位圖文件的類型,必須為BM
unsigned long bfSize; //文件大小,以字節(jié)為單位
unsigned short int bfReserverd1; //位圖文件保留字,必須為0
unsigned short int bfReserverd2; //位圖文件保留字,必須為0
unsigned long bfbfOffBits; //位圖文件頭到數(shù)據(jù)的偏移量,以字節(jié)為單位
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
long biSize; //該結(jié)構(gòu)大小,字節(jié)為單位
long biWidth; //圖形寬度以象素為單位
long biHeight; //圖形高度以象素為單位
short int biPlanes; //目標(biāo)設(shè)備的級(jí)別,必須為1
short int biBitcount; //顏色深度,每個(gè)象素所需要的位數(shù)
short int biCompression; //位圖的壓縮類型
long biSizeImage; //位圖的大小,以字節(jié)為單位
long biXPelsPermeter; //位圖水平分辨率,每米像素?cái)?shù)
long biYPelsPermeter; //位圖垂直分辨率,每米像素?cái)?shù)
long biClrUsed; //位圖實(shí)際使用的顏色表中的顏色數(shù)
long biClrImportant; //位圖顯示過程中重要的顏色數(shù)
}BITMAPINFOHEADER;
注意:BMP采用的是**小端(Little Endian)存儲(chǔ)方式**。這種存儲(chǔ)方式中“RGB24”格式的像素的分量存儲(chǔ)的先后順序?yàn)锽、G、R。由于RGB24格式存儲(chǔ)的順序是R、G、B,所以需要將“R”和“B”順序作一個(gè)**調(diào)換**再進(jìn)行存儲(chǔ)。
音頻采樣數(shù)據(jù)處理
PCM編碼格式
- PCM編碼格式簡介
PCM脈沖編碼調(diào)制是Pulse Code Modulation的縮寫。脈沖編碼調(diào)制是數(shù)字通信的編碼方式之一。主要過程是將話音、圖像等模擬信號(hào)每隔一定時(shí)間進(jìn)行取樣,使其離散化,同時(shí)將抽樣值按分層單位四舍五入取整量化,同時(shí)將抽樣值按一組二進(jìn)制碼來表示抽樣脈沖的幅值。 - 要點(diǎn)
1.PCM16LE雙聲道數(shù)據(jù)中左聲道和右聲道的采樣值是間隔存儲(chǔ)的。每個(gè)采樣值占用2Byte空間。(16LE為采樣格式。“16”代表采樣位數(shù)是16bit。由于1Byte=8bit,所以一個(gè)聲道的一個(gè)采樣值占用2Byte?!癓E”代表Little Endian,代表2 Byte采樣值的存儲(chǔ)方式為高位存在高地址中。)
2.PCM16LE格式的采樣數(shù)據(jù)的取值范圍是-32768到32767,而PCM8格式的采樣數(shù)據(jù)的取值范圍是0到255。所以PCM16LE轉(zhuǎn)換到PCM8需要經(jīng)過兩個(gè)步驟:第一步是將-32768到32767的16bit有符號(hào)數(shù)值轉(zhuǎn)換為-128到127的8bit有符號(hào)數(shù)值,第二步是將-128到127的8bit有符號(hào)數(shù)值轉(zhuǎn)換為0到255的8bit無符號(hào)數(shù)值。
3.WAVE文件是一種RIFF格式的文件。其基本塊名稱是“WAVE”,其中包含了兩個(gè)子塊“fmt”和“data”。從編程的角度簡單說來就是由WAVE_HEADER、WAVE_FMT、WAVE_DATA、采樣數(shù)據(jù)共4個(gè)部分組成。它的結(jié)構(gòu)如下所示。
WAVE結(jié)構(gòu)圖
其中前三部分的結(jié)構(gòu)如下所示。
typedef struct WAVE_HEADER{
char fccID[4];
unsigned long dwSize;
char fccType[4];
}WAVE_HEADER;
typedef struct WAVE_FMT{
char fccID[4];
unsigned long dwSize;
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short uiBitsPerSample;
}WAVE_FMT;
typedef struct WAVE_DATA{
char fccID[4];
unsigned long dwSize;
}WAVE_DATA;
注意:**WAVE_HEADER**和**WAVE_DATA**中包含了一個(gè)文件長度信息的**dwSize**字段,該字段的值必須在寫入完音頻采樣數(shù)據(jù)之后才能獲得。因此這兩個(gè)結(jié)構(gòu)體最后才寫入WAVE文件中。
視音頻碼流處理
H.264標(biāo)準(zhǔn)
- H.264標(biāo)準(zhǔn)簡介
H.264,同時(shí)也是MPEG-4第十部分,是由ITU-T視頻編碼專家組(VCEG)和ISO/IEC動(dòng)態(tài)圖像專家組(MPEG)聯(lián)合組成的聯(lián)合視頻組(JVT,Joint Video Team)提出的高度壓縮數(shù)字視頻編解碼器標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)通常被稱之為H.264/AVC(或者AVC/H.264或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC)而明確的說明它兩方面的開發(fā)者。
H264標(biāo)準(zhǔn)各主要部分有Access Unit delimiter(訪問單元分割符),SEI(附加增強(qiáng)信息),primary coded picture(基本圖像編碼),Redundant Coded Picture(冗余圖像編碼)。還有Instantaneous Decoding Refresh(IDR,即時(shí)解碼刷新)、Hypothetical Reference Decoder(HRD,假想?yún)⒖冀獯a)、Hypothetical Stream Scheduler(HSS,假想碼流調(diào)度器)。
H.264原始碼流(又稱為“裸流”)是由一個(gè)一個(gè)的NALU組成的。他們的結(jié)構(gòu)如下圖所示。
NALU結(jié)構(gòu)圖
其中每個(gè)NALU之間通過startcode(起始碼)進(jìn)行分隔,起始碼分成兩種:0x000001(3Byte)或者0x00000001(4Byte)。如果NALU對(duì)應(yīng)的Slice為一幀的開始就用0x00000001,否則就用0x000001。
AAC音頻編碼技術(shù)
- AAC音頻編碼技術(shù)簡介
AAC,全稱Advanced Audio Coding,中文名:高級(jí)音頻編碼,是一種專為聲音數(shù)據(jù)設(shè)計(jì)的文件壓縮格式。其出現(xiàn)于1997年,基于MPEG-2的音頻編碼技術(shù)。2000年,MPEG-4標(biāo)準(zhǔn)出現(xiàn)后,AAC重新集成了其特性,加入了SBR技術(shù)和PS技術(shù)。AAC是由Fraunhofer IIS、杜比實(shí)驗(yàn)室、AT&T、Sony等公司共同開發(fā),目的是取代MP3格式。與MP3不同,它采用了全新的算法進(jìn)行編碼,更加高效,具有更高的“性價(jià)比”。利用AAC格式,可使人感覺聲音質(zhì)量沒有明顯降低的前提下,更加小巧。
AAC原始碼流(又稱為“裸流”)是由一個(gè)一個(gè)的ADTS frame組成的。他們的結(jié)構(gòu)如下圖所示。
ADTS frame結(jié)構(gòu)圖
其中每個(gè)ADTS frame之間通過syncword(同步字)進(jìn)行分隔。同步字為0xFFF(二進(jìn)制“111111111111”)。
封裝格式處理
FLV封裝格式
- FLV封裝格式簡介
FLV 是FLASH VIDEO的簡稱,F(xiàn)LV流媒體格式是隨著Flash MX的推出發(fā)展而來的視頻格式。由于它形成的文件極小、加載速度極快,使得網(wǎng)絡(luò)觀看視頻文件成為可能,它的出現(xiàn)有效地解決了視頻文件導(dǎo)入Flash后,使導(dǎo)出的SWF文件體積龐大,不能在網(wǎng)絡(luò)上很好的使用等問題。
FLV封裝格式是由一個(gè)FLV Header文件頭和一個(gè)一個(gè)的Tag組成的。Tag中包含了音頻數(shù)據(jù)以及視頻數(shù)據(jù)。FLV的結(jié)構(gòu)如下圖所示。
FLV封裝格式結(jié)構(gòu)圖
網(wǎng)絡(luò)協(xié)議
UDP/RTP協(xié)議
- MPEG2-TS協(xié)議簡介
MPEG2-TS(Transport Stream“傳輸流”;又稱TS、TP、MPEG-TS 或 M2T)是用于音效、圖像與數(shù)據(jù)的通信協(xié)定,最早應(yīng)用于DVD的實(shí)時(shí)傳送節(jié)目。 - UDP協(xié)議簡介
UDP協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包,是一種無連接的協(xié)議。在OSI模型中,在第四層——傳輸層,處于IP協(xié)議的上一層。UDP有不提供數(shù)據(jù)包分組、組裝和不能對(duì)數(shù)據(jù)包進(jìn)行排序的缺點(diǎn),也就是說,當(dāng)報(bào)文發(fā)送之后,是無法得知其是否安全完整到達(dá)的。UDP用來支持那些需要在計(jì)算機(jī)之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用。包括網(wǎng)絡(luò)視頻會(huì)議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都需要使用UDP協(xié)議。UDP協(xié)議從問世至今已經(jīng)被使用了很多年,雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋,但是即使是在今天UDP仍然不失為一項(xiàng)非常實(shí)用和可行的網(wǎng)絡(luò)傳輸層協(xié)議。 - RTP協(xié)議簡介
實(shí)時(shí)傳輸協(xié)議RTP(Real-time Transport Protocol)是一個(gè)網(wǎng)絡(luò)傳輸協(xié)議,它是由IETF的多媒體傳輸工作小組1996年在RFC 1889中公布的,后在RFC3550中進(jìn)行更新。
RTP協(xié)議詳細(xì)說明了在互聯(lián)網(wǎng)上傳遞音頻和視頻的標(biāo)準(zhǔn)數(shù)據(jù)包格式。它一開始被設(shè)計(jì)為一個(gè)多播協(xié)議,但后來被用在很多單播應(yīng)用中。RTP協(xié)議常用于流媒體系統(tǒng)(配合RTSP協(xié)議),視頻會(huì)議和一鍵通(Push to Talk)系統(tǒng)(配合H.323或SIP),使它成為IP電話產(chǎn)業(yè)的技術(shù)基礎(chǔ)。RTP協(xié)議和RTP控制協(xié)議RTCP一起使用,而且它是建立在用戶數(shù)據(jù)報(bào)協(xié)議上的。RTP廣泛應(yīng)用于流媒體相關(guān)的通訊和娛樂,包括電話、視頻會(huì)議、電視和基于網(wǎng)絡(luò)的一鍵通業(yè)務(wù)(類似對(duì)講機(jī)的通話)。 - 發(fā)送流程
MPEG-TS封裝格式數(shù)據(jù)打包為RTP/UDP協(xié)議然后發(fā)送出去的流程如下圖所示。圖中首先每7個(gè)MPEG-TS Packet打包為一個(gè)RTP,然后每個(gè)RTP再打包為一個(gè)UDP。其中打包RTP的方法就是在MPEG-TS數(shù)據(jù)前面加上RTP Header,而打包RTP的方法就是在RTP數(shù)據(jù)前面加上UDP Header。
發(fā)送流程







