SylixOS中视频播放的实现

来源:互联网 发布:武汉发展前景知乎 编辑:程序博客网 时间:2024/06/05 10:42

1. 相关名词解释

1.1      什么是YUV编码

YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度,也就是灰阶值;而“U”和“V”表示的则是色度,作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用CrCb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。

采用YUV色彩空间的重要性是它的亮度信号Y和色度信号UV是分离的。如果只有Y信号分量而没有UV分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。

 

1.2      什么是YUV420格式

YUV420 格式即YUV 4:2:0格式。4:2:0并不意味着只有YCb而没有Cr分量。它指得是对每行扫描线来说,只有一种色度分量以2:1的抽样率存储。相邻的扫描行存储不同的色度分量,也就是说,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0...以此类推。对每个色度分量来说,水平方向和竖直方向的抽样率都是2:1,所以可以说色度的抽样率是4:1。对非压缩的8比特量化的视频来说,每个由2*222列相邻的像素组成的宏像素需要占用6字节内存。

2. 视频播放的实现

2.1      读取YUV420格式帧

本文使用的YUV420格式视频分辨率为:x86架构下SylixOS系统的默认的分辨率640*480,每秒的帧数为25帧。

所以视频的每一帧宽度为640,高度为480,共640*480个像素点。在YUV420格式中,一个像素点对应一个Y,一个2*2的小方块对应一个UV。可以准确的计算出一帧YUV420图像大小为:

Y+U+V

其中:

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

U = Y / 4;

V = Y / 4;

则一帧图像的总大小为: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信息,RGBYUV的变换公式如图2.3所示:

blob.png

2.3  RGBYUV变换公式

 

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设备接口,读入文件,转码,写入内存,从而实现图像、视频的播放。

在转码过程中,需要考虑转码效率,采取更加节约时间的方式转换。同时要考虑系统的性能,适当减少帧数以达到视频更加流畅的目的。

 

 


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 起泡酒开瓶 香槟与起泡酒 起泡酒的酿造工艺 肯爱起泡酒 起泡酒进口报关 起泡酒作用 起泡酒的好处 威龙起泡酒价格 起泡酒分类 起泡酒 牌子 雷司令起泡酒 起泡酒口感 银九起泡酒 起泡酒级别 加州起泡酒 起泡酒颜色 雷司令气泡酒 金殿起泡酒 起泡酒等级 喝起泡酒用什么杯子 起泡酒 怎么喝 张裕 起泡酒 葡萄酒起泡 起泡酒后劲大吗 起泡酒酿造 malvasia起泡酒 菲斯奈特起泡酒 什么牌子的起泡酒好 什么牌子的起泡酒好喝 什么是无醇起泡酒 马天尼粉红起泡酒 不含酒精的起泡酒 气泡音是什么 气泡音毁嗓子 正确与错误气泡音示范 什么是气泡音 怎么发气泡音 气泡音简单教学 气泡音怎么练习 如何练习气泡音 气泡音有什么用