avcodec_decode_audio4已废弃,FFmpeg2.5升级4.1如何解码音频帧
FFmpeg v4.1 替代avcodec_decode_audio4的音频解码方案
FFmpeg从3.0版本开始就已用avcodec_send_packet+avcodec_receive_frame的拆分式接口替换了旧的单步解码接口avcodec_decode_audio4,适配逻辑如下:
前置条件
和旧版本逻辑一致,先完成对应音频解码器的AVCodecContext实例初始化并打开解码器,不需要额外调整初始化逻辑。
具体解码步骤
- 发送待解码的packet到解码器
你不需要修改原有avpkt->data、avpkt->size的赋值逻辑,直接传入持有待解码数据的packet即可:
int ret = avcodec_send_packet(avctx, avpkt);
返回值判断规则:
返回0:packet发送成功
返回
AVERROR(EAGAIN):解码器内部缓存已满,需要先读完所有已解码帧再重试发送返回其他负值:发送出错,直接进入错误处理逻辑即可
循环读取解码完成的frame
// 提前分配好frame用于接收解码结果 AVFrame *decoded_frame = av_frame_alloc(); if (!decoded_frame) { // 内存分配错误处理 return AVERROR(ENOMEM); } while (ret >= 0) { ret = avcodec_receive_frame(avctx, decoded_frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { // 当前没有更多可输出的帧,退出循环等待下一个packet输入 break; } else if (ret < 0) { // 解码出错,释放资源后退出 av_frame_free(&decoded_frame); return ret; } // 此处自行处理解码完成的decoded_frame,比如重采样、播放、写入文件等 // ... // 处理完成后重置frame的引用,方便下次复用 av_frame_unref(decoded_frame); }
注意事项
- 解码流程全部结束时,需要传入NULL packet触发解码器冲刷,输出内部缓存的所有剩余帧:调用
avcodec_send_packet(avctx, NULL)后,再循环调用avcodec_receive_frame直到返回AVERROR_EOF即可 - 如果你是手动分配
avpkt->data缓冲区的场景,发送完成后你仍然需要自行管理该缓冲区的释放,解码器不会接管输入packet的内存所有权 - 新接口内部会自动处理frame的缓冲区管理,不需要每次解码前手动重置frame
内容的提问来源于stack exchange,提问作者just like before
相关产品推荐
相关产品推荐

