无需 hwdownload 将 ffpmeg OpenCL 过滤器输出传递到 NVenc?

问题描述 投票:0回答:2

我正在尝试使用 ffmpeg 对 UHD HDR 视频流进行色调映射(和调整大小)。以下命令:

ffmpeg -vsync 0 -hwaccel cuda -init_hw_device opencl=ocl -filter_hw_device ocl 
    -threads 1 -extra_hw_frames 3 -c:v hevc_cuvid -resize 1920x1080 -i "INPUT.hevc" 
    -vf "hwupload,
         tonemap_opencl=tonemap=mobius:param=0.01:desat=0:r=tv:p=bt709:t=bt709:m=bt709:format=nv12,
         hwdownload,format=nv12,hwupload_cuda" 
    -c:v hevc_nvenc -b:v 8M "OUTPUT.hevc"

似乎有效(RTX 3080 上大约 200 FPS)。然而,我注意到它仍然使用一个 CPU 核心,并且 GPU 使用率据报告仅为 60-70%。当我只在没有任何滤镜的情况下调整大小时,我在 100% GPU 使用率下获得了大约 400FPS。

我怀疑最后的

hwdownload,format=nv12,hwupload_cuda
语句有问题,因为这增加了主内存的绕道。我尝试只使用
hwupload_cuda
而不是不使用
hwdownload
(就像这里建议的那样:https://stackoverflow.com/a/55747785/929037 在这个答案末尾附近的过滤器示例中),但后来我得到了以下错误:

Impossible to convert between the formats supported by the filter 'Parsed_tonemap_opencl_1' and the filter 'auto_scaler_0'
Error reinitializing filters!
Failed to inject frame into filter network: Function not implemented
Error while processing the decoded data for stream #0:0

尝试使用

hwmap
导致

Assertion dst->format == AV_PIX_FMT_OPENCL failed at C:/code/ffmpeg/src/libavutil/hwcontext_opencl.c:2814

是否可以避免这种额外的

hwdownload

video ffmpeg opencl nvidia nvenc
2个回答
7
投票

2022 年编辑:

对于使用 Nvidia 卡并想要零复制 HDR 到 SDR 色调映射的用户,您现在可以使用 FFmpeg 5.0 中引入的功能强大的 Vulkan 过滤器

libplacebo
来实现此目的,而无需 OpenCL 过滤器。

libplacebo 是 MPV 播放器的下一代视频渲染器,它可以在 GPU 上执行高质量视频处理,包括 HDR10 和 DV 内容的色调映射。由于从 CUDA 内存导出到 Vulkan 已经实现,您可以使用

libplacebo
过滤器与 NVDEC、NVENC 和其他 CUDA 过滤器链接以获得最佳性能。

要获得额外的 Vulkan 和 libplacebo 支持,您必须使用使用

--enable-vulkan --enable-libshaderc --enable-libplacebo
构建的 ffmpeg。

可以从 https://github.com/BtbN/FFmpeg-Builds/releases 获取预构建的二进制文件

执行此操作的 cmd 片段:

./ffmpeg -threads 1 -hwaccel cuda -hwaccel_output_format cuda -i HDR.mp4 \
-vf "scale_cuda=w=1920:h=1080:interp_algo=bilinear,hwupload=derive_device=vulkan, \
libplacebo=tonemapping=auto:colorspace=bt709:color_primaries=bt709:color_trc=bt709:format=yuv420p:upscaler=none:downscaler=none:peak_detect=0, \
hwupload=derive_device=cuda" \
-c:v h264_nvenc -preset medium -profile:v high -b:v 8M -y SDR.mp4

这是什么意思:

  1. 使用 NVDEC 硬件加速器将视频解码到 CUDA 内存
  2. 使用 CUDA 过滤器(双线性算法)将视频缩放至 1080p
  3. 使用
    hwupload
  4. 从 CUDA 导出到 Vulkan 内存
  5. 应用从 HDR 到 SDR 8 位 yuv420p 的自动色调映射,无需使用 libplacebo 的内置缩放器来提高性能
  6. 使用
    hwupload
  7. 从 Vulkan 导出到 CUDA 内存
  8. 使用 NVENC 编码器编码为 H.264 1080p SDR 8M

注意,这里的

hwupload
并不意味着复制回内存。 相反,在这个特定的 CUDA-Vulkan 管道中,它执行与
hwmap
相同的操作。整个视频过滤管道都在您的 GPU 和 VRAM 上进行。

upscaler=none:downscaler=none:peak_detect=0
这三个选项禁用了一些高质量的放大/缩小算法和 HDR 峰值检测功能,以换取更好的性能。您可以将它们移除以获得最佳质量。

有关 libplacebo 过滤器中的更多微调选项,请参阅 http://ffmpeg.org/ffmpeg-all.html#libplacebo


2021年原答案:

至少现在不行。

Cuda 和 OpenCL 设备之间的零复制纹理共享又名

hwmap
过滤器在 ffmpeg 中不可用,直到 Nvidia 为它们发布互操作方法为止。

https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__INTEROP.html

Intel 和 AMD 有一些针对 D3D11/VAAPI 的 OpenCL 扩展<->OpenCL 互操作,可以将一个共享图像(例如 NV12)分割成不同的平面(例如平面 Y 和 UV)。 例如 Intel 的

cl_intel_va_api_media_sharing
cl_intel_d3d11_nv12_media_sharing
和 AMD 的
cl_amd_planar_yuv

至于 Nvidia,他们确实有

cl_nv_d3d11_sharing
用于 D3D11<->OpenCL 互操作,但我认为它在 Cuda 方面效果不佳。

另一个解决方案是将色调映射算法移植为 Cuda 过滤器,但这需要一些时间。完成后,预计速度将得到巨大提高。您可以轻松使用它,如

scale_cuda
overlay_cuda
过滤器等。

我看到英特尔已经在其最新的 iGPU 中支持

tonemap_vaapi
通过硬件功能进行过滤。不确定 Nvidia NVENC 的 ASIC 中是否有类似的。


0
投票

我认为这很重要! NVIDIA 驱动程序最近似乎没有在 Linux 上报告正确的修饰符。 所以你必须对 FFmpeg 应用补丁来绕过这个怪癖。

https://github.com/philipl/FFmpeg/commit/fbe140c073788acf61a332db8f532dd0c0104179 将其应用到 libavutil/hwcontext_vulkan.c 然后重建你的 FFmpeg,它应该可以工作。

© www.soinside.com 2019 - 2024. All rights reserved.