最近想做ffmpeg的H264编码,网上找了好久,多数都是跟这个一样的http://blog.csdn.net/eightdegree/article/details/7425635,于是将其整理了下,下面贴出代码
/* g++ -o test test.cpp -lavformat -lavcodec -lavutil -lz -lm -lpthread -lSDL -lswscale */ #include <stdio.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #include<string.h> #include<malloc.h> //#include <SDL/SDL.h> #pragma pack(1) int main() { typedef struct tagBITMAPFILEHEADER { unsigned short bfType; //2 位图文件的类型,必须为“BM” unsigned long bfSize; //4 位图文件的大小,以字节为单位 unsigned short bfReserved1; //2 位图文件保留字,必须为0 unsigned short bfReserved2; //2 位图文件保留字,必须为0 unsigned long bfOffBits; //4 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位 } BITMAPFILEHEADER;//该结构占据14个字节。 printf("%d\n",sizeof(BITMAPFILEHEADER)); typedef struct tagBITMAPINFOHEADER{ unsigned long biSize; //4 本结构所占用字节数 long biWidth; //4 位图的宽度,以像素为单位 long biHeight; //4 位图的高度,以像素为单位 unsigned short biPlanes; //2 目标设备的平面数不清,必须为1 unsigned short biBitCount;//2 每个像素所需的位数,必须是1(双色), 4(16色),8(256色)或24(真彩色)之一 unsigned long biCompression; //4 位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 unsigned long biSizeImage; //4 位图的大小,以字节为单位 long biXPelsPerMeter; //4 位图水平分辨率,每米像素数 long biYPelsPerMeter; //4 位图垂直分辨率,每米像素数 unsigned long biClrUsed;//4 位图实际使用的颜色表中的颜色数 unsigned long biClrImportant;//4 位图显示过程中重要的颜色数 } BITMAPINFOHEADER;//该结构占据40个字节。 BITMAPFILEHEADER *test=NULL; FILE *file[5]; char *szTxt[5]; int nWidth = 0; int nHeight= 0; int nDataLen=0; int nLen; char csFileName[20]; int fileI ; for (fileI = 1; fileI <= 5; fileI ++) { sprintf(csFileName, "%d.bmp", fileI); printf("%s\n",csFileName); file[fileI - 1] = fopen(csFileName, "rb"); fseek(file[fileI-1],0,2); nLen = ftell(file[fileI-1]); szTxt[fileI -1] = (char *)malloc(nLen); nLen = fread(szTxt[fileI-1],1,nLen,file[fileI-1]); fclose(file[fileI - 1]); BITMAPFILEHEADER bmpFHeader; BITMAPINFOHEADER bmpIHeader; test = &bmpFHeader; memcpy(&bmpFHeader,szTxt[fileI -1],sizeof(BITMAPFILEHEADER)); int nHeadLen = bmpFHeader.bfOffBits - sizeof(BITMAPFILEHEADER); memcpy(&bmpIHeader,szTxt[fileI - 1]+sizeof(BITMAPFILEHEADER),nHeadLen); //nHeadLen nWidth = bmpIHeader.biWidth; nHeight = bmpIHeader.biHeight; szTxt[fileI - 1] += bmpFHeader.bfOffBits; nDataLen = nLen-bmpFHeader.bfOffBits; } printf("file ok\n"); 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); 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("不能打开编码库"); 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]; //图象编码 int outbuf_size=100000; uint8_t * outbuf= (uint8_t*)malloc(outbuf_size); int u_size = 0; FILE *f=NULL; const char * filename = "myData.h264"; f = fopen(filename, "wb"); if (!f) { printf( "could not open %s\n", filename); 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); int got_packet_ptr = 0; av_init_packet(&avpkt); avpkt.data = outbuf; avpkt.size = outbuf_size; u_size = avcodec_encode_video2(c, &avpkt, m_pYUVFrame, &got_packet_ptr); if (u_size == 0) { fwrite(avpkt.data, 1, avpkt.size, f); } } fclose(f); //delete []m_pRGBFrame; //delete []m_pYUVFrame; //delete []rgb_buff; free(outbuf); avcodec_close(c); av_free(c); }
不知道为什么还是找不到X264编码器,希望高手指点。