You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派YUV420P摄像头数据转RGBA:sws_scale参数配置困惑

解决YUV420P转RGBA时sws_scale的参数设置问题

我来帮你理清这个问题——用FFmpeg的sws_scale处理YUV420P格式时,最关键的就是搞懂它的平面存储结构,你之前的段错误就是因为没正确拆分Y/U/V三个平面导致的,这也是新手用缩放器时很容易踩的坑!

先搞懂YUV420P的存储结构

YUV420P是平面格式,不是把Y/U/V数据打包在一起,而是分成三个独立的连续内存块:

  • Y平面:每个像素占1字节,分辨率和原始摄像头一致(CAMERA_WIDTH × CAMERA_HEIGHT),总字节数是 W×H
  • U平面:每个像素占1字节,但分辨率是原始的1/4((W/2) × (H/2)),总字节数是 (W×H)/4
  • V平面:和U平面完全相同,也是 (W×H)/4

整个YUV420P数组的总长度是 W×H + (W×H)/4 + (W×H)/4 = W×H×1.5,你可以先确认摄像头返回的数组长度是否符合这个值,避免数据本身有问题。

正确设置src_data和src_strides

sws_scale需要明确知道每个平面的起始地址和每行的字节数(stride),具体设置如下:

1. src_data(源数据指针数组)

这是一个包含3个指针的数组,分别指向Y、U、V三个平面的起始位置:

  • src_data[0]:直接指向摄像头返回的字节数组开头(Y平面的起始)
  • src_data[1]:跳过整个Y平面的字节,指向U平面的起始,计算方式是 src_data[0] + CAMERA_WIDTH * CAMERA_HEIGHT
  • src_data[2]:跳过Y和U平面的字节,指向V平面的起始,计算方式是 src_data[1] + (CAMERA_WIDTH * CAMERA_HEIGHT)/4

2. src_strides(源数据每行字节数)

stride代表每个平面中一行数据占用的字节数,对于无对齐的纯字节数组:

  • Y平面的stride就是CAMERA_WIDTH(每行W个像素,每个1字节)
  • U和V平面的stride是CAMERA_WIDTH / 2(每行是W/2个像素,每个1字节)

如果你的摄像头数据有内存对齐(比如按4字节对齐),stride可能会比理论值大一点,但如果是纯无结构字节数组,用上面的数值就没问题。

完整代码示例

// 假设data是摄像头返回的YUV420P格式纯字节数组
const uint8_t* src_data[3];
int src_strides[3];

// 初始化三个平面的指针
src_data[0] = data.data(); // Y平面起始地址
src_data[1] = src_data[0] + CAMERA_WIDTH * CAMERA_HEIGHT; // U平面起始地址
src_data[2] = src_data[1] + (CAMERA_WIDTH * CAMERA_HEIGHT) / 4; // V平面起始地址

// 设置每行字节数
src_strides[0] = CAMERA_WIDTH;
src_strides[1] = CAMERA_WIDTH / 2;
src_strides[2] = CAMERA_WIDTH / 2;

// 调用sws_scale进行转换(注意dst_data和dst_strides要提前初始化好RGBA的目标缓冲区)
sws_scale(_sws_context, src_data, src_strides, 0, CAMERA_HEIGHT, dst_data, dst_strides);

为什么之前的设置会触发段错误?

你之前把所有数据当成一个平面传入src_data,但sws_scale会按照你指定的AV_PIX_FMT_YUV420P格式去读取三个平面的数据,它会尝试从src_data[1]和src_data[2]的位置读取数据,但这两个指针你没设置,会指向非法内存,自然就触发段错误了。

内容的提问来源于stack exchange,提问作者Yanick Salzmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:27:58