avformat_alloc_output_context2(); //初始化输出码流
avio_open(); //打开输出文件
av_new_stream(); //创建输出码流
avcodec_find_encoder(); //寻找解码器
avcodec_alloc_context3(); //打开解码器上下文
avcodec_open2(); //打开解码器
avformat_write_header(); //写文件头
avcodec_send_frame();
avcodec_receive_packet(); //两步为编码
av_interleaved_write_frame(); //将编码后压缩包写入文件
av_write_trailer(); //写文件尾
主要流程图可以去雷神那看看,对于像我这样的初学者很有帮助。
AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (avcodec == NULL)
{
//创建失败
return -1;
}
AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);
avcodec_context->codec_id = avcodec->id;
avcodec_context->codec_type = AVMEDIA_TYPE_VIDEO;
avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P;
avcodec_context->width = 800;
avcodec_context->height = 600;
avcodec_context->time_base.num =1;
avcodec_context->time_base.den = 25;
avcodec_context->bit_rate = 468000;
avcodec_context->gop_size = 250;
avcodec_context->qmin = 10;
avcodec_context->qmax = 51;
avcodec_context->max_b_frames = 0;
AVDictionary *param = 0;
if (avcodec_context->codec_id == AV_CODEC_ID_H264)
{
av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
}
if (avcodec_open2(avcodec_context, avcodec, ¶m) < 0)
{
//打开失败
return -1;
}
result = avcodec_send_frame(avcodec_context, av_frame);
if(result < 0)
{
cout <<"send during encoding" << endl;
return -1;
}
while(!result)
{
result = avcodec_receive_packet(avcodec_context, av_packet);
if(result == AVERROR_EOF || result == AVERROR(EAGAIN))
break;
else if(result < 0)
{
cout << "receive during encoding" << endl;
return -1;
}
av_packet->stream_index = av_video_stream->index;
result = av_write_frame(avformat_context, av_packet);
current_frame_index ++;
if (result <0)
{
//写入失败
return -1;
}
}
int main(int argc, char *argv[])
{
av_register_all();
AVFormatContext *avformat_context = avformat_alloc_context();
const char *coutFilePath = "out.h264";
AVOutputFormat *avoutput_format = av_guess_format(NULL, coutFilePath, NULL);
avformat_context->oformat = avoutput_format;
if (avio_open(&avformat_context->pb, coutFilePath, AVIO_FLAG_WRITE)<0)
{
return -1;
}
AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (avcodec == NULL)
{
//创建失败
return -1;
}
AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);
avcodec_context->codec_id = avcodec->id;
avcodec_context->codec_type = AVMEDIA_TYPE_VIDEO;
avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P;
avcodec_context->width = 800;
avcodec_context->height = 600;
avcodec_context->time_base.num =1;
avcodec_context->time_base.den = 25;
avcodec_context->bit_rate = 468000;
avcodec_context->gop_size = 250;
avcodec_context->qmin = 10;
avcodec_context->qmax = 51;
avcodec_context->max_b_frames = 0;
AVDictionary *param = 0;
if (avcodec_context->codec_id == AV_CODEC_ID_H264)
{
av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
}
if (avcodec_open2(avcodec_context, avcodec, ¶m) < 0)
{
//打开失败
return -1;
}
if (avformat_write_header(avformat_context, NULL) <0)
{
//写入文件头失败
return -1;
}
int buffer_size = av_image_get_buffer_size(avcodec_context->pix_fmt,
avcodec_context->width, avcodec_context->height, 1);
int y_size = avcodec_context->width * avcodec_context->height;
uint8_t *out_buffer =(uint8_t *)av_malloc(buffer_size);
const char *cinFilePath = "out.yuv";
FILE *in_file = fopen(cinFilePath, "rb");
if (in_file == NULL)
{
return -1;
}
AVFrame *av_frame = av_frame_alloc();
av_frame->width = avcodec_context->width;
av_frame->height = avcodec_context->height;
av_frame->format = AV_PIX_FMT_YUV420P;
av_image_fill_arrays(av_frame->data, av_frame->linesize, out_buffer,
avcodec_context->pix_fmt, avcodec_context->width,
avcodec_context->height, 1);
int i = 0;
AVPacket *av_packet = (AVPacket *)av_malloc(buffer_size);
int result = 0;
int current_frame_index = 1;
while (true)
{
if (fread(out_buffer, 1, y_size * 3 / 2, in_file) <= 0)
{
break;
}
else if (feof(in_file))
{
break;
}
av_frame->data[0] = out_buffer;
av_frame->data[1] = out_buffer + y_size;
av_frame->data[2] = out_buffer + y_size * 5 / 4;
av_frame->pts = i;
i++;
result = avcodec_send_frame(avcodec_context, av_frame);
if(result < 0)
{
cout <<"send during encoding" << endl;
return -1;
}
while(!result)
{
result = avcodec_receive_packet(avcodec_context, av_packet);
if(result == AVERROR_EOF || result == AVERROR(EAGAIN))
break;
else if(result < 0)
{
cout << "receive during encoding" << endl;
return -1;
}
av_packet->stream_index = av_video_stream->index;
result = av_write_frame(avformat_context, av_packet);
current_frame_index ++;
if (result <0)
{
//写入失败
return -1;
}
}
}
av_write_trailer(avformat_context);
avcodec_close(avcodec_context);
av_free(av_frame);
av_free(out_buffer);
av_packet_free(&av_packet);
avio_close(avformat_context->pb);
avformat_free_context(avformat_context);
fclose(in_file);
}