lumen_ffmpeg/encode/
hardware.rs1use crate::gpu::GpuBackend;
2use crate::video::VideoCodec;
3
4use super::codec::encoder_by_name;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct GpuTextureEncodeSupport {
8 pub backend: GpuBackend,
9 pub codec: VideoCodec,
10 pub encoder_name: Option<&'static str>,
11 pub available: bool,
12 pub direct_texture_path: bool,
13 pub reason: Option<String>,
14}
15
16pub(crate) fn hardware_texture_encoder_name(
17 backend: GpuBackend,
18 codec: VideoCodec,
19) -> Option<&'static str> {
20 match (backend, codec) {
21 (GpuBackend::Cuda, VideoCodec::H264) => Some("h264_nvenc"),
22 (GpuBackend::Cuda, VideoCodec::Hevc) => Some("hevc_nvenc"),
23 (GpuBackend::Cuda, VideoCodec::Av1) => Some("av1_nvenc"),
24 (GpuBackend::Metal, VideoCodec::H264) => Some("h264_videotoolbox"),
25 (GpuBackend::Metal, VideoCodec::Hevc) => Some("hevc_videotoolbox"),
26 _ => None,
27 }
28}
29
30pub fn gpu_texture_encode_support(
31 codec: VideoCodec,
32 backend: GpuBackend,
33) -> GpuTextureEncodeSupport {
34 let encoder_name = hardware_texture_encoder_name(backend, codec);
35 let texture_path_wired = matches!(backend, GpuBackend::Cuda | GpuBackend::Metal);
36 let encoder_available =
37 texture_path_wired && encoder_name.is_some_and(|name| encoder_by_name(name).is_ok());
38 let reason = if !encoder_available {
39 Some(match (texture_path_wired, encoder_name) {
40 (false, _) => format!("{backend:?} hardware texture encode is not available yet"),
41 (true, Some(name)) => format!("FFmpeg encoder `{name}` is unavailable"),
42 (true, None) => format!("{backend:?} texture encode is unavailable for {codec:?}"),
43 })
44 } else {
45 None
46 };
47
48 GpuTextureEncodeSupport {
49 backend,
50 codec,
51 encoder_name,
52 available: encoder_available,
53 direct_texture_path: false,
54 reason,
55 }
56}