首页 > 代码库 > 使用ffmpeg将图片编码为x264视频文件

使用ffmpeg将图片编码为x264视频文件

  ffmpeg开源库,实现将bmp格式的图片编码成x264文件。参考资料:http://blog.csdn.net/eightdegree/article/details/7425635#reply

  自己根据博客的代码,vs2010搭建的测试环境。资源下载 

   具体代码:

#define _AFXDLL  
#include<afxwin.h> 
#ifdef  __cplusplus
extern "C" {
#endif

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
	void main()
	{
		CFile file[5];
		BYTE *szTxt[5];

		int nWidth = 0;
		int nHeight= 0;

		int nDataLen=0;

		int nLen;

		CString csFileName;
		for (int fileI = 1; fileI <= 5; fileI ++)
		{
			csFileName.Format("%d.bmp", fileI);
			file[fileI - 1].Open(csFileName,CFile::modeRead | CFile::typeBinary);
			nLen = file[fileI - 1].GetLength();

			szTxt[fileI -1] = new BYTE[nLen];
			file[fileI - 1].Read(szTxt[fileI - 1], nLen);
			file[fileI - 1].Close();

			//BMP bmi;//BITMAPINFO bmi;
			//int nHeadLen = sizeof(BMP);
			BITMAPFILEHEADER bmpFHeader;
			BITMAPINFOHEADER bmpIHeader;
			memcpy(&bmpFHeader,szTxt[fileI -1],sizeof(BITMAPFILEHEADER));

			int nHeadLen = bmpFHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
			memcpy(&bmpIHeader,szTxt[fileI - 1]+sizeof(BITMAPFILEHEADER),nHeadLen);

			nWidth = bmpIHeader.biWidth;// 464;// bmi.bmpInfo.bmiHeader.biWidth;// ;
			nHeight = bmpIHeader.biHeight;//362;// bmi.bmpInfo.bmiHeader.biHeight;// ;

			szTxt[fileI - 1] += bmpFHeader.bfOffBits;
			nDataLen = nLen-bmpFHeader.bfOffBits;
		}
		getchar();
		av_register_all();
		avcodec_register_all();
		AVFrame *m_pRGBFrame =  new AVFrame[1];  //RGB帧数据  
		AVFrame *m_pYUVFrame = new AVFrame[1];;  //YUV帧数据
		AVCodecContext *c= NULL;
		AVCodecContext *in_c= NULL;
		AVCodec *pCodecH264; //编码器
		uint8_t * yuv_buff;//

		//查找h264编码器
		pCodecH264 = avcodec_find_encoder(CODEC_ID_H264);
		if(!pCodecH264)
		{
			fprintf(stderr, "h264 codec not found\n");
			getchar();
			exit(1);
		}

		c= avcodec_alloc_context3(pCodecH264);
		c->bit_rate = 3000000;// put sample parameters 
		c->width =nWidth;// 
		c->height = nHeight;// 

		// frames per second 
		AVRational rate;
		rate.num = 1;
		rate.den = 25;
		c->time_base= rate;//(AVRational){1,25};
		c->gop_size = 10; // emit one intra frame every ten frames 
		c->max_b_frames=1;
		c->thread_count = 1;
		c->pix_fmt = PIX_FMT_YUV420P;//PIX_FMT_RGB24;

		//av_opt_set(c->priv_data, /*"preset"*/"libvpx-1080p.ffpreset", /*"slow"*/NULL, 0);
		//打开编码器
		if(avcodec_open2(c,pCodecH264,NULL)<0){
			printf("avcodec_open2 failed\n");
			TRACE("不能打开编码库");
			getchar();
		}

		int size = c->width * c->height;

		yuv_buff = (uint8_t *) malloc((size * 3) / 2); // size for YUV 420 

		//将rgb图像数据填充rgb帧
		uint8_t * rgb_buff = new uint8_t[nDataLen];

		//图象编码 outbuf_size太小会报错,图像清晰度也会差
		int outbuf_size = 900000;
		uint8_t * outbuf= (uint8_t*)malloc(outbuf_size); 
		int u_size = 0;
		FILE *f=NULL; 
		char * filename = "myData.h264";
		f = fopen(filename, "wb");
		if (!f)
		{
			TRACE( "could not open %s\n", filename);
			getchar();
			exit(1);
		}

		//初始化SwsContext
		SwsContext * scxt = sws_getContext(c->width,c->height,PIX_FMT_BGR24,c->width,c->height,PIX_FMT_YUV420P,SWS_POINT,NULL,NULL,NULL);

		AVPacket avpkt;

		//AVFrame *pTFrame=new AVFrame
		for (int i=0;i<250;++i)
		{

			//AVFrame *m_pYUVFrame = new AVFrame[1];

			int index = (i / 25) % 5;
			memcpy(rgb_buff,szTxt[index],nDataLen);

			avpicture_fill((AVPicture*)m_pRGBFrame, (uint8_t*)rgb_buff, PIX_FMT_RGB24, nWidth, nHeight);

			//将YUV buffer 填充YUV Frame
			avpicture_fill((AVPicture*)m_pYUVFrame, (uint8_t*)yuv_buff, PIX_FMT_YUV420P, nWidth, nHeight);

			// 翻转RGB图像
			m_pRGBFrame->data[0]  += m_pRGBFrame->linesize[0] * (nHeight - 1);
			m_pRGBFrame->linesize[0] *= -1;                   
			m_pRGBFrame->data[1]  += m_pRGBFrame->linesize[1] * (nHeight / 2 - 1);
			m_pRGBFrame->linesize[1] *= -1;
			m_pRGBFrame->data[2]  += m_pRGBFrame->linesize[2] * (nHeight / 2 - 1);
			m_pRGBFrame->linesize[2] *= -1;


			//将RGB转化为YUV
			sws_scale(scxt,m_pRGBFrame->data,m_pRGBFrame->linesize,0,c->height,m_pYUVFrame->data,m_pYUVFrame->linesize);

			static int got_packet_ptr = 0;
			av_init_packet(&avpkt);
			avpkt.data = http://www.mamicode.com/outbuf;>
 完全按照博客中的代码测试发现会报下面的信息,而且在播放过程中,画面都是模糊的。修改了outbuff_size的大小解决了这个问题。



 

疑问:为什么要循环250次?有知道麻烦解答下!
for (int i=0;i<250;++i)


使用ffmpeg将图片编码为x264视频文件