记录FFmpeg遇见的坑

这篇博客记录了在使用FFmpeg过程中遇到的一些问题,包括音频帧克隆失败、解码后编码导致的卡顿、AAC文件时长错误、RTMP流连接超时以及音频编码警告等,并给出了相应的解决办法。同时提到了编译MP3lame和x264的相关步骤,以及内存管理在避免声音问题中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用av_frame_clone可以将一个frame clone后,其实也只是v_frame_alloc()+av_frame_ref()。但是有时候在音频帧的clone后不知道为什么会导致了返回了NULL。这个时候就懵逼了。这个debug进去后发现了一个问题,就是channel_layout没有设置导致的。这个因为是我手动设置解码器,所以忘记弄了,这个一般直接读取的话没有那个错误。


假如你用ffmpeg解码后再进行编码,不知为什么如果源过快时候会发现画面卡顿,音频声音差,只要你将输入源sleep,情况明显改善。这时,其实是内存污染作怪。在ffmpeg里面,解码后的avframe内存还是归ffmpeg管理,当你每次读包解码时候,过快这样就会导致那种情况了。你要做的是用av_frame_clone,那样的话那个就可以了。


假如你将一个音频文件转码成aac文件结尾的文件,这个时候你会发现有个问题是,不知道为什么文件的播放时间总是会比我们实际的时间会长,而且这种长度会随着本来的音频时间长度成线性关系增加。这时,你可能会怀疑自己的编码是不是哪里出了问题。但事实上不是,那是因为aac文件播放本来就有adts,而在ffmpeg里面计算aac文件播放的duration时间,跟踪源码发现ffmpeg里面计算文件是长度是对比视频跟音频的长度,取其最大的。代码如下



static void estimate_timings_from_bit_rate(AVFormatContext *ic)
{
    int64_t filesize, duration;
    int i, show_warning = 0;
    AVStream *st;

    /* if bit_rate is already set, we believe it */
    if (ic->bit_rate <= 0) {
        int64_t bit_rate = 0;
        for (i = 0; i < ic->nb_streams; i++) {
            st = ic->streams[i];
            if (st->codecpar->bit_rate <= 0 && st->internal->avctx->bit_rate > 0)
                st->codecpar->bit_rate = st->internal->avctx->bit_rate;
            if (st->codecpar->bit_rate > 0) {
                if (INT64_MAX - st->codecpar->bit_rate < bit_rate) {
                    bit_rate = 0;
                    break;
                }
                bit_rate += st->codecpar->bit_rate;
            } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 1) {
                // If we have a videostream with packets but without a bitrate
                // then consider the sum not known
                bit_rate = 0;
                break;
            }
        }
        ic->bit_rate = bit_rate;
    }

    /* if duration is already set, we believe it */
    if (ic->duration == AV_NOPTS_VALUE &&
        ic->bit_rate != 0) {
        filesize = ic->pb ? avio_size(ic->pb) : 0;
        if (filesize > ic->internal->data_offset) {
            filesize -= ic->internal->data_offset;
            for (i = 0; i < ic->nb_streams; i++) {
                st      = ic->streams[i];
             
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值