首页 > 其他分享 >FFMpeg笔记(十四)继续说说FFmpeg 升级6.1 遇到的那些坑

FFMpeg笔记(十四)继续说说FFmpeg 升级6.1 遇到的那些坑

时间:2024-06-08 16:11:51浏览次数:23  
标签:seek 读取 FFmpeg 6.1 pb 版本 delta EOF FFMpeg

一、mp4 秒播率下降

    灰度阶段发现秒播率略低0.x%,以为是灰度的数据抖动。上线后短视频业务方找过来,说秒播率明显下降。一起分析,发现业务方不止关心1秒秒播率,也关心首次播放vv 的200ms 秒播率,筛选出来发现数据大降。。然后我就开始分析。思路是将起播分为多个阶段,查数据看哪个阶段的耗时有明显增加,最终将问题局限在mp4 视频avformat_find_stream_info 阶段耗时大涨,普通hls 视频不存在问题。

    接下来重点分析avformat_find_stream_info 流程,重点是try_decode_frame 尝试解码获取解码器必要信息,和读取了多少数据用于探测两个步骤。try_decode_frame 对于mp4 格式一般是不需要执行的,本地验证也是如此。读取的字节数FFmpeg也有记录,对比了下新老版本,字节数一致。会不会是新老版本的代码优化上不一致,导致新版本的执行效率低于老版本?看了一眼数据,再执行效率低下也不至于增加几百ms。再苦思冥想了3天还是没解决,弹尽粮绝了,已经准备掏出手机,BOSS直聘,启动投递附件简历!LeetCode 也练习了一波接雨水,恢复了点自信。

    转机出现在线上拉取的一份日志,和网络团队的同事一起分析的时候,发现起播阶段底层在读取网络数据的时候,经常要读取几百KB,这个数字超过了业务方预下载数据的字节数,导致进行了网络请求(耗时点),同时我们设置的probesize 也就几十KB。网络的同事提示我,会不会是新版本起播时读取的字节数多于老版本,导致秒播率下降?这个问题我也不是没想过,但只是局限在avformat_find_stream_info 内部的readsize统计,底层avio 读取网络数据数据的字节数没有统计过,对比发现,新版本在起播阶段会多读取几百KB字节,问题大概率就是这了,然后断点向上反查,最终定位到问题。

    FFmpeg 6.1 在读取mp4 视频时,会读取一部分字节数来获取流信息。新版本有两个commit为了解决mp4 视频有多个轨道时,一些特殊情况导致的必须获取更多数据才能拿到全部视频流信息:

void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
{
   ......
                    int64_t cur_delta;
                    if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance)
                        continue;
                    cur_delta = FFABS(e1->pos - e2->pos); // ABS 导致一个比较大的负值变成了正值
                    if (cur_delta < (1 << 23))
                        pos_delta = FFMAX(pos_delta, cur_delta);
                    break;
                }
            }
        }
    }

    pos_delta *= 2;
    ctx = ffiocontext(s->pb);
    /* XXX This could be adjusted depending on protocol*/
    if (s->pb->buffer_size < pos_delta) {
        av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);

        /* realloc the buffer and the original data will be retained */
        if (ffio_realloc_buf(s->pb, pos_delta)) { // 使用比较大的正值创建了大的buffer,在填充buffer 时,就需要读取更多的网络数据,如果没有,就需要进行网络请求
            av_log(s, AV_LOG_ERROR, "Realloc buffer fail.\n");
            return;
        }

        ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, pos_delta/2);
    }

    ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip);
}

  看commit message,是为了解决特定情况下的问题。但不得不说,我认为这是新版本的一个瑕疵。为了解决一个特定的问题,让普通的mp4 文件在起播的关键阶段多读取了几百KB 的网络数据,导致起播变慢,这是不应该的。不清楚最新版本解决了没有,看提交记录,是6.0 -> 6.1版本才新增的。这样看来,盲目升级最新版本也不是什么好事。ε(┬┬﹏┬┬)3

二、iOS 包大小异常

    在灰度阶段,发现iOS 包大小异常增加15M!!平时增加几百k 都要求爷爷告奶奶,现在这个数字,感觉我又要打开BOSS直聘了。检查每个文件的大小后发现,tx_template.c 文件定义了几个超大数组,这些超大数组被linkmap 识别为占用包大小。

    分析后发现,未初始化的超大数组,实际是以common段的方式存在在二进制中,最终是不占用包大小的,实际验证后也是如此。linkmap的计算方式没有考虑BSS 段中的common 类别,是linkmap 计算错误。

三、自研数据协议导致的EOF 读取不到

    在FFmpeg 4.x的版本,av_read_frame 增加了这样一个逻辑,当avio 返回EOF的时候,av_read_frame 会检查pb->error 是否为0,如果不为0的时候,返回具体的错误,而不返回EOF。在我们自研的数据协议里,当发生seek 打断的时候,返回AVERROR_EXIT ,导致了线上偶先seek 后读不到EOF,始终读到AVERROR_EXIT,无法结束视频。

