有些时候大家需要一些yuv或者rgb 的 raw data的文件。ffmpeg项目中的libavcodec支持很多格式的raw相互转换,在早期的版本中,使用 img_convert,在新版本中,使用 sws_scale 完成。各种不同的格式在ffmpeg里面被称为 pixel formats,下面贴出来的就是:
PIX_FMT_YUV420P, < Planar YUV 4:2:0 (1 Cr & Cb sample per 2x2 Y samples)\n"
PIX_FMT_YUV422, < Packed pixel, Y0 Cb Y1 Cr \n"
PIX_FMT_RGB24, < Packed pixel, 3 bytes per pixel, RGBRGB...\n"
PIX_FMT_BGR24, < Packed pixel, 3 bytes per pixel, BGRBGR...\n"
PIX_FMT_YUV422P, < Planar YUV 4:2:2 (1 Cr & Cb sample per 2x1 Y samples)\n"
PIX_FMT_YUV444P, < Planar YUV 4:4:4 (1 Cr & Cb sample per 1x1 Y samples)\n"
PIX_FMT_RGBA32, < Packed pixel, 4 bytes per pixel, BGRABGRA..., stored in cpu endianness\n"
PIX_FMT_YUV410P, < Planar YUV 4:1:0 (1 Cr & Cb sample per 4x4 Y samples)\n"
PIX_FMT_YUV411P, < Planar YUV 4:1:1 (1 Cr & Cb sample per 4x1 Y samples)\n"
IX_FMT_RGB565, < always stored in cpu endianness \n"
PIX_FMT_RGB555, < always stored in cpu endianness, most significant bit to 1 \n"
PIX_FMT_GRAY8,\n"
PIX_FMT_MONOWHITE, < 0 is white \n"
PIX_FMT_MONOBLACK, < 0 is black \n"
PIX_FMT_PAL8, < 8 bit with RGBA palette \n"
PIX_FMT_YUVJ420P, < Planar YUV 4:2:0 full scale (jpeg)\n"
PIX_FMT_YUVJ422P, < Planar YUV 4:2:2 full scale (jpeg)\n"
PIX_FMT_YUVJ444P, < Planar YUV 4:4:4 full scale (jpeg)\n"
PIX_FMT_UYVY422, < Packed pixel, Cb Y0 Cr Y1 \n"
PIX_FMT_UYVY411, < Packed pixel, Cb Y0 Y1 Cr Y2 Y3\n"
/////////////////////////////////////////////////////////////////
举例来说,
PIX_FMT_YUV444P, < Planar YUV 4:4:4
指的是文件的开始1/3是y分量,中间1/3是u分量,最后1/3是v分量。
PIX_FMT_RGB24, < Packed pixel, 3 bytes per pixel, RGBRGB...\n"
指的是文件内的数据3个byte是一组,始终按照RGB方式排列。
PIX_FMT_RGBA32, < Packed pixel, 4 bytes per pixel, BGRABGRA..., stored in cpu endianness\n"
指的是文件内的数据4个byte是一组,始终按照RGB+alpha byte方式排列,alpha表示透明度。
/////////////////////////////////////////////////////////////////
ffmpeg对于以上所有类型抽象成
typedef struct AVPicture {
uint8_t *data[4];
int linesize[4];
} AVPicture;
该结构体总共表示四个平面,
data[0]表示第一个平面的数据开始地址,
linesize[0]表示第一个平面的每一行有多少个字节。
这样PIX_FMT_YUV444P有三个Planar,最后一个平面空着不用就好了。
AVFrame这个结构体的包含AVPicture,此外,AVFrame还含有其他一些成员数据,比如。是否key_frame、已编码图像数coded_picture_number、是否作为参考帧reference、宏块类型 *mb_type等等,这里就不详细叙述了。
/////////////////////////////////////////////////////////////////
鉴于img_convert在新版中已经不用,所以这里只介绍一下效率更高的。sws_scale。
来看看它的函数定义:
int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
其中src和srcStride定义了输入图像的四个平面的数据起始指针和四个平面中每一行包含的像素的个数。
dst和dstStride是输出变量,定义的是输出图像的四个平面的数据起始指针和四个平面包含的数据的大小。
为什么一个图像有四个平面,可以找一下YUV格式的一些详细介绍就可以明白。
当然,RGB格式是按照紧凑格式进行编码的,因此只有一个平面,也就是说只要设置src[0]就可以,src[1],src[2],src[3]都为NULL。
我们就在设置src[0]和srcStride[0]的地方做文章。
按照一般处理src[0]和srcStride[0]分别设置为起始图像数据的开始和图像每一行的像素个数。
那如果把src[0] 设置为 width * ( height - 1) srcStride[0] = -height 结果会如何呢?是不是就会把图像倒过来呢?
实际确实如此。进行图像倒置的操作尽然如此简单。这样避免了人为再添加一次图像的反转操作,提高了编码的性能。
/////////////////////////////////////////////////////////////////
不发命令行工具了,需要的mail给我.
这里提供一个windows平台下使用ffmpeg的快捷方法,下面这个开发包内直接提供lib给开发人员使用。