FFmpeg学习:视频重采样
视频重采样
视频重采样参数
1.图像色彩空间转换;
2.分辨率缩放;
3.前后图像滤波处理
图像宽高、像素格式、尺寸转换算法
视频像素和尺寸转换api
【第一】创建格式转换上下文
SwsContext* video_swscontext = NULL;
【第二】格式变换上下文初始化
【函数原型】
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);
【参数含义】
- int srcW, int srcH, enum AVPixelFormat srcFormat定义输入图像信息(宽、高、颜色空间(像素格式))
- int dstW, int dstH, enum AVPixelFormat dstFormat定义输出图像信息宽、高、颜色空间(像素格式))。
- int flags选择缩放算法(只有当输入输出图像大小不同时有效)
- SwsFilter *srcFilter, SwsFilter *dstFilter分别定义输入/输出图像滤波器信息,如果不做前后图像滤波,输入NULL
- const double *param定义特定缩放算法需要的参数(?),默认为NULL
【flags缩放算法】
点击查看代码
/* values for the flags, the stuff on the command line is different */
#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
#define SWS_SRC_V_CHR_DROP_MASK 0x30000
#define SWS_SRC_V_CHR_DROP_SHIFT 16
#define SWS_PARAM_DEFAULT 123456
#define SWS_PRINT_INFO 0x1000
//the following 3 flags are not completely implemented
//internal chrominance subsampling info
#define SWS_FULL_CHR_H_INT 0x2000
//input subsampling info
#define SWS_FULL_CHR_H_INP 0x4000
#define SWS_DIRECT_BGR 0x8000
#define SWS_ACCURATE_RND 0x40000
#define SWS_BITEXACT 0x80000
#define SWS_ERROR_DIFFUSION 0x800000
#define SWS_MAX_REDUCE_CUTOFF 0.002
#define SWS_CS_ITU709 1
#define SWS_CS_FCC 4
#define SWS_CS_ITU601 5
#define SWS_CS_ITU624 5
#define SWS_CS_SMPTE170M 5
#define SWS_CS_SMPTE240M 7
#define SWS_CS_DEFAULT 5
#define SWS_CS_BT2020 9
【第三】格式转换函数 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[]);
【参数分析】
- const uint8_t *const srcSlice[];原数据存放的地址,一个数组至于取几个要看前面像素格式决定的,如果是YUV平面格式的就要取3位分别对应YUV,如果是RGB打包格式的那么就只取一位。
- const int srcStride[], 一行字节数的大小,就是之前frame里面的linesize。
- int srcSliceY 定义在输入图像上处理区域,srcSliceY是起始位置,
- int srcSliceH srcSliceH是处理多少行。如果srcSliceY=0,srcSliceH=height,表示一次性处理完整个图像
- uint8_t *const dst[];转换后的目的数据存放的空间,是一个指针数组,因此要提前分配空间,
- const int dstStride[] 输出的一行的大小
【第四】释放上下文
void sws_freeContext(struct SwsContext *swsContext);
使用举例
//像素格式和尺寸转换上下文
SwsContext *vctx = NULL;
unsigned char *rgb = NULL;
//在解码后得到解码帧后进行转换的,注意内存的申请和格式转换
//视频
if (cc == vc)
{
vctx = sws_getCachedContext(
vctx, //传NULL会新创建
frame->width, frame->height, //输入的宽高
(AVPixelFormat)frame->format, //输入格式 YUV420p
frame->width, frame->height, //输出的宽高
AV_PIX_FMT_RGBA, //输入格式RGBA
SWS_BILINEAR, //尺寸变化的算法
0, 0, 0);
//if(vctx)
//cout << "像素格式尺寸转换上下文创建或者获取成功!" << endl;
//else
// cout << "像素格式尺寸转换上下文创建或者获取失败!" << endl;
if (vctx)
{
//申请转换后数据存放的内存
if (!rgb) rgb = new unsigned char[frame->width*frame->height * 4];
//转换为对应存放格式,因为是要转换为打包的RGBA格式因此只需要一维,如果是YUV420P的则需要三维都需要内存地址的,否则会奔溃
uint8_t *data[2] = { 0 };
data[0] = rgb;
int lines[2] = { 0 };
lines[0] = frame->width * 4;//存放一行数据大小,
re = sws_scale(vctx,
frame->data, //输入数据
frame->linesize, //输入行大小
0,
frame->height, //输入高度
data, //输出数据和大小
lines //一行的大小
);
cout << "sws_scale = " << re << endl;
}
}