libavcodec
:主要实现一系列编码器的实现
一编码/解码常见结构体
(1) AVCodec
:编码器信息
(2) AVCodecContext:编码器上下文
(3)AVFrame
:音视频的原始帧数据,对应的AVPacket
里面的帧是压缩后的帧.
2 内存分配和释放
av_frame_alloc()\av_frame_free()
生成和释放:AVFrame
// 分配编解码器的上下文
avcodec_alloc_context3()/avcodec_free_context
二 解码
avcodec_find_decoder
:查找解码器
AVCodec *codec;
// 获取解码器实例, st 是AVStream
codec = avcodec_find_decoder(st->codecpar->codec_id)(旧版本)
codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO)(新版本)
avcodec_open2
:打开解码器
avcodec_decode_video2
:视频解码(已废弃).
注意在新版本中如ffmpeg4.3.1
中视频解码使用avcodec_send_packet
和avcodec_receive_frame
实现了后台解码,源码如下:
static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
const char *filename)
{
char buf[1024];
int ret;
// 发送数据到ffmpeg,放到解码队列中
ret = avcodec_send_packet(dec_ctx, pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding\n");
exit(1);
}
while (ret >= 0) {
// 在解码队列中,取出frame
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
exit(1);
}
printf("saving frame %3d\n", dec_ctx->frame_number);
fflush(stdout);
/* the picture is allocated by the decoder. no need to
free it */
snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
pgm_save(frame->data[0], frame->linesize[0],
frame->width, frame->height, buf);
}
}
// 新版本源码路径是:/FFmpeg/FFmpeg-iOS-build-script-master/thin/arm64/share/ffmpeg/examples/decode_video.c (需要编译)
对已经h264编码的适配用上述方法解码,结果 ret = avcodec_receive_frame(dec_ctx, frame); ret = -541478725 (错误信息:End of file)
三 编码
avcodec_find_encoder_by_name
:查找编码器,和解码不同的是,通过名字查找.
avcodec_open2
:编码的时候需要设置一些参数,分辨率,帧率等
avcodec_encode_video2
:编码 编解码ffmpeg用的是第三方库比如lib264
,ffmpeg只是二次封装
H264编码一些参数设置
AVCodecContext * codec = NULL;
c = avcodec_alloc_context3(codec);
//libx264
// 查询编解码器
codec = avcodec_find_encoder_by_name(codec_name);
// 码率
c->bit_rate = 400000;
// 分辨率
c->width = 352;
c->height = 288;
// 时间基 随帧率变化 1/25
c->time_base = (AVRational){1, 25};
// 帧率越大 码率越大 流畅度越好
c->framerate = (AVRational){25, 1};
// gop_size:多少帧产生一个关键帧,比如 120帧 c->gop_size = 10 120分成10组,10帧有个关键帧,后面都是参考帧 gop_size设置很小的话:码率增加 关键帧就多了 设置太大 码率减少,关键帧少了
c->gop_size = 10;
// 1 b帧:前后参考帧 max_b_frames 压缩率非常高
// 2 p帧:向前参考帧 参考帧越多 ,压缩率越高 同样编码时长越大,实时性有影响
// 3 i帧:关键帧
c->max_b_frames = 1;
// YUV 420
c->pix_fmt = AV_PIX_FMT_YUV420P;
AAC 编码的一些设置参数设置
AVCodecContext * codec = NULL;
c = avcodec_alloc_context3(codec);
// 比特率64k
c->bit_rate = 64000;
// 采样格式 16位的
c->sample_fmt = AV_SAMPLE_FMT_S16;
// 采样率
c->sample_rate = select_sample_rate(codec);
c->channel_layout = select_channel_layout(codec);
// 通道
c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
结语:在学习ffmpeg其他内容之前,调研一下SDL
.主要为SDL安装,编译程序,窗口创建,SDL事件处理,纹理渲染等.
网友评论