1.添加头文件
///AVCodec 编码器结构体
///AVCodecContext 编码器上下文
///AVFrame 解码后的帧
///结构体的分配与释放
//av_frame_alloc()
//av_frame_free(AVFrame **frame)
// avcodec_alloc_context3(<#const AVCodec *codec#>)
// avcodec_free_context(<#AVCodecContext **avctx#>)
//1.输入参数
//2.查找编码器
//3.创建编码器上下文
//4.设置编码器参数
//5.编码器与编码器上下文绑定到一起
//6.创建输出文件
//7.创建AVFRAME
//8.创建
//9.生成视频内容
//10.编码
int encode_action(AVCodecContext *codec_context,AVFrame *frame,AVPacket *packet, FILE *file) {
int ret = -1;
ret = avcodec_send_frame(codec_context, frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_send_frame error = %s\n",av_err2str(ret));
goto __ERROR;
}
while (ret >= 0) {
ret = avcodec_receive_packet(codec_context, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
} else if (ret < 0) {
return -1;
}
fwrite(packet->data, 1, packet->size, file);
av_packet_unref(packet);
}
__ERROR:
return 0;
}
void media_codec() {
///AVCodec 编码器结构体
///AVCodecContext 编码器上下文
///AVFrame 解码后的帧
///结构体的分配与释放
//av_frame_alloc()
//av_frame_free(AVFrame **frame)
// avcodec_alloc_context3(<#const AVCodec *codec#>)
// avcodec_free_context(<#AVCodecContext **avctx#>)
//解码步骤
// 1.查找解码器
// avcodec_find_decoder(<#enum AVCodecID id#>)
// 2.打开解码器
// avcodec_open2(<#AVCodecContext *avctx#>, <#const AVCodec *codec#>, <#AVDictionary **options#>)
//3.解码
// avcodec_decode_subtitle2(<#AVCodecContext *avctx#>, <#AVSubtitle *sub#>, <#int *got_sub_ptr#>, <#const AVPacket *avpkt#>)
av_log_set_level(AV_LOG_DEBUG);
//1.输入参数
//2.查找编码器
//3.创建编码器上下文
//4.设置编码器参数
//5.编码器与编码器上下文绑定到一起
//6.创建输出文件
//7.创建AVFRAME
//8.创建AVPacket
//9.生成视频内容
//10.编码
//1.输入参数
char *dst = "/Users/king/Desktop/ffmpeg/audio/codec_video.h264";
char *codecname = "libx264";
//2.查找编码器
// avcodec_find_encoder(<#enum AVCodecID id#>)
// c
const AVCodec *codec = NULL;
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
// codec = avcodec_find_encoder_by_name(codecname);
if (codec == NULL) {
av_log(NULL, AV_LOG_ERROR, "cant find codec\n");
goto __ERROR;
}
//3.创建编码器上下文
AVCodecContext *codec_context = NULL;
codec_context = avcodec_alloc_context3(codec);
if (codec_context == NULL) {
av_log(NULL, AV_LOG_ERROR, "cant find codec_context\n");
goto __ERROR;
}
codec_context->width = 640;
codec_context->height = 480;
codec_context->bit_rate = 500000;
codec_context->time_base = (AVRational){1,25};//时间帧
codec_context->framerate = (AVRational){25,1};//帧率
codec_context->gop_size = 10;// 一组帧大小
codec_context->max_b_frames = 1;//B帧数量 B帧数量一般不超过三帧 B帧过多会影响执行效率 直播议案不会要B帧
codec_context->pix_fmt = AV_PIX_FMT_YUV420P; //视频格式
if (codec->id == AV_CODEC_ID_H264) {
av_opt_set(codec_context->priv_data, "preset", "slow", 0);
}
//5.编码器与编码器上下文绑定到一起
int ret = -1;
ret = avcodec_open2(codec_context, codec, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_open2 error = %s\n",av_err2str(ret));
goto __ERROR;
}
//6.创建输出文件
FILE *file = NULL;
file = fopen(dst, "wb");
if(!file) {
av_log(NULL, AV_LOG_ERROR, "file error\n");
goto __ERROR;
}
//7.创建AVFRAME
AVFrame *frame = av_frame_alloc();
if(!frame) {
av_log(NULL, AV_LOG_ERROR, "frame error\n");
goto __ERROR;
}
frame->width = codec_context->width;
frame->height = codec_context->height;
frame->format = codec_context->pix_fmt;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "av_frame_get_buffer error = %s\n",av_err2str(ret));
goto __ERROR;
}
//8.创建AVPacket
AVPacket *packet = NULL;
packet = av_packet_alloc();
if(!packet) {
av_log(NULL, AV_LOG_ERROR, "packet error\n");
goto __ERROR;
}
//9.生成视频内容
for (int i = 0; i < 25 * 10; i++) {
/// 确保frame中的data'有效
ret = av_frame_make_writable(frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "av_frame_make_writable error\n");
goto __ERROR;
}
/// Y分量
for (int y = 0; y < codec_context->height; y++) {
for (int k = 0; k < codec_context->width; k++) {
frame->data[0][y *frame->linesize[0] + k] = k + y + i * 3;
}
}
/// UV分量
for (int y = 0; y < codec_context->height/2; y++) {
for (int k = 0; k < codec_context->width/2; k++) {
frame->data[1][y * frame->linesize[1] + k] = 128 + y + i * 2;
frame->data[2][y * frame->linesize[2] + k] = 64 + y + i * 5;
}
}
frame->pts = i;
//10.编码
ret = encode_action(codec_context, frame, packet,file);
if (ret == -1) {
goto __ERROR;
}
}
ret = encode_action(codec_context, frame, packet,file);
__ERROR:
if (codec_context) {
avcodec_close(codec_context);
avcodec_free_context(&codec_context);
}
if(frame) {
av_frame_free(&frame);
}
if (packet) {
av_packet_free(&packet);
}
if(file) {
fclose(file);
}
}