ffmpeg关于sws_scale的那些事儿

随便聊聊,sws_scale 在对rgb处理上,基本都是把数据放于一个通道,而且针对行来扫描,所以linedata就是图像的宽 * 通道数,而在对yuv的处理上,基本上都是依据具体的格式,分为三个通道来处理

下面对其函数参数进行详细说明:

1.参数 SwsContext *c, 转换格式的上下文。也就是 sws_getContext 函数返回的结果。
2.参数 const uint8_t *const srcSlice[], 输入图像的每个颜色通道的数据指针。其实就是解码后的AVFrame中的data[]数组。因为不同像素的存储格式不同,所以srcSlice[]维数
也有可能不同。
以YUV420P为例,它是planar格式,它的内存中的排布如下:
YYYYYYYY UUUU VVVV
使用FFmpeg解码后存储在AVFrame的data[]数组中时:
data[0]——-Y分量, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8……
data[1]——-U分量, U1, U2, U3, U4……
data[2]——-V分量, V1, V2, V3, V4……
linesize[]数组中保存的是对应通道的数据宽度 ,
linesize[0]——-Y分量的宽度
linesize[1]——-U分量的宽度
linesize[2]——-V分量的宽度

而RGB24,它是packed格式,它在data[]数组中则只有一维,它在存储方式如下:
data[0]: R1, G1, B1, R2, G2, B2, R3, G3, B3, R4, G4, B4……
这里要特别注意,linesize[0]的值并不一定等于图片的宽度,有时候为了对齐各解码器的CPU,实际尺寸会大于图片的宽度,这点在我们编程时(比如OpengGL硬件转换/渲染)要特别注意,否则解码出来的图像会异常。

3.参数const int srcStride[],输入图像的每个颜色通道的跨度。.也就是每个通道的行字节数,对应的是解码后的AVFrame中的linesize[]数组。根据它可以确立下一行的起始位置,不过stride和width不一定相同,这是因为:
a.由于数据帧存储的对齐,有可能会向每行后面增加一些填充字节这样 stride = width + N;
b.packet色彩空间下,每个像素几个通道数据混合在一起,例如RGB24,每个像素3字节连续存放,因此下一行的位置需要跳过3*width字节。

4.参数int srcSliceY, int srcSliceH,定义在输入图像上处理区域,srcSliceY是起始位置,srcSliceH是处理多少行。如果srcSliceY=0,srcSliceH=height,表示一次性处理完整个图像。这种设置是为了多线程并行,例如可以创建两个线程,第一个线程处理 [0, h/2-1]行,第二个线程处理 [h/2, h-1]行。并行处理加快速度。
5.参数uint8_t *const dst[], const int dstStride[]定义输出图像信息(输出的每个颜色通道数据指针,每个颜色通道行字节数)

某博主写的帖子还是很到位的,Y分量数据,U分量数据,V分量数据,以及每个分量的宽度,完成图像的缩放简直so easy。

 

比如,针对bgra的长宽的裸流缩放为适当的rgb的裸流,其代码如下:

    AVFrame *nDst = nullptr;
	nDst = av_frame_alloc();
	nDst->width = nDstW;
	nDst->height = nDstH;
	nDst->f
