FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

本文介绍了FFMPEG的swscale库如何实现YUV、RGB等不同格式视频原始数据间的转换及分辨率变换。通过设置转换格式和调用sws_getContext(),可以将数据保存为RGB24或其他格式。FFMPEG中的图像数据分为planar(如YUV420P)和packed(如RGB24、UYVY)两种存储方式,具体格式的属性可在pixfmt.h文件中查看。
摘要由CSDN通过智能技术生成

FFMPEG中的swscale提供了视频原始数据(YUV420,YUV422,YUV444,RGB24...)之间的转换,分辨率变换等操作,使用起来十分方便,在这里记录一下它的用法。

swscale主要用于在2个AVFrame之间进行转换。
下面来看一个视频解码的简单例子,这个程序完成了对"北京移动开发者大会茶歇视频2.flv"(其实就是优酷上的一个普通视频)的解码工作,并将解码后的数据保存为原始数据文件(例如YUV420,YUV422,RGB24等等)。其中略去了很多的代码。

//ffmpeg simple player
//
//媒资检索系统子系统
//
//2013 雷霄骅 leixiaohua1020@126.com
//中国传媒大学/数字电视技术
//
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
	AVFormatContext	*pFormatCtx;
	int				i, videoindex;
	AVCodecContext	*pCodecCtx;
	AVCodec			*pCodec;
	char filepath[]="北京移动开发者大会茶歇视频2.flv";
	av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){
		printf("无法打开文件\n");
		return -1;
	}
	
	......
	
		AVFrame	*pFrame,*pFrameYUV;
		pFrame=avcodec_alloc_frame();
		pFrameYUV=avcodec_alloc_frame();
		uint8_t *out_buffer;

		out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height)];
		avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
/*
		out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];
		avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);*/

/*
		out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_UYVY422, pCodecCtx->width, pCodecCtx->height)];
		avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_UYVY422, pCodecCtx->width, pCodecCtx->height);
		out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV422P, pCodecCtx->width, pCodecCtx->height)];
		avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV422P, pCodecCtx->width, pCodecCtx->height);*/
		
		......
		
		FILE *output=fopen("out.rgb","wb+");
		//------------------------------
		while(av_read_frame(pFormatCtx, packet)>=0)
		{
			if(packet->stream_index==videoindex)
			{
				ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
				
				if(ret < 0)
				{
					printf("解码错误\n");
					return -1;
				}
				if(got_picture)
				{
					/*img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_UYVY422, SWS_BICUBIC, NULL, NULL, NULL); 
					sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
					img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV422P, SWS_BICUBIC, NULL, NULL, NULL); 
					sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);*/
					//转换
					img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); 
					sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
					
					
					//RGB
					fwrite(pFrameYUV->data[0],(pCodecCtx->width)*(pCodecCtx->height)*3,1,output);
					/*
					//UYVY
					fwrite(pFrameYUV->data[0],(pCodecCtx->width)*(pCodecCtx->height),2,output);
					//YUV420P
					fwrite(pFrameYUV->data[0],(pCodecCtx->width)*(pCodecCtx->height),1,output);
					fwrite(pFrameYUV->data[1],(pCodecCtx->width)*(pCodecCtx->height)/4,1,output);
					fwrite(pFrameYUV->data[2],(pCodecCtx->widt
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值