您的位置:首页 > 编程语言 > C语言/C++

ffmpeg实现RGB封装H264

2013-01-23 15:53 323 查看
最近想做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编码器,希望高手指点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cc++