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;
    }
}