From 9b2b0c0e8042e86ed56c8d0bedb2ecd6bc97436d Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 21 May 2026 21:32:30 +0100 Subject: [PATCH] Retest Kiyo Pro USB3 cadence --- docs/native-capture-cadence.md | 29 +++++++++++++ .../ks_camera_cadence/ks_camera_cadence.cpp | 43 ++++++++++++++++--- notes/fresh-workspace-handoff.md | 10 +++-- state/evidence.jsonl | 1 + state/map.yaml | 13 +++--- 5 files changed, 82 insertions(+), 14 deletions(-) diff --git a/docs/native-capture-cadence.md b/docs/native-capture-cadence.md index 3542f91..50af726 100644 --- a/docs/native-capture-cadence.md +++ b/docs/native-capture-cadence.md @@ -235,3 +235,32 @@ is bus topology, not HDR or low-light mode. Razer documents the Kiyo Pro's 60 fps modes as USB 3.0 operation; locally the device is sitting on a USB 2.x hub path. Move it to a verified SuperSpeed root/hub path before spending more time mutating unknown vendor selectors. + +Motherboard USB3 port follow-up: + +- After moving the Kiyo Pro off the external hub and directly onto the + motherboard USB3 port, the device moved to + `\\?\usb#root_hub30#...` port `7` and reports `bcdUSB=0x0320`. +- Windows still reports the negotiated connection speed enum as `2` + (`UsbHighSpeed`, not `UsbSuperSpeed`). The probe now prints the enum name so + this is harder to misread. +- The advertised mode surface improved: `1280x720` and `1920x1080` now expose + `YUY2`, `MJPG`, `H264`, and `NV12` at 60 fps. +- Baseline measured cadence stayed around 25 fps for every 720p/1080p format: + +| Mode | Advertised FPS | Delivered FPS | +| --- | ---: | ---: | +| 1280x720 YUY2 | 60.00 | 24.96 | +| 1920x1080 YUY2 | 60.00 | 24.98 | +| 1280x720 MJPG | 60.00 | 25.20 | +| 1920x1080 MJPG | 60.00 | 25.03 | +| 1280x720 H264 | 60.00 | 25.19 | +| 1920x1080 H264 | 60.00 | 25.01 | +| 1280x720 NV12 | 60.00 | 25.07 | +| 1920x1080 NV12 | 60.00 | 25.16 | + +Conclusion: the direct motherboard port improved enumeration but did not fix +cadence. Because Windows still reports `UsbHighSpeed`, verify the cable and +port path before assuming the private firmware selectors are guilty. If the +same 25 fps lock remains after `UsbSuperSpeed` is confirmed, the next cut is +explicit frame-interval negotiation or cautious vendor-selector tracing. diff --git a/native/probes/ks_camera_cadence/ks_camera_cadence.cpp b/native/probes/ks_camera_cadence/ks_camera_cadence.cpp index 6adc6e6..96c0f22 100644 --- a/native/probes/ks_camera_cadence/ks_camera_cadence.cpp +++ b/native/probes/ks_camera_cadence/ks_camera_cadence.cpp @@ -392,6 +392,23 @@ std::string accessText(ULONG accessFlags) return text.empty() ? "none" : text; } +const char* usbSpeedText(UCHAR speed) +{ + switch (speed) + { + case UsbLowSpeed: + return "UsbLowSpeed"; + case UsbFullSpeed: + return "UsbFullSpeed"; + case UsbHighSpeed: + return "UsbHighSpeed"; + case UsbSuperSpeed: + return "UsbSuperSpeed"; + default: + return "unknown"; + } +} + bool getTopologyNodes(HANDLE filter, std::vector& nodes) { KSPROPERTY property{}; @@ -796,9 +813,10 @@ void printUsbVideoDescriptors(USHORT vendorId, USHORT productId) } std::printf( - "USB descriptor match: hub=%s port=%lu speed=%d configs=%u bcdUSB=0x%04x bcdDevice=0x%04x\n", + "USB descriptor match: hub=%s port=%lu speed=%s(%d) configs=%u bcdUSB=0x%04x bcdDevice=0x%04x\n", hubPath.c_str(), static_cast(port), + usbSpeedText(connection->Speed), static_cast(connection->Speed), connection->DeviceDescriptor.bNumConfigurations, connection->DeviceDescriptor.bcdUSB, @@ -1375,7 +1393,16 @@ int main(int argc, char** argv) { std::setvbuf(stdout, nullptr, _IONBF, 0); const std::string targetVid = argc > 1 ? argv[1] : "vid_f182"; - const bool controlsOnly = argc > 2 && std::string(argv[2]) == "--controls-only"; + bool controlsOnly = false; + bool baselineOnly = false; + bool allWebcamFormats = false; + for (int arg = 2; arg < argc; ++arg) + { + const std::string option = argv[arg]; + controlsOnly = controlsOnly || option == "--controls-only"; + baselineOnly = baselineOnly || option == "--baseline-only"; + allWebcamFormats = allWebcamFormats || option == "--all-webcam-formats"; + } const bool leapMode = targetVid == "vid_f182" || targetVid == "VID_F182"; const auto paths = enumerateCapturePaths(); std::printf("capture interfaces: %zu\n", paths.size()); @@ -1439,17 +1466,23 @@ int main(int argc, char** argv) {"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -8, camManual}}}, {"gain minimum", {{"procamp.gain", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_GAIN, 0, procManual}}}, }; + const std::vector baselineScenarios = { + {"baseline", {}}, + }; + const auto& scenarios = baselineOnly ? baselineScenarios : webcamScenarios; bool measuredAny = false; for (const auto& candidate : candidates) { const double targetFps = candidate.interval100ns > 0 ? 10000000.0 / static_cast(candidate.interval100ns) : 0.0; + const auto subtype = fourccOrGuid(candidate.subtype); const bool interesting = ((candidate.width == 1920 && candidate.height == 1080) || (candidate.width == 1280 && candidate.height == 720)) && targetFps >= 25.0 && - fourccOrGuid(candidate.subtype) == "MJPG"; + (subtype == "MJPG" || + (allWebcamFormats && (subtype == "YUY2" || subtype == "NV12" || subtype == "H264"))); if (!interesting) { continue; @@ -1461,9 +1494,9 @@ int main(int argc, char** argv) candidate.width, candidate.height, candidate.bitCount, - fourccOrGuid(candidate.subtype).c_str(), + subtype.c_str(), targetFps); - for (const auto& scenario : webcamScenarios) + for (const auto& scenario : scenarios) { measuredAny = measureScenario(filter.value, candidate, scenario) || measuredAny; } diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index e194410..98fa867 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -47,10 +47,12 @@ Get-Content .\state\evidence.jsonl -Tail 8 output management. - Keep PowerShell/FFmpeg/SRT as bridge utilities until native program output replaces them. -- Kiyo Pro has two UVC extension units, but the immediate 60 fps blocker now - looks like bus topology: the local Pro is behind a Genesys Logic USB hub as - USB high-speed / `bcdUSB=0x0210`, not SuperSpeed. Move/verify it on a USB 3.x - path before poking writable vendor selectors. +- Kiyo Pro has two UVC extension units. Moving it to a motherboard USB3 port + changed the descriptor path to `root_hub30` / `bcdUSB=0x0320` and exposed + 720p/1080p YUY2/MJPG/H264/NV12 at 60 fps, but Windows still reports + `UsbHighSpeed` rather than `UsbSuperSpeed`; measured cadence remains about + 25 fps across all tested formats. Verify cable/port SuperSpeed before poking + writable vendor selectors. ## Immediate Re-entry Instruction diff --git a/state/evidence.jsonl b/state/evidence.jsonl index e4dfb41..45543b0 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -10,3 +10,4 @@ {"ts":"2026-05-21T21:55:00+00:00","type":"verification","status":"ok","note":"Online Kiyo Pro research found matching trouble reports: Razer documents 1080p60/720p60, HDR can reduce frame rate, anti-flicker/powerline can interact with frame rate, and Microsoft maps low-light compensation to AUTO_EXPOSURE_PRIORITY, which can vary frame rate. Local KS follow-up found Kiyo Pro reports low-light priority=1 and powerline=50Hz. Setting low-light priority to 0 did not improve cadence; setting powerline to 60Hz moved 720p/1080p MJPG only from about 25 fps to about 29 fps. Standard KS controls are not enough; next step is compare Synapse/OBS and inspect vendor/extension controls or firmware state."} {"ts":"2026-05-21T22:15:00+00:00","type":"verification","status":"ok","note":"Kiyo Pro HDR-off test added KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR get/set with filter-scope and pin-0 extended-property headers. The camera returns Element not found for standard extended Video HDR, and setting HDR off does not change cadence: 720p/1080p MJPG remain about 25 fps. HDR may still be controlled through Razer/Synapse, but not via the standard Windows extended Video HDR KS property on this path."} {"ts":"2026-05-21T22:45:00+00:00","type":"verification","status":"ok","note":"Kiyo Pro controls-only probe parsed USB descriptors through hub IOCTLs without Synapse. The device exposes UVC extension units {2c49d16a-32b8-4485-3ea8-643a152362f2} and {23e49ed0-1178-4f31-ae52-d2fb8a8d3b48}; the second answers KS selector probes including writable selectors 1,3,4,6,11,12,14,15 and readable selector 10 returns ASCII PYTHON_V2B. Stronger finding: the local Kiyo Pro is behind a Genesys Logic VID_05E3&PID_0610 hub at USB speed 2 / bcdUSB 0x0210, so it is on a high-speed USB 2.x path rather than SuperSpeed USB 3.x. Verify/move bus topology before mutating unknown vendor controls."} +{"ts":"2026-05-21T23:10:00+00:00","type":"verification","status":"ok","note":"After moving Kiyo Pro to a motherboard USB3 port, the descriptor path changed to root_hub30 port 7 with bcdUSB 0x0320 and 720p/1080p YUY2/MJPG/H264/NV12 all advertised at 60 fps. Windows still reports USB speed enum 2 (UsbHighSpeed, not UsbSuperSpeed). Baseline cadence remains locked around 25 fps across all tested 720p/1080p formats: YUY2 24.96/24.98, MJPG 25.20/25.03, H264 25.19/25.01, NV12 25.07/25.16. Verify a true SuperSpeed cable/port path before blaming unknown vendor selectors."} diff --git a/state/map.yaml b/state/map.yaml index f3c02fc..5a3cba9 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -94,11 +94,14 @@ current_status: cadence to about 29 fps, and standard extended Video HDR is not exposed on this KS path. The controls-only probe now parses USB VideoControl descriptors and found the Kiyo Pro's two vendor extension units. One - extension unit answers writable KS selectors, but the stronger local cause - is bus topology: the Pro is currently behind a Genesys Logic USB hub as - high-speed USB 2.x (`bcdUSB=0x0210`, speed `2`), not SuperSpeed USB 3.x. + extension unit answers writable KS selectors. Moving the Pro directly to a + motherboard USB3 port changed the path to `root_hub30`, `bcdUSB=0x0320`, + and exposed 720p/1080p YUY2/MJPG/H264/NV12 at 60 fps, but Windows still + reports `UsbHighSpeed` rather than `UsbSuperSpeed`, and baseline cadence is + still about 25 fps across every tested format. next_action: > Turn the warmed, queued Leap KS path into an `IMimirVideoCaptureDriver`, preserve direct control hooks for timing-camera state, and decide whether - Kiyo Pro reaches 60 fps after moving it to a verified SuperSpeed USB path - before mutating unknown vendor extension selectors. + Kiyo Pro reaches 60 fps after confirming a true `UsbSuperSpeed` cable/port + path; if it remains locked at 25 fps there, inspect explicit frame-interval + negotiation or vendor selectors.