av_register_all();
const char *inFilename = "/home/16THDD/xieyingbo/xieyingbo/big_buck_bunny.yuv";
const char *outFilename = "/home/16THDD/xieyingbo/xieyingbo/big_buck_bunny.264";
AVFormatContext *pFormatCtx = NULL;
int ret = avformat_open_input(&pFormatCtx, inFilename, NULL, NULL);
if(ret != 0)
{
printf("%s\n", "open input format error.");
}
int width = 640, height = 360; //源文件分辨率
AVRational avrational; //设置时间基
avrational.den = 1;
avrational.num = 30; //30(30帧 fps)
//1.查找编码器
AVcodec *encodec = avcodec_find_encoder_by_name("libx264");
if(NULL == encodec)
{
printf("%s\n", "find encodec error.");
}
//2.创建编码器上下文
AVCodecContext *encodeCtx = avcodec_alloc_context3(encodec);
if(NULL == encodecCtx)
{
printf("%s\n", "avcodec alloc context3 error.");
}
//3.设置编码参数(不设置的话为默认参数)
encodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; //视频还是音频
encodecCtx->pix_fmt = AV_PIX_FMT_YUV420P; //颜色空间
encodecCtx->width = width;
encodecCtx->height = height;
encodecCtx->time_base = avrational; //时间基
encodecCtx->bit_rate = 4096000; //比特率(每秒传输多少数据,比特率越大,图像质量越好)
encodecCtx->max_b_frames = 2; //最大连续B帧(减少B帧会减小数据量,但是会影响解码效率)
encodecCtx->gop_size = 50; //I帧间隔
//4.打开编码器
ret = avcodec_open2(encodecCtx, encodec, NULL);
if(ret <= 0)
{
printf("%s\n", "avcodec open encodecCtx error.");
}
//5.读取yuv数据
FILE *src_fp = fopen(inFilename, "rb");
if(NULL == src_fp)
{
printf("%s\n", "open inFilename error.");
}
FILE *dst_fp = fopen(outFilename, "wb+");
if(NULL == dst_fp)
{
printf("%s\n", "open outFilename error.");
}
AVFrame *avframe = av_frame_alloc(); //申请frame内存
int framesize = av_image_get_buffer_size(encodecCtx->pix_fmt, width, height, 1); //获取转换空间大小
uint8_t *frameBuffer = av_malloc(framesize); //申请内存空间
av_image_fill_arrays(avframe->data, avframe->linesize, frameBuffer, encodecCtx->pix_fmt, 640, 360); //把转换后的连续空间打包到avframe中
avframe->format = encodecCtx->pix_fmt;
avframe->width = width;
avframe->height = height;
int picturesize = width * height;
AVPacket avpacket;
int count = 0;
while(fread(frameBuffer, 1, picturesize *3/2, src_fp) == picturesize *3/2)
{
//YUV420 Y 1 U 1/4 V 1/4
avframe->data[0] = frameBuffer;
avframe->data[1] = frameBuffer + picturesize;
avframe->data[2] = frameBuffer + picturesize +picturesize / 4;
count++;
avframe->pts = count; //表示这一帧的展示顺序,不是时间戳
}
encodeVideo(encodecCtx, avframe, *packet, dst_fp);
void encodeVideo(AVCodecContext *enCodecCtx, AVFrame *frame, AVPacket *packet, FILE *dst_fp)
{
//6.开始编码
int ret = avcodec_send_frame(enCodecCtx, frame);
if(ret < 0)
{
printf("%s\n", "avcodec send frame failed.");
}
while(ret >= 0)
{
ret = avocdec_receive_packet(encodecCtx, packet);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) //没有数据了
{
break;
}
else if(ret < 0)
{
printf("%s\n", "encodec frame failed.");
return;
}
fwrite(packet->data, 1, packet->size, dst_fp);
av_packet_unref(&packet);
}
}