```markdown # Testing Linux Shutter and Gain/ISO Control with V4L2 We need to verify that our application can properly read and control webcam exposure settings (shutter speed and ISO/gain) on Linux systems. Chrome on Linux uses the V4L2 (Video4Linux2) kernel API to access low-level camera controls, which provides full support for manual exposure control via the Image Capture API. This is one of the few platform/browser combinations where programmatic camera control actually works. This test will help us determine what capabilities are available on your specific hardware and verify that both browser-level and system-level control are functioning properly. ## Prerequisites - A physical webcam (built-in or USB) - Chrome browser (version 101 or later recommended) - Linux system with V4L2 support (standard on most distributions) - `v4l2-ctl` utility installed (usually in `v4l-utils` package) - Ubuntu/Debian: `sudo apt install v4l-utils` - Fedora: `sudo dnf install v4l-utils` - Arch: `sudo pacman -S v4l-utils` ## Test Steps ### Step 1: Verify V4L2 Devices Check that your system can see the webcam at the kernel level: ```bash v4l2-ctl --list-devices ``` **Expected output:** ``` Integrated Camera: Integrated C (usb-0000:00:14.0-5): /dev/video0 /dev/video1 ``` Note which `/dev/video*` device is your camera (usually `/dev/video0`). ### Step 2: Check Available V4L2 Controls List all controls your camera supports: ```bash v4l2-ctl -d /dev/video0 --list-ctrls ``` **Expected output should include:** ``` exposure_auto 0x009a0901 (menu) : min=0 max=3 default=3 value=3 exposure_absolute 0x009a0902 (int) : min=3 max=2047 step=1 default=250 value=250 exposure_auto_priority 0x009a0903 (bool) : default=0 value=1 ``` Look specifically for: - `exposure_auto` - Auto exposure mode setting - `exposure_absolute` - Manual exposure time (shutter speed) - `gain` or `iso_sensitivity` - ISO/gain control (not all cameras expose this) ### Step 3: Test V4L2 Manual Control Try setting exposure manually using V4L2 commands: ```bash # Set exposure to manual mode (1 = manual, 3 = auto) v4l2-ctl -d /dev/video0 -c exposure_auto=1 # Set a specific exposure value (adjust based on your camera's range) v4l2-ctl -d /dev/video0 -c exposure_absolute=100 # Read back the current value v4l2-ctl -d /dev/video0 -C exposure_absolute ``` **Expected behavior:** - If you have a camera app open (like Cheese or guvcview), you should see the image get darker/brighter - The read-back command should show the value you just set ### Step 4: Check Browser Support 1. Open Chrome and navigate to: `chrome://version` 2. Verify you're on Chrome 101+ and Linux 3. Open the browser console (F12 or Right-click → Inspect → Console tab) ### Step 5: Check if Exposure Constraints are Supported in Browser Paste this code into the console and press Enter: ```javascript navigator.mediaDevices.getSupportedConstraints(); ``` **Expected results:** - Look for `exposureMode: true` and `exposureTime: true` in the output - Linux Chrome should show these as `true` - If they're missing, your Chrome version may be too old or there's a configuration issue ### Step 6: Test Camera Capabilities in Browser Request camera access and check what your specific camera exposes to the browser: ```javascript navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { const track = stream.getVideoTracks()[0]; const capabilities = track.getCapabilities(); console.log('Camera capabilities:', capabilities); // Look specifically for exposure controls if (capabilities.exposureMode) { console.log('✅ Exposure modes supported:', capabilities.exposureMode); } else { console.log('❌ Exposure mode not supported'); } if (capabilities.exposureTime) { console.log('✅ Exposure time range:', capabilities.exposureTime); console.log(' Min:', capabilities.exposureTime.min, 'microseconds'); console.log(' Max:', capabilities.exposureTime.max, 'microseconds'); } else { console.log('❌ Exposure time not supported'); } if (capabilities.iso) { console.log('✅ ISO range:', capabilities.iso); } else { console.log('⚠️ ISO not supported (many cameras don\'t expose this)'); } // Keep stream open for next test window.testStream = stream; window.testTrack = track; }) .catch(err => console.error('Camera access denied:', err)); ``` **Expected results:** - Should see exposure time ranges (e.g., `{min: 1, max: 1250, step: 1}`) - The min/max values should roughly correspond to what you saw in V4L2 (though units may differ) - ISO support varies by camera - don't worry if this is missing ### Step 7: Test Manual Control in Browser If Step 6 showed exposure controls are available, test setting them manually: ```javascript // First, get current settings to see starting point console.log('Current settings:', window.testTrack.getSettings()); // Switch to manual exposure mode window.testTrack.applyConstraints({ exposureMode: 'manual' }) .then(() => { console.log('✅ Switched to manual exposure mode'); // Set very low exposure time (should make image dark) return window.testTrack.applyConstraints({ exposureTime: 50 // 50 microseconds - adjust based on your camera's range }); }) .then(() => { console.log('✅ Set exposure time to 50 microseconds (image should be dark)'); // Wait 2 seconds so you can observe the change return new Promise(resolve => setTimeout(resolve, 2000)); }) .then(() => { // Set high exposure time (should make image bright) return window.testTrack.applyConstraints({ exposureTime: 500 // adjust based on your camera's max }); }) .then(() => { console.log('✅ Set exposure time to 500 microseconds (image should be brighter)'); // Try setting ISO if supported if (window.testTrack.getCapabilities().iso) { return window.testTrack.applyConstraints({ iso: 800 // adjust based on your camera's range }); } else { console.log('⚠️ Skipping ISO test (not supported by this camera)'); } }) .then(() => { console.log('✅ Set ISO to 800 (if supported)'); // Read back all current settings const settings = window.testTrack.getSettings(); console.log('Final settings:', settings); console.log('Exposure mode:', settings.exposureMode); console.log('Exposure time:', settings.exposureTime, 'microseconds'); if (settings.iso) console.log('ISO:', settings.iso); }) .catch(err => console.error('Failed to set constraints:', err)); ``` **Expected results:** - You should see the video feed change brightness in real-time as exposure values change - Console should show confirmation messages for each step - The final `getSettings()` should reflect the values you set ### Step 8: Verify V4L2 and Browser are Synchronized Check that browser changes are reflected at the kernel level: ```bash # While the browser still has the camera open, check V4L2 values v4l2-ctl -d /dev/video0 -C exposure_absolute ``` **Expected result:** - The V4L2 value should roughly match what you set in the browser - Note: Units may differ (microseconds in browser vs. device-specific units in V4L2) ### Step 9: Clean Up In the browser console: ```javascript // Stop the camera stream if (window.testStream) { window.testStream.getTracks().forEach(track => track.stop()); console.log('Camera stream stopped'); } ``` ## Alternative Test: Use WebRTC Sample Page Visit this official test page: https://webrtc.github.io/samples/src/content/getusermedia/exposure/ This page provides sliders to test exposure control in a visual interface without needing to type console commands. ## Reporting Results Please report back with: 1. **System info:** - Linux distribution and version - Chrome version - Camera model (from `v4l2-ctl --list-devices`) 2. **V4L2 capabilities:** - Output of `v4l2-ctl -d /dev/video0 --list-ctrls | grep exposure` - Did manual V4L2 control work? (Step 3) 3. **Browser results:** - Did `getSupportedConstraints()` show exposure support? - What ranges did `getCapabilities()` report? - Did manual control via browser work? (Step 7) - Did you observe visual changes in brightness? 4. **Any errors or unexpected behavior** ## Troubleshooting **Problem:** Camera not found by V4L2 - Check camera is connected: `ls -l /dev/video*` - Try unplugging and replugging USB cameras - Check permissions: `sudo usermod -a -G video $USER` (then log out/in) **Problem:** Browser shows camera but no exposure controls - Verify Chrome version is 101+ - Try Chrome Canary/Dev channel - Some cameras don't expose these controls even though V4L2 supports them **Problem:** applyConstraints() fails with OverconstrainedError - The value you're requesting is outside the camera's supported range - Check capabilities again and use values within min/max - Try removing all constraints and setting them one at a time **Problem:** Changes don't appear to affect the image - Some cameras ignore certain parameters - Try more extreme values (very low exposure like 10, or very high like 1000) - Check if auto-exposure is still enabled: set `exposureMode: 'manual'` first ```