请教一个关于 ffmpeg 的问题

132 天前
xyzos  xyzos

前提:在 windows/linux 上,使用同样一个 ffmpeg 静态编译的可执行文件,对同样一个 h264 编码的 mp4 文件解码,解码命令如下: (1) .\ffmpeg.exe -hwaccel cuda -i E:\tmp\1080p_60_10M.mp4 -f null - 解码帧率为 fps=780 (2) .\ffmpeg.exe -i E:\tmp\1080p_60_10M.mp4 -f null - 解码帧率为 fps=1617

(1) 解码结果:

  Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'E:\tmp\1080p_60_10M.mp4':

Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf60.3.100 Duration: 00:01:36.67, start: 0.000000, bitrate: 10533 kb/s Stream #0:00x1: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 10528 kb/s, 60 fps, 60 tbr, 15360 tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] encoder : Lavc60.3.100 libx264 Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native)) Press [q] to stop, [?] for help Output #0, null, to 'pipe:': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf60.22.101 Stream #0:0(und): Video: wrapped_avframe, nv12(progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 60 fps, 60 tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] encoder : Lavc60.40.100 wrapped_avframe [out#0/null @ 0000017e54639b80] video:2719KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown frame= 5800 fps=780 q=-0.0 Lsize=N/A time=00:01:36.66 bitrate=N/A speed= 13x

(2) 解码结果:

    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'E:\tmp\1080p_60_10M.mp4':

Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf60.3.100 Duration: 00:01:36.67, start: 0.000000, bitrate: 10533 kb/s Stream #0:00x1: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 10528 kb/s, 60 fps, 60 tbr, 15360 tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] encoder : Lavc60.3.100 libx264 Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native)) Press [q] to stop, [?] for help Output #0, null, to 'pipe:': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf60.22.101 Stream #0:0(und): Video: wrapped_avframe, yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 60 fps, 60 tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] encoder : Lavc60.40.100 wrapped_avframe [out#0/null @ 000001f2b2f29c00] video:2719KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown frame= 5800 fps=1617 q=-0.0 Lsize=N/A time=00:01:36.66 bitrate=N/A speed=26.9x

问题:指定了 -hwaccel cuda 参数进行解码的 fps 要比不指定这个参数进行解码的帧率少了一倍,自己的主机是 nvidia 显卡,这个可能是什么原因?

2821 次点击
所在节点   FFmpeg  FFmpeg
18 条回复
xiaoding
xiaoding
132 天前
ffmpeg.exe -hwaccel cuda -hwaccel_output_format cuda -i E:\tmp\1080p_60_10M.mp4 -f null -
xyzos
xyzos
132 天前
@xiaoding -hwaccel_output_format cuda 加上这个参数结果也还是 700 多 fps 没啥变化
nilaoda
nilaoda
132 天前
很正常,硬解需要频繁和 GPU 进行数据交换,对于 H264 这种很好解码的编码来说硬解不会比软解快,你可以尝试一些难以软解的编码再和硬解对比。
ntedshen
ntedshen
132 天前
cuda 是 cuda ,nvenc 是 nvenc ,cuda 并不是硬编/解码。。。
建议直接挂 auto 。。。
ntedshen
ntedshen
132 天前
不对,是我记错了。。。
NVENC and NVDEC are NVIDIA's hardware-accelerated encoding and decoding APIs. They used to be called CUVID. They can be used for encoding and decoding on Windows and Linux. FFmpeg refers to NVENC/NVDEC interconnect as CUDA.

找个片
h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 2496x832 [SAR 1:1 DAR 3:1], 13574 kb/s, 23.98 fps, 23.98 tbr, 24k tbn (default)

测试了一下
./ffmpeg.exe -hwaccel cuda -i .\u305.mp4 -f null -
27.9x
./ffmpeg.exe -hwaccel auto -i .\u305.mp4 -f null -
26.2x
./ffmpeg.exe -i .\u305.mp4 -f null -
97x

猜测应该是不开 hwaccel 的时候 h264 直接输出了,而 nvdec 至少还运行了一下(输出是 nv12 而不是 yuv420p )。。。
yinmin
yinmin
132 天前
显卡视频解码是用 gpu 的 video decode 单元,这个单元普遍很弱,打不过 cpu 多核解码,intel 、amd 也都一样。
wnpllrzodiac
wnpllrzodiac
132 天前
看你速度怎么统计吧。
硬盘-》内存-》显存-》内存( yuv 数据)
ffmpeg 是不能直接使用 gpu 数据的。

如果在显存那步算是结束点的话,因该快一点。硬件解码的问题是兼容性不好。

输出的像素格式可能与显示的需求不一致,需要做转换。
输出的数据结构可能有 padding ,需要按照每行做操作。
解码同时的硬件单元可能老黄没给足,不一定比 cpu 快。
解码如果 dxva2 直接现存输出到显示器的话,会快很多。

总之,硬件加速远比你想象的要复杂,不是一定比用 cpu 快的。
而且老黄的卡,发力点现在明显也不再编解码上面。AI 才是赚钱的机器。
wnpllrzodiac
wnpllrzodiac
132 天前
我记得以前测试下来,硬件编码要快不少,硬件解码加成不多,有时候还起反作用。
硬件编码的主要好处是降低 cpu 的开销,不然 cpu 实在撑不了几路。但是老黄也抠门,民用 gpu 的编码并发有限制,从来给不到 2+。

硬件解码+硬件编码一起用可能省点时间,因为在 gpu 里的数据可以直接用?
不确定 ffmpeg 或者老黄有没有给这样的直通 api
MrKrabs
132 天前
cpu 多核解码把硬件解码爆了很正常
功耗就差多了
zhs227
132 天前
硬件编码性能是优势,解码未必。编码单元和解码单元一般是独立设计的,解码的设计原则是适度冗余。已经实时解了 26 路 1080P60 了算可以了 。
erquren
132 天前
我的 5950X 解码速度比 4090 快一倍
liaohongxing
132 天前
主要就是硬件解码的参数是固定的,有极限。留给某一格式的晶体管就那么多。
wangtian2020
132 天前
设计硬件解码的目标是 省电 + 够用( 4k++ + 60hz++)
足够用的分辨率和帧率下可以省电的解码,它的目标已经完成了
xyzos
132 天前
@zhs227 26 路是 cpu 的结果,显卡硬解的是 13 路
xyzos
132 天前
@ntedshen 验证了一下,指定输出格式为 nv12 对结果也没影响 还是差距很大,应该是硬件解码速度并不是其主要优势,优势是解放 cpu 和 能耗
xyzos
132 天前
@wnpllrzodiac 确定不是 内存 io 的限制,不管是硬解还是软解 gpu decode 模块和 cpu 都是打满的状态,但是内存都基本没变化,我解码的文件也不大 只有十几 M
noahhhh
131 天前
@wnpllrzodiac 4070 ti 就有双编码器吧
ntedshen
131 天前
@xyzos 确实有可能。。。毕竟一般都是侧重关注编码性能而不是关注解码性能,解码反正能在显示器的规格以内就行。。。
话说我又找了一个带 intel a380 的台机( i9-7900x + a380 )测试了一下,目前的成绩是。。。

./ffmpeg.exe -hwaccel qsv -i .\u305.mp4 -f null -
46.8x

./ffmpeg.exe -i .\u305.mp4 -f null -
69.5x

看起来 i 卡解码确实也强一些。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1090588

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX