ffmpeg--libswscale(图像拉伸,像素格式转换)

12种初始化方法:
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);
//或者sws_getCachedContext
//sws_getContext内部拆分:sws_alloc_context	+	av_opt_set_XXX	+	av_opt_set_XXX   【创建默认+设置参数】
//复杂但是灵活---可以配置一些sws_getContext()配置不了的参数
//比如说设置图像的YUV像素的取值范围是JPEG标准(Y、U、V取值范围都是0-255)还是MPEG标准(Y取值范围是16-235,U、V的取值范围是16-240)。


2、转换一帧图像:1.图像色彩空间转换;2.分辨率缩放;3.前后图像滤波处理。
int sws_scale(struct SwsContext *c, 
              const uint8_t *const srcSlice[], //源数据frame->date,
              const int srcStride[], //步幅,可以理解为图像的行宽frame->linesize 
              int srcSliceY, int srcSliceH,//开始处理的位置相对于图像的位置,若从头开始则是0,0
              uint8_t *const dst[], const int dstStride[]);//输出图像数据,输出图像宽度
              //返回输出图像高度

3、释放
void sws_freeContext(struct SwsContext *swsContext);

主要步骤:

最简单的基于FFmpeg的libswscale的示例(YUV转RGB)

①像素格式: 以“AV_PIX_FMT_”开头
1.后缀: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……
2.后缀:“BE(Big Endian格式) “LE”(Little Endian格式)
②图像拉伸
③YUV像素取值范围
④色域

实例:将视频从YUV420P格式转换为RGB24格式, 同时将分辨率从480x272拉伸为1280x720

#include <stdio.h>
 
#define __STDC_CONSTANT_MACROS
 
#ifdef _WIN32
//Windows
extern "C"
{
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#ifdef __cplusplus
};
#endif
#endif
 
 
int main(int argc, char* argv[])
{
	//Parameters	
	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));
 
	//Structures
	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);
	if (ret< 0) {
		printf( "Could not allocate source image\n");
		return -1;
	}
	ret = av_image_alloc(dst_data, dst_linesize,dst_w, dst_h, dst_pixfmt, 1);
	if (ret< 0) {
		printf( "Could not allocate destination image\n");
		return -1;
	}
	//-----------------------------	
	//Init Method 1
	img_convert_ctx =sws_alloc_context();
	//Show AVOption
	av_opt_show2(img_convert_ctx,stdout,AV_OPT_FLAG_VIDEO_PARAM,0);
	//Set Value
	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);
	//'0' for MPEG (Y:0-235);'1' for JPEG (Y:0-255)
	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);
 
	//Init Method 2
	//img_convert_ctx = sws_getContext(src_w, src_h,src_pixfmt, dst_w, dst_h, dst_pixfmt, 
	//	rescale_method, NULL, NULL, NULL); 
	//-----------------------------
	/*
	//Colorspace
	ret=sws_setColorspaceDetails(img_convert_ctx,sws_getCoefficients(SWS_CS_ITU601),0,
		sws_getCoefficients(SWS_CS_ITU709),0,
		 0, 1 << 16, 1 << 16);
	if (ret==-1) {
		printf( "Colorspace not support.\n");
		return -1;
	}
	*/
	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);                    //Y
			memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/4);      //U
			memcpy(src_data[2],temp_buffer+src_w*src_h*5/4,src_w*src_h/4);  //V
			break;
								}
		case AV_PIX_FMT_YUV422P:{
			memcpy(src_data[0],temp_buffer,src_w*src_h);                    //Y
			memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/2);      //U
			memcpy(src_data[2],temp_buffer+src_w*src_h*3/2,src_w*src_h/2);  //V
			break;
								}
		case AV_PIX_FMT_YUV444P:{
			memcpy(src_data[0],temp_buffer,src_w*src_h);                    //Y
			memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h);        //U
			memcpy(src_data[2],temp_buffer+src_w*src_h*2,src_w*src_h);      //V
			break;
								}
		case AV_PIX_FMT_YUYV422:{
			memcpy(src_data[0],temp_buffer,src_w*src_h*2);                  //Packed
			break;
								}
		case AV_PIX_FMT_RGB24:{
			memcpy(src_data[0],temp_buffer,src_w*src_h*3);                  //Packed
			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);                 //Y
			fwrite(dst_data[1],1,dst_w*dst_h/4,dst_file);               //U
			fwrite(dst_data[2],1,dst_w*dst_h/4,dst_file);               //V
			break;
								}
		case AV_PIX_FMT_YUV422P:{
			fwrite(dst_data[0],1,dst_w*dst_h,dst_file);					//Y
			fwrite(dst_data[1],1,dst_w*dst_h/2,dst_file);				//U
			fwrite(dst_data[2],1,dst_w*dst_h/2,dst_file);				//V
			break;
								}
		case AV_PIX_FMT_YUV444P:{
			fwrite(dst_data[0],1,dst_w*dst_h,dst_file);                 //Y
			fwrite(dst_data[1],1,dst_w*dst_h,dst_file);                 //U
			fwrite(dst_data[2],1,dst_w*dst_h,dst_file);                 //V
			break;
								}
		case AV_PIX_FMT_YUYV422:{
			fwrite(dst_data[0],1,dst_w*dst_h*2,dst_file);               //Packed
			break;
								}
		case AV_PIX_FMT_RGB24:{
			fwrite(dst_data[0],1,dst_w*dst_h*3,dst_file);               //Packed
			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;
}



发布了81 篇原创文章 · 获赞 1 · 访问量 2894

猜你喜欢

转载自blog.csdn.net/qq_42024067/article/details/103367739