- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试优化一款播放视频的软件,它在内部使用 FFmpeg 库进行解码。我们发现,在一些大型(4K,60fps)视频中,解码一帧的时间有时比应该显示该帧的时间要长;遗憾的是,由于问题域,简单地缓冲/跳过帧不是一种选择。
但是,FFmpeg 可执行文件似乎能够以大约 2 倍的速度很好地解码有问题的视频,所以我一直在努力找出我们做错了什么。
我已经编写了一个非常精简的解码器程序用于测试;来源是here (大约 200 行)。从分析来看,解码过程中的一个主要瓶颈似乎是 avcodec_send_packet()
函数,每次调用最多可能需要 50 毫秒。但是,在 FFmpeg 中测量相同的调用显示出奇怪的行为:
(这些是解码 4K 25fps VP9 编码视频时每次调用 avcodec_send_packet() 所花费的时间,以毫秒为单位。)
基本上,似乎当 FFmpeg 使用此函数时,它只需要任意多的时间来完成每 N 个调用,其中 N 是用于解码的线程数。但是,我的测试解码器和实际产品都使用4线程进行解码,并没有发生这种情况;使用基于帧的线程时,测试解码器的行为类似于仅使用 1 个线程的 FFmpeg。这似乎表明我们根本没有使用多线程,但我们仍然看到通过使用更多线程提高了性能。
FFmpeg 的结果平均比我们的解码器快两倍,所以很明显我们做错了什么。我一直在阅读 FFmpeg 的源代码以试图找到任何线索,但到目前为止我还没有找到。
我的问题是:FFmpeg 在这里做了哪些我们没有做的事情?或者,我们如何提高解码器的性能?
非常感谢任何帮助。
最佳答案
我遇到了同样的问题。我花了很长时间才想出一个解决方案,我想在这里分享以供将来引用:
为解码器启用多线程。默认情况下,解码器仅使用一个线程,具体取决于解码器,多线程可以大大加快解码速度。
假设你有 AVFormatContext *format_ctx
,一个匹配的编解码器 AVCodec* codec
和 AVCodecContext* codec_ctx
(分配使用 avcodec_alloc_context3
).
在打开编解码器上下文(使用avcodec_open2
)之前,您可以配置多线程。检查编解码器的功能以确定您可以使用哪种多线程:
// set codec to automatically determine how many threads suits best for the decoding job
codec_ctx->thread_count = 0;
if (codec->capabilities | AV_CODEC_CAP_FRAME_THREADS)
codec_ctx->thread_type = FF_THREAD_FRAME;
else if (codec->capabilities | AV_CODEC_CAP_SLICE_THREADS)
codec_ctx->thread_type = FF_THREAD_SLICE;
else
codec_ctx->thread_count = 1; //don't use multithreading
我发现的另一个加速方法如下:继续向解码器发送数据包(这就是 avcodec_send_packet()
正在做的事情)直到你得到 AVERROR(EAGAIN)
作为返回值。这意味着内部解码器缓冲区已满,您首先需要收集解码帧(但请记住在解码器再次为空后再次发送最后一个数据包)。现在您可以使用 avcodec_receive_frame
收集解码帧,直到您再次获得 AVERROR(EAGAIN)
。一些解码器在有多个帧排队等待解码时工作得更快(这就是解码器在设置 codec_ctx->thread_type = FF_THREAD_FRAME
时所做的事情)。
关于multithreading - FFmpeg 对 avcodec_send_packet() 做了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55186822/
我正在尝试解码帧,但内存使用量随着每一帧(更具体地说,每次调用 avcodec_send_packet)而增长,直到最后代码因 bad_alloc 而崩溃。这是基本的解码循环: int rfret =
我正在使用 ffmpeg 库对 MPEG 传输流中的视频进行解码、缩放和重新编码。我刚刚从源代码重新编译到 v3.3.2,并从旧的 avcodec_decode_video2() API 更改为新的发
我正在尝试从来自 mp4 容器的压缩数据中解码数据包。我已经获得了 AVCodecContext,并从 avreadframe() 获得了数据包。问题是当我尝试解码数据包时,eclipse 一直说无法
以下基于 ffmpeg 的代码片段正在 Windows VC2012、VC20155、VC2017 上构建和运行。 在 Ubuntu LTS 16.04 上使用 gcc,这给了我一些问题,更具体地说,
我正在尝试优化一款播放视频的软件,它在内部使用 FFmpeg 库进行解码。我们发现,在一些大型(4K,60fps)视频中,解码一帧的时间有时比应该显示该帧的时间要长;遗憾的是,由于问题域,简单地缓冲/
Windows 10 x64,ffmpeg: 3.1, 预建 dll 这里绝对是新手。 我正在尝试一个非常基本的案例来解码视频文件中的帧,但每次尝试都失败了。最终的代码片段如下所示: #define
我正在考虑如何设计一个循环,从互联网读取帧,馈送到 ffmpeg 解码器,然后从 ffmpeg 接收以发送到渲染。 考虑这个伪代码循环: while true { auto packet =
我是一名优秀的程序员,十分优秀!