<think> 我们正在讨论FFmpeg中的sws_scale函数,特别是最后两个参数的含义。根据引用[2]提供的函数定义: 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[]); 我们可以数一下参数: 1. struct SwsContext *c 2. const uint8_t *const srcSlice[] 3. const int srcStride[] 4. int srcSliceY 5. int srcSliceH 6. uint8_t *const dst[] 7. const int dstStride[] 所以,最后两个参数分别是: 第6个参数:uint8_t *const dst[] (目标图像数据指针数组) 第7个参数:const int dstStride[] (目标图像的步幅数组) 现在,我们详细解释这两个参数: 1. 第6个参数:`uint8_t *const dst[]` - 这是一个指向指针数组的指针,用于存放转换后的图像数据(即目标图像数据)。在FFmpeg中,图像数据通常按照平面(plane)存储,例如YUV格式通常分为Y平面、U平面和V平面。对于每个平面,都有一个数据指针。 - 对于像素格式如RGB24,可能只有一个平面,而对于YUV420P,则有三个平面(Y、U、V)。 - 所以,这个数组的每个元素都是一个指向某个平面数据的指针。数组的长度取决于目标图像的像素格式(由之前通过sws_getContext设置的目标格式决定)。 2. 第7个参数:`const int dstStride[]` - 这是目标图像每个平面的步幅(stride)数组。步幅指的是图像中每行像素在内存中所占的字节数。由于内存对齐的原因,步幅可能大于图像的宽度(即每行实际有效的字节数)。 - 例如,一个宽度为1280的YUV420P图像的Y平面,每行有1280个字节(每个像素1字节),但系统可能为了内存对齐,将每行分配为1284字节(对齐到4字节边界),那么Y平面的步幅就是1284。 - 同样,这个数组的长度与目标图像的平面数相同。每个元素对应目标图像每个平面的步幅。 举例说明: 假设我们要将一幅图像转换为YUV420P格式,目标图像有三个平面,那么: - dst[0] 指向Y平面数据的起始地址 - dst[1] 指向U平面数据的起始地址 - dst[2] 指向V平面数据的起始地址 - dstStride[0] 是Y平面每行的字节数(步幅) - dstStride[1] 是U平面每行的字节数(步幅) - dstStride[2] 是V平面每行的字节数(步幅) 注意:在调用sws_scale之前,我们需要为dst数组分配好内存,并且设置好每个平面的步幅。 另外,引用[4]提到:“總共有十個參數,其中,較重要的是前七個”,但实际上我们看到的函数定义只有七个参数。可能引用[4]所指的是较早版本或不同上下文,但当前标准定义是七个参数(如引用[2]所示)。 综上所述,最后两个参数分别表示转换后图像的数据缓冲区(dst)和每个平面的步幅(dstStride)。 §§相关问题§§ 1. sws_scale函数中,srcStride和dstStride有什么不同? 2. 如何为sws_scale函数的目标图像分配内存? 3. 在处理不同像素格式时,dst数组应该如何设置? 4. 能否举例说明如何调用sws_scale函数? </think> ### FFmpeg的`sws_scale`函数最后两个参数详解 根据引用[2]和[4]提供的函数定义: ```c int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], // 第6个参数 const int dstStride[]); // 第7个参数 ``` 最后两个参数的含义如下: #### 1. **`uint8_t *const dst[]` (目标图像数据指针数组)** - **作用**:指向输出图像数据的指针数组,存储转换后的像素数据 - **结构**: - 数组长度由目标图像的像素格式决定(如YUV420P需要3个指针,RGB24需要1个指针) - 每个元素指向输出图像特定分量的内存起始地址(如YUV格式中:`dst[0]`=Y平面, `dst[1]`=U平面, `dst[2]`=V平面) - **内存分配**:需**调用者预先分配**足够的内存空间 - **示例**:RGB24输出时只需单个指针:`dst[0] = output_rgb_buffer` #### 2. **`const int dstStride[]` (目标图像步幅数组)** - **作用**:定义输出图像每个平面的内存行跨度(stride) - **关键概念**: - 步幅 = 每行像素占用的**实际字节数**(可能包含内存对齐的填充字节) - 计算方式:`stride ≥ 图像宽度 × 每像素字节数` - **示例**:1280x720的YUV420P输出: - Y平面:`dstStride[0] = 1280`(或更大的对齐值如1284) - UV平面:`dstStride[1] = dstStride[2] = 640`(因色度分量宽高减半) #### 参数关系图 ``` dst[0] → [Y行0] [Y行1] ... // 长度=dstStride[0] dst[1] → [U行0] [U行1] ... // 长度=dstStride[1] dst[2] → [V行0] [V行1] ... // 长度=dstStride[2] ``` > **注意事项**:这两个参数共同定义了输出图像的存储布局,必须与`sws_getContext()`初始化时指定的目标格式一致,否则会导致内存错误或图像扭曲[^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值