Encoding 为什么切片线程对使用ffmpeg x264的实时编码有如此大的影响?

Encoding 为什么切片线程对使用ffmpeg x264的实时编码有如此大的影响?,encoding,ffmpeg,libx264,Encoding,Ffmpeg,Libx264,我使用ffmpeg libx264对从x11实时捕获的720p屏幕进行编码,fps为30。 当我使用-tune zerolatency参数时,在配置文件基线下,每帧的平均编码时间可以高达12ms 在研究ffmpeg x264源代码之后,我发现导致如此长的编码时间的关键参数是切片线程,它通过-tune zerolatency启用。使用-x264参数sliced threads=0禁用后,编码时间可低至2ms 禁用切片线程时,CPU使用率将为40%,而启用时仅为20% 有人能解释一下这个切片线程的细

我使用ffmpeg libx264对从x11实时捕获的720p屏幕进行编码,fps为30。 当我使用-tune zerolatency参数时,在配置文件基线下,每帧的平均编码时间可以高达12ms

在研究ffmpeg x264源代码之后,我发现导致如此长的编码时间的关键参数是切片线程,它通过-tune zerolatency启用。使用-x264参数sliced threads=0禁用后,编码时间可低至2ms

禁用切片线程时,CPU使用率将为40%,而启用时仅为20%

有人能解释一下这个切片线程的细节吗?特别是在实时编码中(假设没有帧缓冲进行编码。仅在捕获帧时进行编码)。

显示基于帧的线程比基于片的线程具有更好的吞吐量。它还注意到,由于编码器的某些部分是串行的,所以后者不能很好地扩展

veryfast
配置文件的加速比与编码线程(非实时):

主要区别似乎是帧线程增加了帧延迟,因为需要处理不同的帧,而在基于切片的线程中,所有线程都在同一帧上工作。在实时编码中,需要等待更多帧到达以填充管道,而不是离线

普通线程,也称为基于帧的线程,使用聪明的交错帧系统实现并行。但这是有代价的:如前所述,每一个额外的线程都需要额外的一帧延迟。基于切片的线程没有这样的问题:每个帧都被分割成切片,每个切片编码在一个核心上,然后将结果拼接在一起,形成最终的帧。由于各种原因,它的最大效率要低得多,但它至少允许一些并行性,而不会增加延迟

发件人:

无切片线程:具有2个线程的示例。 开始编码帧#0。完成一半后,开始编码第1帧。线程#1现在只能访问其参考帧的上半部分,因为其余部分尚未编码。因此,它必须限制运动搜索范围。但这可能没问题(除非你在一个小帧上使用很多线程),因为很少有这么长的垂直运动矢量。过了一会儿,两个线程都编码了一行宏块,因此线程1仍然可以使用运动范围=+/-1/2帧高度。稍后,线程0完成第0帧,并继续到第2帧。线程0现在获得运动限制,线程1不受限制

发件人:

因此,有必要使用
-tune zereolatency
启用
切片线程
,因为您需要尽快发送帧,而不是高效地对其进行编码(性能和质量方面)


相反,使用过多线程会影响性能,因为维护线程的开销可能超过潜在收益。

您是否使用默认的
预设值
?如果使用
-preset ultrafast
,会发生什么情况?在上述两种情况下都使用ultrafast。这是一个有趣的问题。您是否正在使用最新版本的
ffmpeg
libx264
,以及使用什么操作系统/CPU。还有,你是如何衡量的?这不是最新的,我的源代码上的最后一次提交是在2014年2月23日,libx264是在2014年2月11日(很抱歉,源代码是从另一个人那里得到的,我只能从git日志中获得详细信息)。主机操作系统是ubuntu 14.04,CPU是Xeon(R)CPU E5-2630 v3。我使用了-benchmark_all选项并将所有输出数据转储到一个文件中,然后使用脚本计算平均编码时间。
x264/doc/threads.txt
表示编码器的部分是串行的,基于切片的线程不能很好地扩展。因为你有8个内核,我想它会产生8个切片线程。您可以覆盖
--threads 4
--slices
/
--slices max
并查看发生了什么。这与您的问题类似:我不认为是调度程序的问题,但您的内核是最新的。“在实时编码中,需要等待更多帧到达以填充管道,而不是脱机。”这是关于帧线程的讨论,对吗?片线程或帧线程都会增加解码时间?线程数是多少?谢谢,我说的是框架线程,因为它可以在不同的框架上工作。默认情况下,它是框架线程(#threads=1.5*内核),这就是为什么启用切片时会看到较低的值。线程太多(16)=开销太大。关于解码时间,似乎使用切片可以使解码器利用多线程并更快地解码(例如:蓝光需要4个切片)。我想知道的另一件事是,如果不使用b帧,为什么编码器会等待以后的帧而不是只使用前一帧。请参阅我更新的答案。每个额外的线程增加1帧延迟,因为它需要它来进行运动估计。非常感谢您的耐心和详细的回答。这对我帮助很大。
threads  speedup       psnr
      slice frame   slice  frame
x264 --preset veryfast --tune psnr --crf 30
 1:   1.00x 1.00x  +0.000 +0.000
 2:   1.41x 2.29x  -0.005 -0.002
 3:   1.70x 3.65x  -0.035 +0.000
 4:   1.96x 3.97x  -0.029 -0.001
 5:   2.10x 3.98x  -0.047 -0.002
 6:   2.29x 3.97x  -0.060 +0.001
 7:   2.36x 3.98x  -0.057 -0.001
 8:   2.43x 3.98x  -0.067 -0.001
 9:         3.96x         +0.000
10:         3.99x         +0.000
11:         4.00x         +0.001
12:         4.00x         +0.001