69 lines
3.5 KiB
Python
69 lines
3.5 KiB
Python
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 "", ""
|