天天看点

ffmpeg实现RGB封装H264

最近想做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编码器,我已经装了X264,并且重新编译ffmpeg./configure --enable-libx264

不知道为什么还是找不到X264编码器,希望高手指点。