上一篇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
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; inb_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; inb_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
# = # 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