yuv数据生成器

1.YUV格式说明

上一篇yuv文章说明
从存储格式以及像素采样对yuv进行了简要说明,更为详细的阐述可参考 : https://blog.csdn.net/byhook/article/details/84037338
以下是重点:
YUV420P,Y,U,V三个分量都是平面格式,分为I420和YV12。I420格式和YV12格式的不同处在U平面和V平面的位置不同。在I420格式中,U平面紧跟在Y平面之后,然后才是V平面(即:YUV);但YV12则是相反(即:YVU)。
YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12与NV21类似,U 和 V 交错排列,不同在于UV顺序。
I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UVUV =>YUV420SP
NV21: YYYYYYYY VUVU =>YUV420SP

2.YUV生成器

参考JM8.6相关configure配置,模拟出基于配置参数的动态yuv生成器,并通过JM8.6中encode_extended.cfg验证了生成yuv数据的正确性。
2.1构造配置参数
typedef struct
{
   char Inputfilenme[128];
   int FrameDecoder;
   char OutputFileName[128];
   int clCount;
   int YUVSWSCALE;
   int YUVOUTPUT;
public:
   void parser(int argc,char*argv[]);
   char *GetConfigFileContent (const char*filename);
   void ParseContent (char *buf, int bufsize);
}InputParameters;

使用vs2010环境编写,Inputfilenme表示输入视频文件名称,OutputFileName为输出yuv文件,FrameDecoder表示输出的帧数,YUVTYPE表示的是输出类型,YUVOUTPUT表示是否进行yuv文件输出(默认为1)

ConfigMapping cinfigMap[] = {
	{"InputFileName", &configinput.Inputfilenme,  1},
	{"OutputFileName", &configinput.OutputFileName,1},
	{"FrameDecoder",  &configinput.FrameDecoder,  0},
	{"YUVTYPE",  &configinput.YUVSWSCALE,  0},
	{"YUVOUTPUT",  &configinput.YUVOUTPUT,  0},
};

解析文件参数调用逻辑如下:

	memset (&configinput, 0, sizeof (InputParameters));
	configinput.parser(argc,argv);
	AV_Pareser *pParser=new AV_Pareser(configinput.Inputfilenme);

具体的音视频解析类为如下定义

AV_Pareser::AV_Pareser(const char* filename)
{
	g_filename = filename;
	av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	avformat_open_input(&pFormatCtx,g_filename,NULL,NULL);
	if(avformat_find_stream_info(pFormatCtx,NULL)<0){
		printf("Couldn't find stream information.\n");
	}
	m_pVideoId = 0;
}


AV_Pareser::~AV_Pareser(void)
{
}

void AV_Pareser::Set_FormatCtx(struct AVFormatContext*ForamtCtx)
{
   pFormatCtx = ForamtCtx;
}

AVCodec*AV_Pareser::Get_Video_Codec()
{
	int videoindex=-1;
	AVCodec * pCodec = NULL;
	for(int i=0; i<pFormatCtx->nb_streams; i++) 
	if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
		videoindex=i;
		break;
    }
	m_pVideoId = videoindex;
	pCodec = avcodec_find_decoder(pFormatCtx->streams[videoindex]->codec->codec_id);
    return pCodec;
}

AVCodec*AV_Pareser::Get_Audio_Codec()
{
	int audioindex=-1;
	AVCodec * pCodec = NULL;
	for(int i=0; i<pFormatCtx->nb_streams; i++) 
	if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
		audioindex=i;
		break;
	}
	//m_pVideoId = videoindex;
	pCodec = avcodec_find_decoder(pFormatCtx->streams[audioindex]->codec->codec_id);
	return pCodec;
}

encoder_extended.cfg文件如下配置

# New Input File Format is as follows
# <ParameterName> = <ParameterValue> # Comment
#
# See configfile.h for a list of supported ParameterNames


##########################################################################################
# Files
##########################################################################################
InputFileName             = "bigbuckbunny_480x272.h264"       # Input sequence h264 file
OutputFileName             = "bigbuckbunny_480x272.yuv"    # output yuv
FrameDecoder             = 1      # output frame . (0-N)
YUVTYPE             = 0     # YUV format 422P==4 420P==0 YUYV=1 NV21=26 NV12=25
YUVOUTPUT           = 1      # output yuv

需要根据h264文件的帧数,修改FrameDecoder的帧数,注意FrameDecoder的值小于文件帧数

sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, 
	pFrameYUV->data, pFrameYUV->linesize);
if(configinput.YUVSWSCALE == 4) 
{
	fwrite(pFrameYUV->data[0],1,y_size,fp_out);     //Y    //422P
	fwrite(pFrameYUV->data[1],1,y_size/2,fp_out);   //U
	fwrite(pFrameYUV->data[2],1,y_size/2,fp_out);   //V
} else if(configinput.YUVSWSCALE == 0) {
	fwrite(pFrameYUV->data[0],1,y_size,fp_out);     //Y  					//420P
	fwrite(pFrameYUV->data[1],1,y_size/4,fp_out);   //U
	fwrite(pFrameYUV->data[2],1,y_size/4,fp_out);   //V
} else if(configinput.YUVSWSCALE == 1)
{
	fwrite(pFrameYUV->data[0],1,y_size*2,fp_out);     //Y      //YUYV
} else if(configinput.YUVSWSCALE == 26 || configinput.YUVSWSCALE == 25)
{
	fwrite(pFrameYUV->data[0],1,y_size,fp_out);     //Y    two-plane 420P
	fwrite(pFrameYUV->data[1],1,y_size/2,fp_out);   //U
} else
{
	printf("not support!\n");
}

资源链接
https://download.csdn.net/download/zhiyanzhai563/12020326

发布了38 篇原创文章 · 获赞 5 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zhiyanzhai563/article/details/103447274