SylixOS中視頻播放的實現

1. 相關名詞解釋

1.1      什麼是YUV編碼

YUV主要用於優化彩色視頻信號的傳輸,使其向後相容老式黑白電視。與RGB視頻信號傳輸相比,它最大的優勢在於只需佔用極少的頻寬(RGB要求三個獨立的視頻信號同時傳輸)。其中「Y」表示明亮度,也就是灰階值;而「U」和「V」表示的則是色度,做用是描述影像色彩及飽和度,用於指定像素的顏色。「亮度」是透過RGB輸入信號來創建的,方法是將RGB信號的特定部分疊加到一塊兒。「色度」則定義了顏色的兩個方面─色調與飽和度,分別用Cr和Cb來表示。其中,Cr反映了RGB輸入信號紅色部分與RGB信號亮度值之間的差別。而Cb反映的是RGB輸入信號藍色部分與RGB信號亮度值之間的差別。架構

採用YUV色彩空間的重要性是它的亮度信號Y和色度信號U、V是分離的。若是隻有Y信號份量而沒有U、V份量,那麼這樣表示的圖像就是黑白灰度圖像。彩色電視採用YUV空間正是爲了用亮度信號Y解決彩色電視機與黑白電視機的兼容問題,使黑白電視機也能接收彩色電視信號。函數

 

1.2      什麼是YUV420格式

YUV420 格式即YUV 4:2:0格式。4:2:0並不意味着只有Y、Cb而沒有Cr份量。它指得是對每行掃描線來講,只有一種色度份量以2:1的抽樣率存儲。相鄰的掃描行存儲不一樣的色度份量,也就是說,若是一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。對每一個色度份量來講,水平方向和豎直方向的抽樣率都是2:1,因此能夠說色度的抽樣率是4:1。對非壓縮的8比特量化的視頻來講,每一個由2*2個2行2列相鄰的像素組成的宏像素須要佔用6字節內存。性能

2. 視頻播放的實現

2.1      讀取YUV420格式幀

本文使用的YUV420格式視頻分辨率爲:x86架構下SylixOS系統的默認的分辨率640*480,每秒的幀數爲25幀。優化

因此視頻的每一幀寬度爲640,高度爲480,共640*480個像素點。在YUV420格式中,一個像素點對應一個Y,一個2*2的小方塊對應一個U和V。能夠準確的計算出一幀YUV420圖像大小爲:編碼

Y+U+Vspa

其中:視頻

Y = 640(width) * 480(height);接口

U = Y / 4;內存

V = Y / 4;get

則一幀圖像的總大小爲:width * height * 3/2 ,單位是字節。

 

讀入函數如程序清單2.1所示:

 

程序清單2.1 讀入一幀YUV圖像

#define nWidth     (640)                     /*  幀寬度                    */

#define nHeight    (480)                     /*  幀高度                    */

#define FrameSize  (nWidth*nHeight*3/2)      /*  幀大小                    */

 

fread(pBuf, 1, FrameSize, fp);               /*  讀入一幀YUV               */

 

2.2      顯示一幀畫面

要將每一幀畫面顯示到屏幕上,須要打開系統的framebuffer設備,將framebuffer物理內存映射到用戶空間,並在對應區域寫入顏色值,對應的顏色會自動在屏幕上顯示。只要將一幀全部的像素點顏色寫入對應區域,完整的一幀畫面就會在屏幕上顯示。

源視頻幀數爲每秒25幀,即每一幀間隔時間爲0.04秒,爲了保證播放的流暢度,加入定時器控制顯示幀間隔。

顯示一幀的代碼實現如程序清單2.2 所示:

 

程序清單2.2 顯示一幀YUV圖像

#define FrameInterval   (40000)              /*  每幀間隔時間,單位微秒       */

 

gettimeofday(&start,NULL);

for (j = 0; j< nHeight;j++) {

    for (i = 0;i < nWidth;i++) {

        Color = pointXY[j][i][iPlayFrame];

 

        draw_pixel(pframebuffer, &scr_info, &var_info, i, j, Color);

    }

}                                            /*  整個循環爲一幀畫面的輸出     */

 

do {

    gettimeofday(&end,NULL);

 

    time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);

}while(time_use <= FrameInterval);           /*  控制幀間隔時間              */

 

 

2.3      將YUV420格式幀轉換爲RGB888格式幀

SylixOS系統提供接口所接受的顏色信息格式爲RGB格式,形如」#FF0000」爲紅色的顏色值。

須要將讀入的YUV420信息轉碼爲RGB信息,RGB與YUV的變換公式如圖2.3所示:

                                                      

圖2.3  RGB與YUV變換公式

 

RGB 也能夠直接從YUV (256級別) 計算:

R = Y + 1.402 (Cr-128)

G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)

B = Y + 1.772 (Cb-128)

 

可是直接計算涉及浮點運算,影響轉碼效率,因此利用空間換時間思路,以查找表來替代轉換過程當中的一些計算。

查表法轉換的實現函數如程序清單2.4所示,因爲表數據較多,因此未列出具體的表信息。

 

程序清單2.4 轉碼一幀YUV圖像

for (int i = 0;i < height;i++){

    for (int j = 0;j < width;j++){

    yIdx = i * width + j;

    vIdx = (i/2) * (width/2) + (j/2);

    uIdx = vIdx;

 

    rdif = Table_fv1[vData[vIdx]];

    invgdif = Table_fu1[uData[uIdx]] + Table_fv2[vData[vIdx]];

    bdif = Table_fu2[uData[uIdx]];

 

    bgr[0] = yData[yIdx] + bdif;       //B

    bgr[1] = yData[yIdx] - invgdif;    //G

    bgr[2] = yData[yIdx] + rdif;       //R

 

    for (int e = 0;e < 3; e++)

    {

    if(bgr[e] < 0 || bgr[e] > 255)

        bgr[e] = (bgr[e] < 0)?0:255;

    }

 

    pointXY[i][j][iReadFrame] = rgbColor(bgr[0], bgr[1], bgr[2]);

    for (int k = 0;k < 3;k++){

        idx = (i * width + j) * 3 + k;

        pBGR24[idx] = bgr[k];

        }

    }

}

iReadFrame++;

 

3. 總結

在SylixOS中咱們能夠利用系統提供的framebuffer設備接口,讀入文件,轉碼,寫入內存,從而實現圖像、視頻的播放。

在轉碼過程當中,須要考慮轉碼效率,採起更加節約時間的方式轉換。同時要考慮系統的性能,適當減小幀數以達到視頻更加流暢的目的。

相關文章
相關標籤/搜索