致敬雷神:FFmpeg源代码简单分析:libswscale的sws_getContext()
FFmpeg里面的sws_scale库可以在一个函数里面同时实现:1.图像色彩空间转换;2.分辨率缩放;3.前后图像滤波处理。
libswscale库常用函数有三个:
- sws_getContext():初始化一个SwsContext。
- sws_scale():处理图像数据。
- sws_freeContext():释放一个SwsContext。
sws_getContext()
sws_getContext()的声明位于libswscale\swscale.h;定义位于libswscale\utils.c
从sws_getContext()的定义中可以看出,它首先调用了一个函数sws_alloc_context()用于给SwsContext分配内存。然后将传入的源图像,目标图像的宽高,像素格式,以及标志位分别赋值给该SwsContext相应的字段。最后调用一个函数sws_init_context()完成初始化工作。
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);
参数int srcW, int srcH, enum AVPixelFormat srcFormat定义输入图像信息(宽、高、颜色空间(像素格式))
参数int dstW, int dstH, enum AVPixelFormat dstFormat定义输出图像信息(宽、高、颜色空间(像素格式))
参数int flags选择缩放算法(只有当输入输出图像大小不同时有效)
参数SwsFilter *srcFilter, SwsFilter *dstFilter分别定义输入/输出图像滤波器信息,如果不做前后图像滤波,输入NULL
参数const double *param定义特定缩放算法需要的参数,默认为NULL
函数返回SwsContext结构体,定义了基本变换信息。
应用实例:
sws_getContext(w, h, YV12, w, h, NV12, 0, NULL, NULL, NULL); // YV12->NV12 色彩空间转换
sws_getContext(w, h, YV12, w/2, h/2, YV12, 0, NULL, NULL, NULL); // YV12图像缩小到原图1/4
sws_getContext(w, h, YV12, 2w, 2h, YN12, 0, NULL, NULL, NULL); // YV12图像放大到原图4倍,并转换为NV12结构
sws_scale()
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH,uint8_t *const dst[], const int dstStride[]);
参数struct SwsContext *c为上面sws_getContext函数返回值;
参数const uint8_t *const srcSlice[], const int srcStride[]定义输入图像信息(当前处理区域的每个通道数据指针,每个通道行字节数)
参数int srcSliceY, int srcSliceH,定义在输入图像上处理区域,srcSliceY是起始位置;
(srcSliceH是处理多少行。如果srcSliceY=0,srcSliceH=height,表示一次性处理完整个图像。
这种设置是为了多线程并行,例如可以创建两个线程,第一个线程处理 [0, h/2-1]行,第二个线程处理 [h/2, h-1]行。
并行处理加快速度。)
参数uint8_t *const dst[], const int dstStride[]定义输出图像信息(输出的每个通道数据指针,每个通道行字节数)
sws_freeContext()
void sws_freeContext(struct SwsContext *swsContext);
Libswscale处理数据流程
从图中可以看出,libswscale处理数据有两条最主要的方式:unscaled和scaled。
unscaled用于处理不需要拉伸的像素数据(属于比较特殊的情况),scaled用于处理需要拉伸的像素数据。
Unscaled只需要对图像像素格式进行转换;而Scaled则除了对像素格式进行转换之外,还需要对图像进行缩放。
Scaled方式可以分成以下几个步骤:
- XXX to YUV Converter:首相将数据像素数据转换为8bitYUV格式;
- Horizontal scaler:水平拉伸图像,并且转换为15bitYUV;
- Vertical scaler:垂直拉伸图像;
- Output converter:转换为输出像素格式。