直播系统开发之视音频数据处理入门:RGB处理(一)

tech2026-09-29  1

从这篇文章开始打算写6篇文章分别记录上述6种不同类型的视音频数据的处理方法。本文首先记录第一部分即RGB/YUV视频像素数据的处理方法。视频像素数据在视频播放器的解码流程中的位置如下图所示。

本文分别介绍如下几个RGB/YUV视频像素数据处理函数: 分离YUV420P像素数据中的Y、U、V分量 分离YUV444P像素数据中的Y、U、V分量 将YUV420P像素数据去掉颜色(变成灰度图) 将YUV420P像素数据的亮度减半 将YUV420P像素数据的周围加上边框 生成YUV420P格式的灰阶测试图 计算两个YUV420P像素数据的PSNR 分离RGB24像素数据中的R、G、B分量 将RGB24格式像素数据封装为BMP图像 将RGB24格式像素数据转换为YUV420P格式像素数据 生成RGB24格式的彩条测试图

本文中的RGB/YUV文件需要使用RGB/YUV播放器才能查看。YUV播放器种类比较多,例如YUV Player Deluxe,或者开源播放器(参考文章《修改了一个YUV/RGB播放器》)等。

 

 

函数列表

 

(1) 分离YUV420P像素数据中的Y、U、V分量

本程序中的函数可以将YUV420P数据中的Y、U、V三个分量分离开来并保存成三个文件。函数的代码如下所示。

 

/**

* Split Y, U, V planes in YUV420P file.

* @param url Location of Input YUV file.

* @param w Width of Input YUV file.

* @param h Height of Input YUV file.

* @param num Number of frames to process.

*

*/

int simplest_yuv420_split(char *url, int w, int h,int num){

FILE *fp=fopen(url,"rb+");

FILE *fp1=fopen("output_420_y.y","wb+");

FILE *fp2=fopen("output_420_u.y","wb+");

FILE *fp3=fopen("output_420_v.y","wb+");

 

unsigned char *pic=(unsigned char *)malloc(w*h*3/2);

 

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

 

fread(pic,1,w*h*3/2,fp);

//Y

fwrite(pic,1,w*h,fp1);

//U

fwrite(pic+w*h,1,w*h/4,fp2);

//V

fwrite(pic+w*h*5/4,1,w*h/4,fp3);

}

 

free(pic);

fclose(fp);

fclose(fp1);

fclose(fp2);

fclose(fp3);

 

return 0;

}

调用上面函数的方法如下所示。

simplest_yuv420_split("lena_256x256_yuv420p.yuv",256,256,1);

从代码可以看出,如果视频帧的宽和高分别为w和h,那么一帧YUV420P像素数据一共占用w*h*3/2 Byte的数据。其中前w*h Byte存储Y,接着的w*h*1/4 Byte存储U,最后w*h*1/4 Byte存储V。上述调用函数的代码运行后,将会把一张分辨率为256x256的名称为lena_256x256_yuv420p.yuv的YUV420P格式的像素数据文件分离成为三个文件:

output_420_y.y:纯Y数据,分辨率为256x256。

output_420_u.y:纯U数据,分辨率为128x128。

output_420_v.y:纯V数据,分辨率为128x128。

注:本文中像素的采样位数一律为8bit。由于1Byte=8bit,所以一个像素的一个分量的采样值占用1Byte。

 

程序输入的原图如下所示。

lena_256x256_yuv420p.yuv

程序输出的三个文件的截图如下图所示。在这里需要注意输出的U、V分量在YUV播放器中也是当做Y分量进行播放的。

 

output_420_y.y

           

output_420_u.y和output_420_v.y

 

(2)分离YUV444P像素数据中的Y、U、V分量

本程序中的函数可以将YUV444P数据中的Y、U、V三个分量分离开来并保存成三个文件。函数的代码如下所示。

 

/**

* Split Y, U, V planes in YUV444P file.

* @param url Location of YUV file.

* @param w Width of Input YUV file.

* @param h Height of Input YUV file.

* @param num Number of frames to process.

*

*/

int simplest_yuv444_split(char *url, int w, int h,int num){

FILE *fp=fopen(url,"rb+");

FILE *fp1=fopen("output_444_y.y","wb+");

FILE *fp2=fopen("output_444_u.y","wb+");

FILE *fp3=fopen("output_444_v.y","wb+");

unsigned char *pic=(unsigned char *)malloc(w*h*3);

 

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

fread(pic,1,w*h*3,fp);

//Y

fwrite(pic,1,w*h,fp1);

//U

fwrite(pic+w*h,1,w*h,fp2);

//V

fwrite(pic+w*h*2,1,w*h,fp3);

}

 

free(pic);

fclose(fp);

fclose(fp1);

fclose(fp2);

fclose(fp3);

 

return 0;

}

调用上面函数的方法如下所示。

simplest_yuv444_split("lena_256x256_yuv444p.yuv",256,256,1);

从代码可以看出,如果视频帧的宽和高分别为w和h,那么一帧YUV444P像素数据一共占用w*h*3 Byte的数据。其中前w*h Byte存储Y,接着的w*h Byte存储U,最后w*h Byte存储V。上述调用函数的代码运行后,将会把一张分辨率为256x256的名称为lena_256x256_yuv444p.yuv的YUV444P格式的像素数据文件分离成为三个文件:

output_444_y.y:纯Y数据,分辨率为256x256。 output_444_u.y:纯U数据,分辨率为256x256。 output_444_v.y:纯V数据,分辨率为256x256。

输入的原图如下所示。

输出的三个文件的截图如下图所示。

 

output_444_y.y

 

output_444_u.y

 

output_444_v.y

最新回复(0)