探针增加尺寸扫描:区分链路带宽不够与摄像头本身就是 15 fps - What: tools/camera_probe.py 新增 SWEEP_SIZES 与 size_sweep(),在帧率扫描之后对 MJPG@30 依次申请 1920x1080/1280x720/960x540/848x480/640x480 并打印实测速率,提示语写明判断方式:帧越小越快 ⇒ 链路带宽是瓶颈;每个尺寸都一样 ⇒ 是摄像头本身的速率上限。 - Why: 用户实测 MJPG 在 1080p 与 720p 都是 15 fps、YUYV 两档都是 1 fps,两种解释仍然都成立(链路只能扛约 3-4 MB/s,或这颗摄像头在这些格式上就是 15 fps 设备),而处置完全不同;帧率扫描只能区分"申请被砍半"与"固定上限",尺寸扫描才能区分"带宽"与"设备"。 - Verification: compileall 通过;无摄像头时仍返回 1 并给出解释;studio 全量 91 passed(探针的无摄像头用例覆盖 main() 的降级路径)。 - Not in this change: 未改 SDK 采集参数;未做自动降级。

This commit is contained in:
ykcheungab
2026-09-14 13:40:04 +08:00
parent a44eb2d65d
commit 30ef50814f
+45
View File
@@ -49,6 +49,18 @@ BACKENDS: tuple[tuple[str, int], ...] = (
#: follows the request or ignores it.
SWEEP_RATES: tuple[float, ...] = (60.0, 30.0, 20.0, 15.0, 10.0)
#: Sizes asked for at one fixed rate. This is what separates the two remaining
#: explanations for a low rate: "the link cannot carry the pixels" (smaller
#: frames go faster) from "this camera is a 15 fps device" (the rate does not
#: move at all).
SWEEP_SIZES: tuple[tuple[int, int], ...] = (
(1920, 1080),
(1280, 720),
(960, 540),
(848, 480),
(640, 480),
)
SAMPLES = 60
#: A request is "missed" when the measured rate is below this fraction of it.
TOLERANCE = 0.9
@@ -145,6 +157,24 @@ def sweep(index: int, backend_name: str, backend: int, size: tuple[int, int],
return rows
def size_sweep(index: int, backend_name: str, backend: int, fps: float = 30.0,
*, samples: int = SAMPLES) -> list[dict]:
"""Ask for one rate at shrinking sizes: bandwidth, or a fixed ceiling?
A link that cannot carry the pixels gets faster as the frames get smaller. A
camera whose own rate is 15 fps delivers 15 whatever it is asked for.
"""
rows = []
for width, height in SWEEP_SIZES:
result = probe(
index, backend_name, backend, ("MJPG", width, height, fps),
samples=samples,
)
if result is not None:
rows.append(result)
return rows
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("--index", type=int, default=None, help="camera index to probe")
@@ -198,6 +228,21 @@ def main(argv: list[str] | None = None) -> int:
f"(a ceiling that does not move with the request is the "
f"hardware's, not the request's)"
)
print(
f"\n sizes at MJPG@{30:g} fps [{first_backend[0]}] -- bandwidth, "
f"or a fixed ceiling?"
)
for result in size_sweep(
index, first_backend[0], first_backend[1], samples=args.samples
):
width, height = result["asked"][1], result["asked"][2]
print(
f" {width}x{height:<5} -> measured {result['measured_fps']:5.1f} fps"
)
print(
" smaller frames going faster means the link is the limit; the "
"same number at every size means the camera is"
)
if header:
found += 1