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

时间:2015-11-10 06:14:53

标签: encoding ffmpeg libx264

我使用ffmpeg libx264来编码从x11实时捕获的720p屏幕,其fps为30。 当我使用 -tune zerolatency 参数时,每个帧的平均编码时间可以与配置文件基线一样大到12毫秒。

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

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

有人可以解释有关此切片线程的详细信息吗?特别是在实时编码中(假设没有帧被缓冲以进行编码。仅在捕获帧时进行编码)。

1 个答案:

答案 0 :(得分:11)

documentation表明基于帧的线程比基于切片的吞吐量更好。它还指出,后者由于编码器的部分串行而无法很好地扩展。

veryfast个人资料的加速与编码线程(非实时):

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

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

  

普通线程,也称为基于帧的线程,使用巧妙的交错帧系统进行并行处理。但它需要付出代价:如前所述,每个额外的线程都需要一层延迟。基于切片的线程没有这样的问题:每个帧被分成片,每个片在一个核上编码,然后将结果打包在一起以形成最终帧。由于各种原因,它的最高效率要低得多,但它至少允许一些并行性而不会增加延迟。

来自:Diary of an x264 Developer

  

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

来自:http://web.archive.org/web/20150307123140/http://akuvian.org/src/x264/sliceless_threads.txt

因此,sliced-threads启用-tune zereolatency是有意义的,因为您需要尽快发送一个帧,而不是有效地编码它们(性能和质量明智)。

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