前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ffmpeg libswscale实现YUV转RGB

ffmpeg libswscale实现YUV转RGB

作者头像
曾大稳
发布2018-09-11 10:42:27
3.7K0
发布2018-09-11 10:42:27
举报
文章被收录于专栏:曾大稳的博客

libswscale里面实现了各种图像像素格式的转换。

主要函数如下:

代码语言:javascript
复制
//使用参数初始化SwsContext结构体
sws_getContext()
//转换一帧图像
sws_scale()
//释放SwsContext结构体
sws_freeContext()

初始化函数:

代码语言:javascript
复制
//为SwsContext结构体分配内存
sws_alloc_context()
//设置SwsContext结构体的值
av_opt_set()/av_opt_set_XXX()
//初始化SwsContext结构体。
sws_init_context()

这种复杂的方法可以配置一些sws_getContext()配置不了的参数。比如说设置图像的YUV像素的取值范围是JPEG标准(Y、U、V取值范围都是0-255)还是MPEG标准(Y取值范围是16-235,U、V的取值范围是16-240)

获取像素格式信息:

代码语言:javascript
复制
//可以获得指定像素格式的AVPixFmtDescriptor结构体
av_pix_fmt_desc_get()
//通过AVPixFmtDescriptor获取值
av_get_bits_per_pixel() //获取比特数(bpp)

图像拉伸:

代码语言:javascript
复制
SWS_BICUBIC性能比较好;SWS_FAST_BILINEAR在性能和速度之间有一个比好好的平衡。

示例将通过yuv文件生成rgb文件,代码如下:

代码语言:javascript
复制
#include "stdafx.h"


extern "C" {
	#include <libswscale/swscale.h>
	#include <libavutil/opt.h>
	#include <libavutil/imgutils.h>
}


void p(const char * msg, int d = -1123) {
	if (d == -1123) {
		printf_s("%s\n", msg);
	}
	else {
		printf_s("%s  %d \n", msg, d);
	}
}


