from __future__ import annotations ARM_MACHINES = frozenset({"aarch64", "arm64", "armv7l", "armv8l"}) def resolve_live_video_encoder( requested_encoder: str, ffmpeg_encoders_text: str, machine: str, *, has_mpp_service: bool = False, has_render_node: bool = False, has_v4l2_device: bool = False, usable_encoders: set[str] | None = None, ) -> tuple[str, str]: requested = (requested_encoder or "").strip() blob = ffmpeg_encoders_text or "" machine_norm = (machine or "").strip().lower() is_arm = machine_norm in ARM_MACHINES def has_encoder(name: str) -> bool: return bool(name) and name in blob def is_usable(name: str) -> bool: return usable_encoders is None or name in usable_encoders arm_candidates: list[str] = [] if has_encoder("h264_rkmpp") and has_mpp_service and is_usable("h264_rkmpp"): arm_candidates.append("h264_rkmpp") if has_encoder("h264_v4l2m2m") and has_v4l2_device and is_usable("h264_v4l2m2m"): arm_candidates.append("h264_v4l2m2m") if is_arm: if requested == "h264_vaapi": if arm_candidates: return arm_candidates[0], f"LIVE_VIDEO_ENCODER=h264_vaapi is not stable on ARM, fallback to {arm_candidates[0]}" return "", "LIVE_VIDEO_ENCODER=h264_vaapi is not supported on ARM, fallback to libx264" if requested == "h264_v4l2m2m" and not has_v4l2_device: return "", "LIVE_VIDEO_ENCODER=h264_v4l2m2m requires /dev/video* on this ARM host, fallback to libx264" if requested and has_encoder(requested) and usable_encoders is not None and requested not in usable_encoders: if arm_candidates: return arm_candidates[0], f"LIVE_VIDEO_ENCODER={requested} failed encoder smoke test, fallback to {arm_candidates[0]}" return "", f"LIVE_VIDEO_ENCODER={requested} failed encoder smoke test, fallback to libx264" if requested: if requested in arm_candidates: return requested, "" if requested.startswith("h264_") and has_encoder(requested) and is_usable(requested): return requested, "" if arm_candidates: return arm_candidates[0], f"LIVE_VIDEO_ENCODER={requested} is unavailable on this ARM host, fallback to {arm_candidates[0]}" return "", f"LIVE_VIDEO_ENCODER={requested} is unavailable on this ARM host, fallback to libx264" if arm_candidates: return arm_candidates[0], "" return "", "" if requested == "h264_qsv": if has_encoder("h264_vaapi") and has_render_node and is_usable("h264_vaapi"): return "h264_vaapi", "LIVE_VIDEO_ENCODER=h264_qsv is not enabled in this Linux stack yet, fallback to h264_vaapi" return "", "LIVE_VIDEO_ENCODER=h264_qsv is not enabled in this Linux stack yet, fallback to libx264" if requested == "h264_vaapi" and not has_render_node: return "", "LIVE_VIDEO_ENCODER=h264_vaapi requires /dev/dri/renderD*; fallback to libx264" if requested and has_encoder(requested) and usable_encoders is not None and requested not in usable_encoders: return "", f"LIVE_VIDEO_ENCODER={requested} failed encoder smoke test, fallback to libx264" if requested and requested.startswith("h264_") and has_encoder(requested) and is_usable(requested): return requested, "" if requested: return "", f"LIVE_VIDEO_ENCODER={requested} is unavailable on this host, fallback to libx264" return "", ""