sws_getContext和sws_scale分析

简介: sws_getContext和sws_scale分析
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);


创建转换上下文,参数分析:


flags参数是指选择的转换算法,如果没有精准的要求,这些算法差别不大,一般用SWS_BILINEAR参数,可选类型定义在//libswscale/swscale.h内,如下:

Intel® Pentium® Silver N6000 @ 1.10GHz 4

Thread(s) per core: 1 Core(s) per socket: 4

1920x1080p25 UYVY422–>NV12

SWS_BILINEAR–>30-40ms

SWS_FAST_BILINEAR–>10ms


#define SWS_FAST_BILINEAR 1

#define SWS_BILINEAR 2

#define SWS_BICUBIC 4

#define SWS_X 8

#define SWS_POINT 0x10

#define SWS_AREA 0x20

#define SWS_BICUBLIN 0x40

#define SWS_GAUSS 0x80

#define SWS_SINC 0x100

#define SWS_LANCZOS 0x200

#define SWS_SPLINE 0x400


i9-9900KF CPU @ 3.60GHz 8核16线程下 3840x2160时,yuv420p->uyvy422,用SWS_BILINEAR转化一帧视频消耗31ms,用SWS_POINT消耗3ms。以上各个参数分析

AV_PIX_FMT_UYVY422 1080p50转成AV_PIX_FMT_UYVY422 720p50时,SWS_FAST_BILINEAR和SWS_AREA消耗cpu最小,并且负载均衡,其内部应该开启多个线程一起转换了。其他几个参数负载极不均衡而且对cpu消耗很大。


srcFilter, 输入图像的滤波器信息, 如果不用赋值NULL

dstFilter, 输出图像的滤波器信息, 如果不用赋值NULL

param 特定缩放算法需要的参数,如果不用赋值NULL

int attribute_align_arg sws_scale(struct SwsContext *c,
const uint8_t * const srcSlice[],
const int srcStride[], int srcSliceY,
int srcSliceH, uint8_t *const dst[],
const int dstStride[])


真正做转换的函数,参数分析:

这个转换是深拷贝,需要给dst申请空间,实测yuv420->uyvy422每执行一次就输出一帧,开始不需要多帧输入填充缓存。

sws_scale转换包含像素格式转换和缩放拉伸转换,输入输出可以是rgb或yuv中的任意一种。


srcSlice对应frame->data

yuv各种格式在AVFrame::data[]中的存储方式,另一篇博客:YUV的plannar,packet及semi-planar格式


srcStride这个参数填入frame->linesize linesize[]

数组中保存的是对应通道的数据宽度

linesize[0]——-Y分量的宽度

linesize[1]——-U分量的宽度

linesize[2]——-V分量的宽度

linesize[0]的值并不一定等于图片的宽度,有时候为了对齐各解码器的CPU(32位/64位),实际尺寸会大于图片的宽度,这点在我们编程时(比如OpengGL硬件转换/渲染)要特别注意,否则解码出来的图像会异常,增加linesize[0]的值使得,linesize[0]/32或linesize[0]/64为整数,叫做对齐cpu字节。

以上是planner格式,如果是packet格式,如1920x1080 uyvy422,linesize[1],linesize[2]都为0,因为只有一个分量了,此时linesize[0]为1920*2 = 3840

实测yuv422格式,1080i50视频,在x86上没有格式对齐, frame->linesize[0]为1920x2。此时frame->linesize[0] x frame->width即为此帧frame数据大小。

如果是planner格式的像素,frame的大小应该是(frame->linesize[0]+frame->linesize[1]+frame->linesize[2]) x frame->width。如果用宽x高x像素格式字节数算的话,当像需要补齐字节时,得到的值会小于frame包含的真实值,进行memcpy赋值时会少复制内容。


参数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_getCachedContext ,区别在于: sws_getContext 可以用于多路码流转换,为每个不同的码流都指定一个不同的转换上下文,而 sws_getCachedContext 只能用于一路码流转换。

/**
 * Free the swscaler context swsContext.
 * If swsContext is NULL, then does nothing.
 */
void sws_freeContext(struct SwsContext *swsContext);


释放sws_scale


字节对齐解释:比如704*576分辨率的视频,它的width=704,height=576,摄像机芯片一般会要求64或者128对齐,当128位对齐时,704不能被128整除,需要在每一行结尾补64字节0x00占位,它的linesize也就是每一行的长度768。



相关文章
|
3月前
列分Frame
列分Frame。
21 4
|
3月前
行分Frame
行分Frame。
32 3
|
4月前
Frame
Frame。
34 1
|
7月前
|
Python
Pygame基础5-Surface & Rect
Pygame基础5-Surface & Rect
|
存储 API
sws_scale():bad dst image pointers
sws_scale():bad dst image pointers
330 0
sws_scale():bad dst image pointers
|
程序员 iOS开发
frame 和 bounds的区别
frame 和 bounds的区别
158 0
frame 和 bounds的区别
Fffmpeg:从AVFrame中由YUV获取RGB
Fffmpeg:从AVFrame中由YUV获取RGB
180 0
|
Android开发
详解Bitmap之ARGB_8888/RGB_565/ALPHA_8/ARGB_4444
有时会看到别人使用bitmap是用到ARGB_8888/RGB_565这类参数,那么这些参数是什么?对bitmap有什么影响?
579 0