int yuv2Rgb(FILE *yuvFile,FILE * rgbFile) {

	SwsContext *img_convert_ctx = NULL;

	const AVPixelFormat srcPixelFormat = AV_PIX_FMT_YUV420P;
	const AVPixelFormat dstPixelFormat = AV_PIX_FMT_RGB24;

	const int srcW = 1080;
	const int srcH= 720;

	const int dstW = 540;
	const int dstH = 360;

	uint8_t *src_data[4];
	int src_linesize[4];

	uint8_t *dst_data[4];
	int dst_linesize[4];


	//1. 获得指定像素格式的AVPixFmtDescriptor结构体
	const AVPixFmtDescriptor * pSrcPixFmtDes = av_pix_fmt_desc_get(srcPixelFormat);
	//2. 获得指定像素格式每个像素占用的比特数bpp(Bit Per Pixel) 
	int srcBpp=  av_get_bits_per_pixel(pSrcPixFmtDes);

	const AVPixFmtDescriptor * pDstPixFmtDes = av_pix_fmt_desc_get(dstPixelFormat);
	int dstBpp = av_get_bits_per_pixel(pDstPixFmtDes);


	

	//3. 根据宽高,像素格式分配buffer大小
	if (av_image_alloc(src_data, src_linesize, srcW, srcH, srcPixelFormat, 1) < 0) {
		p("Could not allocate source image");
		return -1;
	}

	if (av_image_alloc(dst_data, dst_linesize, dstW, dstH, dstPixelFormat, 1) < 0) {
		p("Could not allocate source image");
		return -1;
	}

	//4. 为SwsContext结构体分配内存。
	img_convert_ctx = sws_alloc_context();
	//Show AVOption
	av_opt_show2(img_convert_ctx, stdout, AV_OPT_FLAG_VIDEO_PARAM, 0);




	//图像拉伸   SWS_BICUBIC性能比较好;SWS_FAST_BILINEAR在性能和速度之间有一个比好好的平衡。
	//const int rescale_method = SWS_BICUBIC;
	//5. 设置值
	av_opt_set_int(img_convert_ctx, "sws_flags", SWS_BICUBIC | SWS_PRINT_INFO, 0);
	av_opt_set_int(img_convert_ctx, "srcw", srcW, 0);
	av_opt_set_int(img_convert_ctx, "srch", srcH, 0);
	av_opt_set_int(img_convert_ctx, "src_format", srcPixelFormat, 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", dstW, 0);
	av_opt_set_int(img_convert_ctx, "dsth", dstH, 0);
	av_opt_set_int(img_convert_ctx, "dst_format", dstPixelFormat, 0);
	av_opt_set_int(img_convert_ctx, "dst_range", 1, 0);
	sws_init_context(img_convert_ctx, NULL, NULL);//对SwsContext中的各种变量进行赋值

	
	uint8_t *temp_buffer = (uint8_t *)malloc(srcW *srcH *srcBpp / 8);

	int frame_idx = 0;
	while (1){
		if (fread(temp_buffer, 1, srcW*srcH*srcBpp / 8, yuvFile) != srcW * srcH*srcBpp / 8) {
			break;
		}

		switch (srcPixelFormat) {
			case AV_PIX_FMT_GRAY8: {
				memcpy(src_data[0], temp_buffer, srcW*srcH);
				break;
			}
			case AV_PIX_FMT_YUV420P: {
				memcpy(src_data[0], temp_buffer, srcW*srcH);                    //Y
				memcpy(src_data[1], temp_buffer + srcW * srcH, srcW*srcH / 4);      //U
				memcpy(src_data[2], temp_buffer + srcW * srcH * 5 / 4, srcW*srcH / 4);  //V
				break;
			}
			case AV_PIX_FMT_YUV422P: {
				memcpy(src_data[0], temp_buffer, srcW*srcH);                    //Y
				memcpy(src_data[1], temp_buffer + srcW * srcH, srcW*srcH / 2);      //U
				memcpy(src_data[2], temp_buffer + srcW * srcH * 3 / 2, srcW*srcH / 2);  //V
				break;
			}
			case AV_PIX_FMT_YUV444P: {
				memcpy(src_data[0], temp_buffer, srcW*srcH);                    //Y
				memcpy(src_data[1], temp_buffer + srcW * srcH, srcW*srcH);        //U
				memcpy(src_data[2], temp_buffer + srcW * srcH * 2, srcW*srcH);      //V
				break;
			}
			case AV_PIX_FMT_YUYV422: {
				memcpy(src_data[0], temp_buffer, srcW*srcH * 2);                  //Packed
				break;
			}
			case AV_PIX_FMT_RGB24: {
				memcpy(src_data[0], temp_buffer, srcW*srcH * 3);                  //Packed
				break;
			}
			default: {
				printf("Not Support Input Pixel Format.\n");
				break;
			}
		}

		sws_scale(img_convert_ctx, src_data, src_linesize, 0, srcH, dst_data, dst_linesize);//转换像素
		printf("Finish process frame %5d\n", frame_idx);
		frame_idx++;

		switch (dstPixelFormat) {
			case AV_PIX_FMT_GRAY8: {
				fwrite(dst_data[0], 1, dstW*dstH, rgbFile);
				break;
			}
			case AV_PIX_FMT_YUV420P: {
				fwrite(dst_data[0], 1, dstW*dstH, rgbFile);                 //Y
				fwrite(dst_data[1], 1, dstW*dstH / 4, rgbFile);               //U
				fwrite(dst_data[2], 1, dstW*dstH / 4, rgbFile);               //V
				break;
			}
			case AV_PIX_FMT_YUV422P: {
				fwrite(dst_data[0], 1, dstW*dstH, rgbFile);                 //Y
				fwrite(dst_data[1], 1, dstW*dstH / 2, rgbFile);               //U
				fwrite(dst_data[2], 1, dstW*dstH / 2, rgbFile);               //V
				break;
			}
			case AV_PIX_FMT_YUV444P: {
				fwrite(dst_data[0], 1, dstW*dstH, rgbFile);                 //Y
				fwrite(dst_data[1], 1, dstW*dstH, rgbFile);                 //U
				fwrite(dst_data[2], 1, dstW*dstH, rgbFile);                 //V
				break;
			}
			case AV_PIX_FMT_YUYV422: {
				fwrite(dst_data[0], 1, dstW*dstH * 2, rgbFile);               //Packed
				break;
			}
			case AV_PIX_FMT_RGB24: {
				fwrite(dst_data[0], 1, dstW*dstH * 3, rgbFile);               //Packed
				break;
			}
			default: {
				p("Not Support Output Pixel Format.\n");
				break;
			}
		}
	}

	sws_freeContext(img_convert_ctx);
	free(temp_buffer);
	av_freep(&src_data[0]);
	av_freep(&dst_data[0]);

	return 0;


}


int main() {
	FILE* inFile;
	FILE* outFile;
	fopen_s(&inFile,"F:/视频资源/gxsp.yuv", "rb");
	fopen_s(&outFile, "F:/视频资源/gxsp.rgb", "wb");
	yuv2Rgb(inFile,outFile);

	fclose(inFile);
	fclose(outFile);

	getchar();

	return 0;
}

参考链接: libswscale实现YUV转RGB

相关格式转换: 视音频数据处理入门:RGB、YUV像素数据处理

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档