根据新版本调整set_pattern:0~65535

This commit is contained in:
xinzhu.yin
2026-07-07 18:59:44 +08:00
parent 9fa811a9eb
commit 32aaef1c0f
24 changed files with 3016 additions and 279 deletions

111
app/ucd/pg_status.py Normal file
View File

@@ -0,0 +1,111 @@
"""从 UniTAP Pattern Generator 读取状态并格式化为日志行。"""
from __future__ import annotations
import logging
import os
import re
from typing import Any
import UniTAP
from UniTAP.common import ColorInfo
log = logging.getLogger(__name__)
def _enum_display_name(name: str) -> str:
spaced = re.sub(r"([a-z])([A-Z])", r"\1 \2", name)
return spaced.replace("_", " ")
def _format_pattern_name(pg, pattern_hint: str | None = None) -> str:
if pattern_hint:
return pattern_hint
pattern = getattr(pg, "_pattern", None)
if isinstance(pattern, UniTAP.VideoPattern):
return _enum_display_name(pattern.name)
if isinstance(pattern, str):
return os.path.basename(pattern) or "Image File"
pattern_id = getattr(pg, "_pattern_id", None)
if pattern_id is not None:
return _enum_display_name(getattr(pattern_id, "name", str(pattern_id)))
return ""
def _format_cef(ci: ColorInfo) -> str:
fmt_map = {
ColorInfo.ColorFormat.CF_RGB: "RGB",
ColorInfo.ColorFormat.CF_YCbCr_422: "YCbCr 4:2:2",
ColorInfo.ColorFormat.CF_YCbCr_444: "YCbCr 4:4:4",
ColorInfo.ColorFormat.CF_YCbCr_420: "YCbCr 4:2:0",
ColorInfo.ColorFormat.CF_Y_ONLY: "Y only",
ColorInfo.ColorFormat.CF_RAW: "RAW",
ColorInfo.ColorFormat.CF_DSC: "DSC",
}
fmt = fmt_map.get(
ci.color_format,
ci.color_format.name.replace("CF_", "").replace("_", " "),
)
if ci.color_format == ColorInfo.ColorFormat.CF_RGB:
range_str = (
"Legacy RGB mode"
if ci.dynamic_range == ColorInfo.DynamicRange.DR_VESA
else "Limited range"
)
elif ci.dynamic_range == ColorInfo.DynamicRange.DR_VESA:
range_str = "Full range"
else:
range_str = "Limited range"
return f"{fmt}/{range_str}"
def _max_bitrate_gbps(pg, bpp: int) -> float:
caps = pg._caps()
effective_bpp = bpp if bpp > 0 else 24
return round(caps.max_pix_rate * effective_bpp / 1_000_000_000.0, 3)
def collect_pattern_generator_status(
pg,
*,
pattern_hint: str | None = None,
) -> dict[str, Any]:
vm = pg.get_stream_video_mode()
pg_status = pg.status()
ci = vm.color_info
refresh_hz = vm.timing.frame_rate / 1000.0 if vm.timing.frame_rate else 0.0
timing = f"{vm.timing.hactive} x {vm.timing.vactive} @ {refresh_hz:g}Hz"
current_br = vm.bit_rate
max_br = _max_bitrate_gbps(pg, ci.bpp)
return {
"total_bitrate": f"{current_br:.3f} / {max_br:.3f} Gbps",
"timing": timing,
"pattern": _format_pattern_name(pg, pattern_hint),
"cef": _format_cef(ci),
"bpc": str(ci.bpc),
"status": str(pg_status.error),
}
def format_pattern_generator_status_log(status: dict[str, Any]) -> list[str]:
return [
f"Total bitrate: {status['total_bitrate']}",
f" Timing: {status['timing']}",
f" Pattern: {status['pattern']}",
f" CEF: {status['cef']}",
f" BPC: {status['bpc']}",
f" Status: {status['status']}",
]
def read_pattern_generator_status_lines(
pg,
*,
pattern_hint: str | None = None,
) -> list[str]:
status = collect_pattern_generator_status(pg, pattern_hint=pattern_hint)
return format_pattern_generator_status_log(status)