ffmpeg初探(一)----利用sws_getContext实现YUV\RGB像素格式转换

最近需要将ffmpeg解码出来的图片格式转换成想要的格式,因此网上看到了雷神的文章,修改之后

封装成如下函数任意调用,

说明:
    1、 程序中包含两种对于 色彩fmt 转换初始化的方式,实验测试 两种方法
        均可以,使用其中一种即可。
    2、引用该函数之前需要额外定义 :
       //uint8_t *dst_data[4];
       //int dst_linesize[4];
    3、输入的src_data也必须为 *dst_data[]类型
        因为sws_scale函数要求

/*---------------------------------------------------------------------------------------*/
/*
	以下是修改上面的代码,仅利用里面格式转化的部分,
并将其封装成 一个函数。
	 
函数功能:帧格式pixfmt转换
说明:

	1、 程序中包含两种对于 色彩fmt 转换初始化的方式,实验测试 两种方法
        均可以,使用其中一种即可。
	   
	3、输入的src_data也必须为 *dst_data[]类型
	    因为sws_scale函数要求

*/

void format_convert(int src_pixfmt, int src_w, int src_h, uint8_t *src_data,int *src_linesize,
			int dst_pixfmt, int dst_w, int dst_h, uint8_t *dst_data,int *dst_linesize )
{
			
   int dst_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(dst_pixfmt));
   
   uint8_t *dst_data[4];
   int dst_linesize[4];

   int rescale_method=SWS_BICUBIC;
   struct SwsContext *img_convert_ctx;
   
   int ret=0;

   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;
   }
   
   //---------------格式转换 方法(1)--------------
   //转换格式方法(1) 
#if 0	
	   //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);
#endif //格式转换方法(1)
   //-------------------格式转换 方法(1)---------------------------------------------------
   
   //-------------------格式转换 方法(2)---------------------------------------------------
   //转换格式方法(2)
#if 1
	   //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); 
#endif //格式转换方法(2)
	   //---------------格式转换 方法(2)---------------------------------------------------
   
	   
	   //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;
   //  }

   //数据转换	   
   sws_scale(img_convert_ctx, src_data, src_linesize, 0, src_h, dst_data, dst_linesize);

	// 使用转换之后的数据





	//使用之后,根据自己程序的情况找地方释放
	sws_freeContext(img_convert_ctx);

	av_freep(&src_data[0]);
	av_freep(&dst_data[0]);

}

 

下面是参考的雷神的文章:https://blog.csdn.net/leixiaohua1020/article/details/42134965

程序原型如下:

/**
 *
 * 本程序使用libswscale对像素数据进行缩放转换等处理。
 * 它中实现了YUV420P格式转换为RGB24格式,
 * 参考链接:https://blog.csdn.net/leixiaohua1020/article/details/42134965
 */

#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[])
{

	// Src 文件	
	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));

	// dst 文件
	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;
	}
	//---------------格式转换 方法(1)--------------
//转换格式方法(1)	
#if 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);
#endif //格式转换方法(1)
//-------------------格式转换 方法(1)---------------------------------------------------

//-------------------格式转换 方法(2)---------------------------------------------------
//转换格式方法(2)
#if 
	//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); 
#endif //格式转换方法(2)
	//---------------格式转换 方法(2)---------------------------------------------------

	
	//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_RGBA:{

			fwrite(dst_data[0],1,dst_w*dst_h*4,dst_file);               //Packed
			break;
							  }
		case AV_PIX_FMT_BGRA:{

			fwrite(dst_data[0],1,dst_w*dst_h*4,dst_file);               //Packed
			break;
							  }

		case AV_PIX_FMT_RGB24:{

			fwrite(dst_data[0],1,dst_w*dst_h*3,dst_file);               //Packed
			break;
							  }
		case AV_PIX_FMT_BGR24:{

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

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sws_getContextFFmpeg中用于图像换的函数,其函数原型为: ``` 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); ``` 参数说明: - srcW:源图像宽度 - srcH:源图像高度 - srcFormat:源图像像素格式 - dstW:目标图像宽度 - dstH:目标图像高度 - dstFormat:目标图像像素格式 - flags:换标志,可以为0或SWS_FAST_BILINEAR等 - srcFilter:源图像滤波器 - dstFilter:目标图像滤波器 - param:其它参数 使用示例: ``` // 初始化源图像和目标图像的宽度、高度和像素格式 int src_width = 640; int src_height = 480; AVPixelFormat src_pix_fmt = AV_PIX_FMT_RGB24; int dst_width = 320; int dst_height = 240; AVPixelFormat dst_pix_fmt = AV_PIX_FMT_YUV420P; // 分配输入图像和输出图像所需的内存 uint8_t *src_data[4]; int src_linesize[4]; av_image_alloc(src_data, src_linesize, src_width, src_height, src_pix_fmt, 1); uint8_t *dst_data[4]; int dst_linesize[4]; av_image_alloc(dst_data, dst_linesize, dst_width, dst_height, dst_pix_fmt, 1); // 创建SwsContext struct SwsContext *sws_ctx = sws_getContext(src_width, src_height, src_pix_fmt, dst_width, dst_height, dst_pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL); // 换图像 sws_scale(sws_ctx, src_data, src_linesize, 0, src_height, dst_data, dst_linesize); // 释放资源 sws_freeContext(sws_ctx); av_freep(&src_data[0]); av_freep(&dst_data[0]); ``` 该示例代码中,首先初始化源图像和目标图像的宽度、高度和像素格式,并分配输入图像和输出图像所需的内存。然后创建SwsContext,调用sws_scale函数实现图像换,并最后释放资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值