libswscale介绍
1、2种初始化方法:
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);
2、转换一帧图像:1.图像色彩空间转换;2.分辨率缩放;3.前后图像滤波处理。
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[]);
3、释放
void sws_freeContext(struct SwsContext *swsContext);
主要步骤:
最简单的基于FFmpeg的libswscale的示例(YUV转RGB)
①像素格式: 以“AV_PIX_FMT_”开头
1.后缀:P(planar格式),反之没有P👉默认为packed格式
①Planar格式不同的分量分别存储在不同的数组中 如:AV_PIX_FMT_YUV420P存储方式如下:
data[0]: Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8……
data[1]: U1, U2, U3, U4……
data[2]: V1, V2, V3, V4……
②Packed格式的数据都存储在同一个数组中,如:AV_PIX_FMT_RGB24存储方式
data[0]: R1, G1, B1, R2, G2, B2, R3, G3, B3, R4, G4, B4……
2.后缀:“BE(Big Endian格式) “LE”(Little Endian格式)
②图像拉伸
③YUV像素取值范围
④色域
实例:将视频从YUV420P格式转换为RGB24格式, 同时将分辨率从480x272拉伸为1280x720
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
int main(int argc, char* argv[])
{
FILE *src_file =fopen("sintel_480x272_yuv420p.yuv", "rb");
const int src_w=480,src_h=272;
AVPixelFormat src_pixfmt=AV_PIX_FMT_YUV420P;
int src_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(src_pixfmt));
FILE *dst_file = fopen("sintel_1280x720_rgb24.rgb", "wb");
const int dst_w=1280,dst_h=720;
AVPixelFormat dst_pixfmt=AV_PIX_FMT_RGB24;
int dst_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(dst_pixfmt));
uint8_t *src_data[4];
int src_linesize[4];
uint8_t *dst_data[4];
int dst_linesize[4];
int rescale_method=SWS_BICUBIC;
struct SwsContext *img_convert_ctx;
uint8_t *temp_buffer=(uint8_t *)malloc(src_w*src_h*src_bpp/8);
int frame_idx=0;
int ret=0;
ret= av_image_alloc(src_data, src_linesize,src_w, src_h, src_pixfmt, 1);
ret = av_image_alloc(dst_data, dst_linesize,dst_w, dst_h, dst_pixfmt, 1);
img_convert_ctx =sws_alloc_context();
av_opt_show2(img_convert_ctx,stdout,AV_OPT_FLAG_VIDEO_PARAM,0);
av_opt_set_int(img_convert_ctx,"sws_flags",SWS_BICUBIC|SWS_PRINT_INFO,0);
av_opt_set_int(img_convert_ctx,"srcw",src_w,0);
av_opt_set_int(img_convert_ctx,"srch",src_h,0);
av_opt_set_int(img_convert_ctx,"src_format",src_pixfmt,0);
av_opt_set_int(img_convert_ctx,"src_range",1,0);
av_opt_set_int(img_convert_ctx,"dstw",dst_w,0);
av_opt_set_int(img_convert_ctx,"dsth",dst_h,0);
av_opt_set_int(img_convert_ctx,"dst_format",dst_pixfmt,0);
av_opt_set_int(img_convert_ctx,"dst_range",1,0);
sws_init_context(img_convert_ctx,NULL,NULL);
while(1)
{
if (fread(temp_buffer, 1, src_w*src_h*src_bpp/8, src_file) != src_w*src_h*src_bpp/8){
break;
}
switch(src_pixfmt){
case AV_PIX_FMT_GRAY8:{
memcpy(src_data[0],temp_buffer,src_w*src_h);
break;
}
case AV_PIX_FMT_YUV420P:{
memcpy(src_data[0],temp_buffer,src_w*src_h);
memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/4);
memcpy(src_data[2],temp_buffer+src_w*src_h*5/4,src_w*src_h/4);
break;
}
case AV_PIX_FMT_YUV422P:{
memcpy(src_data[0],temp_buffer,src_w*src_h);
memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/2);
memcpy(src_data[2],temp_buffer+src_w*src_h*3/2,src_w*src_h/2);
break;
}
case AV_PIX_FMT_YUV444P:{
memcpy(src_data[0],temp_buffer,src_w*src_h);
memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h);
memcpy(src_data[2],temp_buffer+src_w*src_h*2,src_w*src_h);
break;
}
case AV_PIX_FMT_YUYV422:{
memcpy(src_data[0],temp_buffer,src_w*src_h*2);
break;
}
case AV_PIX_FMT_RGB24:{
memcpy(src_data[0],temp_buffer,src_w*src_h*3);
break;
}
default:{
printf("Not Support Input Pixel Format.\n");
break;
}
}
sws_scale(img_convert_ctx, src_data, src_linesize, 0, src_h, dst_data, dst_linesize);
printf("Finish process frame %5d\n",frame_idx);
frame_idx++;
switch(dst_pixfmt){
case AV_PIX_FMT_GRAY8:{
fwrite(dst_data[0],1,dst_w*dst_h,dst_file);
break;
}
case AV_PIX_FMT_YUV420P:{
fwrite(dst_data[0],1,dst_w*dst_h,dst_file);
fwrite(dst_data[1],1,dst_w*dst_h/4,dst_file);
fwrite(dst_data[2],1,dst_w*dst_h/4,dst_file);
break;
}
case AV_PIX_FMT_YUV422P:{
fwrite(dst_data[0],1,dst_w*dst_h,dst_file);
fwrite(dst_data[1],1,dst_w*dst_h/2,dst_file);
fwrite(dst_data[2],1,dst_w*dst_h/2,dst_file);
break;
}
case AV_PIX_FMT_YUV444P:{
fwrite(dst_data[0],1,dst_w*dst_h,dst_file);
fwrite(dst_data[1],1,dst_w*dst_h,dst_file);
fwrite(dst_data[2],1,dst_w*dst_h,dst_file);
break;
}
case AV_PIX_FMT_YUYV422:{
fwrite(dst_data[0],1,dst_w*dst_h*2,dst_file);
break;
}
case AV_PIX_FMT_RGB24:{
fwrite(dst_data[0],1,dst_w*dst_h*3,dst_file);
break;
}
default:{
printf("Not Support Output Pixel Format.\n");
break;
}
}
}
sws_freeContext(img_convert_ctx);
free(temp_buffer);
fclose(dst_file);
av_freep(&src_data[0]);
av_freep(&dst_data[0]);
return 0;
}
像素格式
像素格式的知识此前已经记录过,不再重复。在这里记录一下FFmpeg支持的像素格式。有几点注意事项:
(1) 所有的像素格式的名称都是以“AV_PIX_FMT_”开头
(2) 像素格式名称后面有“P”的,代表是planar格式,否则就是packed格式。Planar格式不同的分量分别存储在不同的数组中,例如AV_PIX_FMT_YUV420P存储方式如下:
data[0]: Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8……
data[1]: U1, U2, U3, U4……
data[2]: V1, V2, V3, V4……
Packed格式的数据都存储在同一个数组中,例如AV_PIX_FMT_RGB24存储方式如下:
data[0]: R1, G1, B1, R2, G2, B2, R3, G3, B3, R4, G4, B4……
(3) 像素格式名称后面有“BE”的,代表是Big Endian格式;名称后面有“LE”的,代表是Little Endian格式。
FFmpeg支持的像素格式的定义位于libavutil\pixfmt.h,是一个名称为AVPixelFormat的枚举类型,如下所示。
enum AVPixelFormat {
AV_PIX_FMT_NONE = -1,
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_RGB24,
AV_PIX_FMT_BGR24,
AV_PIX_FMT_YUV422P,
AV_PIX_FMT_YUV444P,
AV_PIX_FMT_YUV410P,
AV_PIX_FMT_YUV411P,
AV_PIX_FMT_GRAY8,
AV_PIX_FMT_MONOWHITE,
AV_PIX_FMT_MONOBLACK,
AV_PIX_FMT_PAL8,
AV_PIX_FMT_YUVJ420P,
AV_PIX_FMT_YUVJ422P,
AV_PIX_FMT_YUVJ444P,
#if FF_API_XVMC
AV_PIX_FMT_XVMC_MPEG2_MC,
AV_PIX_FMT_XVMC_MPEG2_IDCT,
#define AV_PIX_FMT_XVMC AV_PIX_FMT_XVMC_MPEG2_IDCT
#endif
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_UYYVYY411,
AV_PIX_FMT_BGR8,
AV_PIX_FMT_BGR4,
AV_PIX_FMT_BGR4_BYTE,
AV_PIX_FMT_RGB8,
AV_PIX_FMT_RGB4,
AV_PIX_FMT_RGB4_BYTE,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_ARGB,
AV_PIX_FMT_RGBA,
AV_PIX_FMT_ABGR,
AV_PIX_FMT_BGRA,
AV_PIX_FMT_GRAY16BE,
AV_PIX_FMT_GRAY16LE,
AV_PIX_FMT_YUV440P,
AV_PIX_FMT_YUVJ440P,
AV_PIX_FMT_YUVA420P,
#if FF_API_VDPAU
AV_PIX_FMT_VDPAU_H264,
AV_PIX_FMT_VDPAU_MPEG1,
AV_PIX_FMT_VDPAU_MPEG2,
AV_PIX_FMT_VDPAU_WMV3,
AV_PIX_FMT_VDPAU_VC1,
#endif
AV_PIX_FMT_RGB48BE,
AV_PIX_FMT_RGB48LE,
AV_PIX_FMT_RGB565BE,
AV_PIX_FMT_RGB565LE,
AV_PIX_FMT_RGB555BE,
AV_PIX_FMT_RGB555LE,
AV_PIX_FMT_BGR565BE,
AV_PIX_FMT_BGR565LE,
AV_PIX_FMT_BGR555BE,
AV_PIX_FMT_BGR555LE,
AV_PIX_FMT_VAAPI_MOCO,
AV_PIX_FMT_VAAPI_IDCT,
AV_PIX_FMT_VAAPI_VLD,
AV_PIX_FMT_YUV420P16LE,
AV_PIX_FMT_YUV420P16BE,
AV_PIX_FMT_YUV422P16LE,
AV_PIX_FMT_YUV422P16BE,
AV_PIX_FMT_YUV444P16LE,
AV_PIX_FMT_YUV444P16BE,
#if FF_API_VDPAU
AV_PIX_FMT_VDPAU_MPEG4,
#endif
AV_PIX_FMT_DXVA2_VLD,
AV_PIX_FMT_RGB444LE,
AV_PIX_FMT_RGB444BE,
AV_PIX_FMT_BGR444LE,
AV_PIX_FMT_BGR444BE,
AV_PIX_FMT_GRAY8A,
AV_PIX_FMT_BGR48BE,
AV_PIX_FMT_BGR48LE,
AV_PIX_FMT_YUV420P9BE,
AV_PIX_FMT_YUV420P9LE,
AV_PIX_FMT_YUV420P10BE,
AV_PIX_FMT_YUV420P10LE,
AV_PIX_FMT_YUV422P10BE,
AV_PIX_FMT_YUV422P10LE,
AV_PIX_FMT_YUV444P9BE,
AV_PIX_FMT_YUV444P9LE,
AV_PIX_FMT_YUV444P10BE,
AV_PIX_FMT_YUV444P10LE,
AV_PIX_FMT_YUV422P9BE,
AV_PIX_FMT_YUV422P9LE,
AV_PIX_FMT_VDA_VLD,
#ifdef AV_PIX_FMT_ABI_GIT_MASTER
AV_PIX_FMT_RGBA64BE,
AV_PIX_FMT_RGBA64LE,
AV_PIX_FMT_BGRA64BE,
AV_PIX_FMT_BGRA64LE,
#endif
AV_PIX_FMT_GBRP,
AV_PIX_FMT_GBRP9BE,
AV_PIX_FMT_GBRP9LE,
AV_PIX_FMT_GBRP10BE,
AV_PIX_FMT_GBRP10LE,
AV_PIX_FMT_GBRP16BE,
AV_PIX_FMT_GBRP16LE,
AV_PIX_FMT_YUVA422P_LIBAV,
AV_PIX_FMT_YUVA444P_LIBAV,
AV_PIX_FMT_YUVA420P9BE,
AV_PIX_FMT_YUVA420P9LE,
AV_PIX_FMT_YUVA422P9BE,
AV_PIX_FMT_YUVA422P9LE,
AV_PIX_FMT_YUVA444P9BE,
AV_PIX_FMT_YUVA444P9LE,
AV_PIX_FMT_YUVA420P10BE,
AV_PIX_FMT_YUVA420P10LE,
AV_PIX_FMT_YUVA422P10BE,
AV_PIX_FMT_YUVA422P10LE,
AV_PIX_FMT_YUVA444P10BE,
AV_PIX_FMT_YUVA444P10LE,
AV_PIX_FMT_YUVA420P16BE,
AV_PIX_FMT_YUVA420P16LE,
AV_PIX_FMT_YUVA422P16BE,
AV_PIX_FMT_YUVA422P16LE,
AV_PIX_FMT_YUVA444P16BE,
AV_PIX_FMT_YUVA444P16LE,
AV_PIX_FMT_VDPAU,
AV_PIX_FMT_XYZ12LE,
AV_PIX_FMT_XYZ12BE,
AV_PIX_FMT_NV16,
AV_PIX_FMT_NV20LE,
AV_PIX_FMT_NV20BE,
AV_PIX_FMT_RGBA64BE_LIBAV,
AV_PIX_FMT_RGBA64LE_LIBAV,
AV_PIX_FMT_BGRA64BE_LIBAV,
AV_PIX_FMT_BGRA64LE_LIBAV,
AV_PIX_FMT_YVYU422,
#ifndef AV_PIX_FMT_ABI_GIT_MASTER
AV_PIX_FMT_RGBA64BE=0x123,
AV_PIX_FMT_RGBA64LE,
AV_PIX_FMT_BGRA64BE,
AV_PIX_FMT_BGRA64LE,
#endif
AV_PIX_FMT_0RGB=0x123+4,
AV_PIX_FMT_RGB0,
AV_PIX_FMT_0BGR,
AV_PIX_FMT_BGR0,
AV_PIX_FMT_YUVA444P,
AV_PIX_FMT_YUVA422P,
AV_PIX_FMT_YUV420P12BE,
AV_PIX_FMT_YUV420P12LE,
AV_PIX_FMT_YUV420P14BE,
AV_PIX_FMT_YUV420P14LE,
AV_PIX_FMT_YUV422P12BE,
AV_PIX_FMT_YUV422P12LE,
AV_PIX_FMT_YUV422P14BE,
AV_PIX_FMT_YUV422P14LE,
AV_PIX_FMT_YUV444P12BE,
AV_PIX_FMT_YUV444P12LE,
AV_PIX_FMT_YUV444P14BE,
AV_PIX_FMT_YUV444P14LE,
AV_PIX_FMT_GBRP12BE,
AV_PIX_FMT_GBRP12LE,
AV_PIX_FMT_GBRP14BE,
AV_PIX_FMT_GBRP14LE,
AV_PIX_FMT_GBRAP,
AV_PIX_FMT_GBRAP16BE,
AV_PIX_FMT_GBRAP16LE,
AV_PIX_FMT_YUVJ411P,
AV_PIX_FMT_BAYER_BGGR8,
AV_PIX_FMT_BAYER_RGGB8,
AV_PIX_FMT_BAYER_GBRG8,
AV_PIX_FMT_BAYER_GRBG8,
AV_PIX_FMT_BAYER_BGGR16LE,
AV_PIX_FMT_BAYER_BGGR16BE,
AV_PIX_FMT_BAYER_RGGB16LE,
AV_PIX_FMT_BAYER_RGGB16BE,
AV_PIX_FMT_BAYER_GBRG16LE,
AV_PIX_FMT_BAYER_GBRG16BE,
AV_PIX_FMT_BAYER_GRBG16LE,
AV_PIX_FMT_BAYER_GRBG16BE,
#if !FF_API_XVMC
AV_PIX_FMT_XVMC,
#endif
AV_PIX_FMT_NB,
#if FF_API_PIX_FMT
#include "old_pix_fmts.h"
#endif
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)