sws_scale 到底在干嘛?—— FFmpeg libswscale 最细参数说明书
目录一、先给一句话定性二、sws_scale 函数原型三、参数逐个拆解① struct SwsContext *c是什么flags 常见值必须知道② const uint8_t *const srcSlice[]是什么合法值示例③ const int srcStride[]是什么为什么不等于 width * bpp④ int srcSliceY官方语义现实情况⑤ int srcSliceH是什么⑥ uint8_t *const dst[]是什么玩法 AAVFrame 接住玩法 B自己 malloc⑦ const int dstStride[]最常见翻车点正确示例RGB32YUV420P 输出四、使用示例五、90% 花屏 / 灰边 / 崩溃的真实原因六、colorspace / range 怎么塞进去七、一句话总结觉得有用就请您帮忙点赞转发收藏吧您的鼓励是我创作的动力多谢看官。由于能力水平有限文中的错误或不严谨的地方在所难免还请批评指正。sws_scale是 FFmpeg 多媒体框架中libswscale库的核心函数主要用于高效地执行‌图像像素格式转换‌、‌分辨率缩放‌以及‌图像滤波处理‌。它通常在视频解码后、渲染或编码前被调用将解码得到的原始帧数据如 YUV 格式转换为目标格式如 RGB 格式或调整尺寸。做播放器的人早晚都会遇到这一句sws_scale(sws_ctx, frame-data, frame-linesize, 0, frame-height, dst-data, dst-linesize);抄能用但一问为什么传 linesize为什么 srcSliceY 永远是 0dstStride 能不能乱填​今天就把它拆干净。一、先给一句话定性sws_scale 不是“画图函数”是像素搬运工负责 YUV↔RGB / resize / colorspace / range 全部打包干完。核心任务只有两件格式转换Pixel Format几何缩放Scale二、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[]);看着吓人其实分组很好记上下文 src 数据 / 步长 裁剪区域 dst 数据 / 步长三、参数逐个拆解①struct SwsContext *c是什么一次初始化终身干活直到分辨率/格式变由这个函数产出的struct SwsContext *sws_ctx sws_getContext( src_w, src_h, src_fmt, dst_w, dst_h, dst_fmt, SWS_BILINEAR, NULL, NULL, NULL );flags 常见值必须知道flag中文用在哪里SWS_FAST_BILINEAR快双线性播放器首选SWS_BILINEAR双线性质量稍好SWS_BICUBIC立方放大好看SWS_POINT最近邻截图 / 调试SWS_LANCZOS锐缩图强迫症SWS_AREA均值缩得很小实时播放器结论1080p↓SWS_FAST_BILINEAR放大预览BICUBIC②const uint8_t *const srcSlice[]是什么AVFrame-data 原样传srcSlice frame-data;合法值示例格式srcSlice 含义YUV420P{data[0], data[1], data[2]}NV12{data[0], data[1]}RGB24{data[0]}RGBA{data[0]}别传 AVFrame传它的 data*③const int srcStride[]是什么每一平面的“行跨度bytes per line”srcStride frame-linesize;为什么不等于 width * bppCPU 对齐32 / 64GPU / SIMD 友好例1280×720 yuv420plinesize[0] 1280 Y linesize[1] 640 U linesize[2] 640 V但 1278 宽可能变成linesize[0] 1280 ← paddingsws_scale 靠 stride 找下一行❌ 自己算 stride 花屏之源④int srcSliceY官方语义从第几行开始处理切片现实情况srcSliceY 0; // 99% 情况什么时候不是 0多线程切条处理 slice古老优化超大图分段 scale现在没人这么干 记住播放器永远传 0⑤int srcSliceH是什么要处理的行数正确写法srcSliceH frame-height;别写 dst_h / coded_height⑥uint8_t *const dst[]是什么输出缓冲区两种玩法玩法 AAVFrame 接住av_frame_get_buffer(dst_frame, 32); dst dst_frame-data;玩法 B自己 mallocuint8_t* rgb new uint8_t[w*h*4]; uint8_t* out[1] { rgb };注意对齐推荐av_malloc()⑦const int dstStride[]最常见翻车点正确示例RGB32int dst_stride dst_w * 4; uint8_t* out[1] { buf }; int stride[1] { dst_stride };YUV420P 输出int dst_linesize[3] { dst_w, dst_w / 2, dst_w / 2 };sws_scale 不帮你 alloc也不帮你猜 stride四、使用示例SwsContext* sws sws_getContext( dec_frame-width, dec_frame-height, (AVPixelFormat)dec_frame-format, dst_w, dst_h, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr ); uint8_t* rgb (uint8_t*)av_malloc(dst_w * dst_h * 3); uint8_t* out[] { rgb }; int dst_stride[] { dst_w * 3 }; sws_scale(sws, dec_frame-data, dec_frame-linesize, 0, dec_frame-height, out, dst_stride);五、90% 花屏 / 灰边 / 崩溃的真实原因症状真凶右边彩色条纹dstStride ≠ width*bpp上下错位srcSliceH 传错颜色发绿pixfmt 传 AV_PIX_FMT_YUV420 → YUVJ420P缩放糊flag 用 POINT内存越界dst buffer 没算 padding六、colorspace / range 怎么塞进去sws_scale只看像素布局不认 color_range / primaries。高级玩家这样玩sws_setColorspaceDetails( sws, sws_getCoefficients(AVCOL_SPC_BT709), 1, // src_range (0full) sws_getCoefficients(AVCOL_SPC_BT709), 1, // dst_range 0, 116, 116 );不然 YUV→RGB 永远“差点味”七、一句话总结sws_scale src/data/linesize dst/data/linesize 裁剪从 0 到 height永远用 AVFrame 的 linesize别自己算flags 别瞎选。

相关新闻