FFmpeg – 常用的视频像素格式以及使用SwsContext和sws_scale进行视频像素格式转换和视频缩放
1 视频像素格式
YUV420P
YUV420P三个Plane,按照YYYY.....UUUU.....VVVV.....分别存储于各个Plane通道
RGB24
RGB24一个Plane,按照RGBRGBRGB......的顺序存储在一个Plane中
BGR24
BGR24一个Plane,按照BGRBGRBGR......的顺序存储在一个Plane中
NV12
NV12两个Plane,一个Plane存储YYYYYY......,另一个Plane按照UV的顺序交叉存储UVUVUV......
NV21
NV21两个Plane,一个Plane存储YYYYYY......,另一个Plane按照VU的顺序交叉存储VUVUVU......
2 FFmpeg视频像素格式转换和视频缩放相关函数
2.1 sws_getContext
函数形式
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
)
函数功能
分配并返回一个SwsContext结构体,用于在sws_scale函数中执行图像缩放和转换操作。
函数参数
- srcW - 源图像的宽度
- srcH - 源图像的高度
- srcFormat - 源图像格式
- dstW - 目标图像的宽度
- dstH - 目标图像的高度
- dstFormat - 目标图像格式
- flags - 指定用于重新算法的算法和选项
- param - 调整使用的缩放器的额外参数
关于flags参数,可以有以下选项
#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
此篇文章 比较了不同flag的性能以及效果,可以参考以下。
函数返回值
返回已经分配的SwsContext的指针,如果出现错误,则返回NULL
2.2 sws_getCachedContext
函数形式
struct SwsContext* sws_getCachedContext (struct SwsContext * context,
int srcW,
int srcH,
enum AVPixelFormat srcFormat,
int dstW,
int dstH,
enum AVPixelFormat dstFormat,
int flags,
SwsFilter * srcFilter,
SwsFilter * dstFilter,
const double * param
)
函数功能
此函数与之前的sws_getContext的区别在于,此函数会先行检查SwsContext是否可以重用,如果不可以则重新分配一个新的。
如果SwsContext为NULL,则会调用sws_getContext函数获取新的上下文,如果SwsContext不为NULL,检查设置的新参数是否是已经保存在输入的sws_getContext中,如果参数完全一致则返回当前上下文,否则则释放当前上下文并根据新参数获取新的上下文。
函数参数
- srcW - 源图像的宽度
- srcH - 源图像的高度
- srcFormat - 源图像格式
- dstW - 目标图像的宽度
- dstH - 目标图像的高度
- dstFormat - 目标图像格式
- flags - 指定用于重新算法的算法和选项
- param - 调整使用的缩放器的额外参数
关于flags参数,可以有以下选项
#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
此篇文章 比较了不同flag的性能以及效果,可以参考以下。
函数返回值
返回已经分配的SwsContext的指针,如果出现错误,则返回NULL
2.3 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[]
)
函数功能
将原图像切片进行缩放,并将缩放的图像切片放入目标图像中。
切片是图像中的一系列连续行,切片必须连续提供,可以是自上而下或者自下而上的顺序。
函数参数
- c - 使用sws_getContext()创建的上下文
- srcSlice - 指向源切片平面的指针的数组
- srcStride - 指向源图像每个平面步幅的数组
- srcSliceY - 要处理的切片在源图像中的位置,即切片第一行的图像的数字(从零开始计数)
- srcSliceH - 源切片的高度,即切片中的行数
- dst - 指向目标图像平面的指针的数组
- dstStride - 指向目标图像每个平面的步幅的数组
函数返回值
目标图像切片的高度
2.4 sws_freeContext
函数形式
void sws_freeContext(struct SwsContext * swsContext)
函数功能
释放swscaler上下文swsContext,如果swsContext为NULL,则不做任何事情。
3 使用示例
将OpenCV的BGR24视频像素格式的cv::Mat转换成YUV420P,并保持相同的宽高
void CvMatToAVFrame(const cv::Mat& input_mat, AVFrame* out_avframe)
{
int image_width = input_mat.cols;
int image_height = input_mat.rows;
int cvLinesizes[1];
cvLinesizes[0] = input_mat.step1();
SwsContext* openCVBGRToAVFrameSwsContext = sws_getContext(
image_width,
image_height,
AVPixelFormat::AV_PIX_FMT_BGR24,
image_width,
image_height,
AVPixelFormat::AV_PIX_FMT_YUV420P,
SWS_FAST_BILINEAR,
nullptr, nullptr, nullptr
);
sws_scale(openCVBGRToAVFrameSwsContext,
&input_mat.data,
cvLinesizes,
0,
image_height,
out_avframe->data,
out_avframe->linesize);
if (openCVBGRToAVFrameSwsContext != nullptr)
{
sws_freeContext(openCVBGRToAVFrameSwsContext);
openCVBGRToAVFrameSwsContext = nullptr;
}
}
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:FFmpeg – 常用的视频像素格式以及使用SwsContext和sws_scale进行视频像素格式转换和视频缩放
原文链接:https://www.stubbornhuang.com/2135/
发布于:2022年05月21日 9:20:08
修改于:2023年06月26日 20:09:44
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
52