探针增加尺寸扫描:区分链路带宽不够与摄像头本身就是 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:
@@ -49,6 +49,18 @@ BACKENDS: tuple[tuple[str, int], ...] = (
|
|||||||
#: follows the request or ignores it.
|
#: follows the request or ignores it.
|
||||||
SWEEP_RATES: tuple[float, ...] = (60.0, 30.0, 20.0, 15.0, 10.0)
|
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
|
SAMPLES = 60
|
||||||
#: A request is "missed" when the measured rate is below this fraction of it.
|
#: A request is "missed" when the measured rate is below this fraction of it.
|
||||||
TOLERANCE = 0.9
|
TOLERANCE = 0.9
|
||||||
@@ -145,6 +157,24 @@ def sweep(index: int, backend_name: str, backend: int, size: tuple[int, int],
|
|||||||
return rows
|
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:
|
def main(argv: list[str] | None = None) -> int:
|
||||||
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||||
parser.add_argument("--index", type=int, default=None, help="camera index to probe")
|
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"(a ceiling that does not move with the request is the "
|
||||||
f"hardware's, not the request's)"
|
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:
|
if header:
|
||||||
found += 1
|
found += 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user