原文链接:https://blog.csdn.net/leixiaohua1020/article/details/44305697
FFmpeg中的图像处理(缩放,YUV/RGB格式转换)类库libswsscale的源代码。libswscale是一个主要用于处理图片像素数据的类库。可以完成图片像素格式的转换,图片的拉伸等工作。有关libswscale的使用可以参考文章:https://blog.csdn.net/leixiaohua1020/article/details/42134965
它的初始化函数为sws_getContext(),它的数据处理函数为sws_scale()。
SwsContext是使用libswscale时候一个贯穿始终的结构体。但是我们在使用FFmpeg的类库进行开发的时候,是无法看到它的内部结构的。在libswscaleswscale.h中只能看到一行定义:struct SwsContext;
它的定义位于libswscaleswscale_internal.h中,(几百行的定义)
sws_getContext()是初始化SwsContext的函数。
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param);
该函数包含以下参数:
srcW:源图像的宽
srcH:源图像的高
srcFormat:源图像的像素格式
dstW:目标图像的宽
dstH:目标图像的高
dstFormat:目标图像的像素格式
flags:设定图像拉伸使用的算法
成功执行的话返回生成的SwsContext,否则返回NULL。
成功执行的话返回生成的SwsContext,否则返回NULL。sws_getContext()的定义位于libswscaleutils.c
从sws_getContext()的定义中可以看出,它首先调用了一个函数sws_alloc_context()用于给SwsContext分配内存。然后将传入的源图像,目标图像的宽高,像素格式,以及标志位分别赋值给该SwsContext相应的字段。最后调用一个函数sws_init_context()完成初始化工作。下面我们分别看一下sws_alloc_context()和sws_init_context()这两个函数。
sws_init_context()除了对SwsContext中的各种变量进行赋值之外,主要按照顺序完成了以下一些工作:
1. 通过sws_rgb2rgb_init()初始化RGB转RGB(或者YUV转YUV)的函数(注意不包含RGB与YUV相互转换的函数)。
2. 通过判断输入输出图像的宽高来判断图像是否需要拉伸。如果图像需要拉伸,那么unscaled变量会被标记为1。
3. 通过sws_setColorspaceDetails()初始化颜色空间。
4. 一些输入参数的检测。例如:如果没有设置图像拉伸方法的话,默认设置为SWS_BICUBIC;如果输入和输出图像的宽高小于等于0的话,也会返回错误信息。
5. 初始化Filter。这一步根据拉伸方法的不同,初始化不同的Filter。
6. 如果flags中设置了“打印信息”选项SWS_PRINT_INFO,则输出信息。
7. 如果不需要拉伸的话,调用ff_get_unscaled_swscale()将特定的像素转换函数的指针赋值给SwsContext中的swscale指针。
8. 如果需要拉伸的话,调用ff_getSwsFunc()将通用的swscale()赋值给SwsContext中的swscale指针(这个地方有点绕,但是确实是这样的)。
1.初始化RGB转RGB(或者YUV转YUV)的函数。注意这部分函数不包含RGB与YUV相互转换的函数。
sws_rgb2rgb_init()
sws_rgb2rgb_init()的定义位于libswscale gb2rgb.c,
从sws_rgb2rgb_init()代码中可以看出,有两个初始化函数:rgb2rgb_init_c()是初始化C语言版本的RGB互转(或者YUV互转)的函数,rgb2rgb_init_x86()则是初始化X86汇编版本的RGB互转的函数。
PS:在libswscale中有一点需要注意:很多的函数名称中包含类似“_c”这样的字符串,代表了该函数是C语言写的。与之对应的还有其它标记,比如“_mmx”,“sse2”等。
C语言版本的RGB互转函数的初始化函数rgb2rgb_init_c(),定义位于libswscale
gb2rgb_template.c,
可以看出rgb2rgb_init_c()执行后,会把C语言版本的图像格式转换函数赋值给系统的函数指针。
rgb24tobgr24_c()完成了RGB24向BGR24格式的转换。函数的定义如下所示。从代码中可以看出,该函数实现了“R”与“B”之间位置的对调,从而完成了这两种格式之间的转换。
rgb24to16_c()完成了RGB24向RGB16像素格式的转换。
yuyvtoyuv422_c()完成了YUYV向YUV422像素格式的转换。
该函数将YUYV像素数据分离成为Y,U,V三个分量的像素数据。其中extract_even_c()用于获取一行像素中序数为偶数的像素,对应提取了YUYV像素格式中的“Y”。extract_odd2_c()用于获取一行像素中序数为奇数的像素,并且把这些像素值再次按照奇偶的不同,存储于两个数组中。对应提取了YUYV像素格式中的“U”和“V”。
rgb2rgb_init_x86()用于初始化基于X86汇编语言的RGB互转的代码。由于对汇编不是很熟,不再作详细分析。
可以看出,rgb2rgb_init_x86()首先调用了av_get_cpu_flags()获取CPU支持的特性,根据特性调用rgb2rgb_init_mmx(),rgb2rgb_init_3dnow(),rgb2rgb_init_mmxext(),rgb2rgb_init_sse2(),rgb2rgb_init_avx()等函数。
2.判断图像是否需要拉伸。
这一步主要通过比较输入图像和输出图像的宽高实现。系统使用一个unscaled变量记录图像是否需要拉伸,如下所示。
unscaled = (srcW == dstW && srcH == dstH);
3.初始化颜色空间。
初始化颜色空间通过函数sws_setColorspaceDetails()完成。sws_setColorspaceDetails()是FFmpeg的一个API函数,它的声明如下所示:
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation);
简单解释一下几个参数的含义:
c:需要设定的SwsContext。
inv_table:描述输出YUV颜色空间的参数表。
srcRange:输入图像的取值范围(“1”代表JPEG标准,取值范围是0-255;“0”代表MPEG标准,取值范围是16-235)。
table:描述输入YUV颜色空间的参数表。
dstRange:输出图像的取值范围。
brightness:未研究。
contrast:未研究。
saturation:未研究。
其他雷神博客也还有,可去看。。。。。