static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
{
     ......
    /* A demuxer might have returned EOF because of an IO error, let's
     * propagate this back to the user. */
    if (ret == AVERROR_EOF && s->pb && s->pb->error < 0 && s->pb->error != AVERROR(EAGAIN))
        ret = s->pb->error;

    return ret;
}

  比较奇怪的是,在网络请求慢时,被seek 打断一般都返回AVERROR_EOF,可能其他软件兼容了这个错误,增加兼容逻辑后解决。

标签:seek,读取,FFmpeg,6.1,pb,版本,delta,EOF,FFMpeg
From: https://www.cnblogs.com/jiayayao/p/18238651

相关文章

  • FFmpeg开发笔记(二十七)解决APP无法访问ZLMediaKit的直播链接问题
    ​上一篇文章介绍了如何通过ZLMediaKit实现视频推拉流,并使用VLC播放器验证视频直播地址。即使不用VLC播放器,直接在Qt工程的C++代码中调用FFmpeg的API,也能访问ZLMediaKit的直播地址,并正常渲染视频画面。关于如何在Qt工程中引入FFmpeg,可参考《FFmpeg开发实战:从零基础到短视频上线》......
  • 6.1
    IPv6vs.IPv4我一直对IPv6这个名字感到困惑,因为我觉得IPv4名字来源于它用来表示32位的四个字节,所以IPv6应该被称为IP16。但实际上,这只是协议的版本号。在IPv4推出之前,曾存在过IPv1、IPv2和IPv3,它们主要用于内部研究IP协议,后来被我们现在的IPv4所取代。在上世纪80年代,还提出过IP......
  • FFmpeg结构体:AVInputFormat
    1.描述AVInputFormat是类似COM接口的数据结构,表示输入文件容器格式,着重于功能函数,一种文件容器格式对应一个AVInputFormat结构,在程序运行时有多个实例,位于avoformat.h文件中。2.结构体定义1typedefstructAVInputFormat{2/**3*Acommaseparated......
  • ffmpeg结构体解析-AVClass 和 AVOption
    AVClass先来看AVClass的结构如下:/***DescribetheclassofanAVClasscontextstructure.Thatisan*arbitrarystructofwhichthefirstfieldisapointertoan*AVClassstruct(e.g.AVCodecContext,AVFormatContextetc.).*/typedefstructAVClass{......
  • Android视频开发入门: VideoView、MediaPlayer、 FFmpeg、exoplayer...
    现在,视频功能是越来越普遍的需求。本文将提供一个关于Android视频开发的入门指南,帮助读者快速掌握视频播放、录制和处理等基本功能。1、概述在Android平台上,视频开发主要涉及以下几个方面:视频播放与控制视频录制与处理视频编解码与格式转换视频流媒体与直播接下来,我......
  • 无缝融合:使用 Python 和 PyFFmpeg 合并视频的完整指南
    前言在当今数字化时代,视频内容无处不在。从社交媒体到在线教育,视频已经成为我们生活中不可或缺的一部分。但是,有时候我们可能需要将多个视频片段合并成一个,创造出更丰富、更有吸引力的内容。而今天,我们将向您展示如何使用Python和PyFFmpeg工具实现这一目标。准备工作:安装P......
  • 音频剪裁大师:使用 Python 和 ffmpeg 分割音频的完整指南
    前言在音频处理中,有时候我们需要对音频文件进行分割,提取其中的部分内容以满足特定需求。而Python提供了许多强大的工具和库来实现这一目标,其中ffmpeg是一个功能强大的工具,它不仅支持音频分割,还能进行音频转码、合并、提取等操作。本文将介绍如何使用Python和ffmpeg来分......
  • 6.1-6.3学习笔记
     Linux学习Linux的所有文件均在根目录/下;在Linux中均使用反斜杠/;Linux系统中文件系统的层次结构:    /bin  存放系统的核心命令以及可执行的文件,如cp、cat命令等;    /boot 启动Linux系统所用的文件,如内核文件;    /dev  设备文件,用于访......
  • Linux ffmpeg 离线安装
    linux版本下载地址:http://www.ffmpeg.org/releases/4.3.1 下载地址:http://ffmpeg.org/releases/ffmpeg-4.3.1.tar.gz 配套组件yasm下载http://www.tortall.net/projects/yasm/releases/http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz yasm安......
  • YOLOv8输出视频.avi有损转.mp4(使用ffmpeg)
    问题:在使用YOLOv8模型直接推理视频后,存储的视频文件格式默认为.avi格式,且推理出的视频占用空间巨大,亲测500多M的视频推理完保存的结果视频有25个多G,此时当视频在服务器上时,想预览就需要下载至本地,对于这么大的视频要耗费大量时间。解决办法:可以使用ffmpeg视频处理工具对.avi格......