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

Cur*_*Guo 7 encoding ffmpeg libx264

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

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

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

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

aer*_*tal 11

该文件表明,基于帧的线程具有比片为基础的更好的吞吐量.它还指出,由于编码器的部分串行,后者不能很好地扩展.

加速与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
Run Code Online (Sandbox Code Playgroud)

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

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

来自:x264开发者的日记

无切片线程:具有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因为您需要尽快发送帧,而不是有效地编码它们(性能和质量明智).

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