Webcam grab: SharedReadOnly mode, VideoPreview/VideoRecord source fallback, name the blocking app in the error (NVIDIA Broadcast finding)
This commit is contained in:
@@ -43,14 +43,21 @@ public sealed class MediaCaptureFrameSource : ICameraFrameSource
|
||||
VideoDeviceId = _deviceId,
|
||||
StreamingCaptureMode = StreamingCaptureMode.Video,
|
||||
MemoryPreference = MediaCaptureMemoryPreference.Cpu,
|
||||
SharingMode = MediaCaptureSharingMode.SharedReadOnly,
|
||||
};
|
||||
await capture.InitializeAsync(settings);
|
||||
|
||||
var colorSource = capture.FrameSources
|
||||
.FirstOrDefault(pair => pair.Value.Info.MediaStreamType == MediaStreamType.VideoPreview)
|
||||
.Value;
|
||||
var colorSource = capture.FrameSources.Values
|
||||
.OrderBy(s => s.Info.MediaStreamType == MediaStreamType.VideoPreview ? 0 : 1)
|
||||
.FirstOrDefault(s => s.Info.MediaStreamType is MediaStreamType.VideoPreview or MediaStreamType.VideoRecord);
|
||||
if (colorSource == null)
|
||||
throw new InvalidOperationException($"No video preview source on camera '{_deviceId}'.");
|
||||
{
|
||||
var kinds = string.Join(", ", capture.FrameSources.Values
|
||||
.Select(s => s.Info.MediaStreamType).Distinct());
|
||||
throw new InvalidOperationException(
|
||||
$"Camera '{_deviceId}' exposes no video source (found: {kinds}). " +
|
||||
"It may be locked by another app (e.g. NVIDIA Broadcast).");
|
||||
}
|
||||
|
||||
reader = await capture.CreateFrameReaderAsync(colorSource, MediaEncodingSubtypes.Bgra8);
|
||||
reader.FrameArrived += OnFrameArrived;
|
||||
|
||||
@@ -84,10 +84,19 @@ C# / WPF (.NET 8) following MVVM:
|
||||
- **Seam-first:** everything above the WinRT layer speaks only `VideoFrame` (normalized tightly-packed
|
||||
BGRA8) + `CameraDeviceInfo`/`ICameraEnumerator`/`ICameraFrameSource` interfaces. Tests inject fakes;
|
||||
screen capture and background removal later feed the same seam.
|
||||
- **CPU-first:** `MediaCaptureInitializationSettings { MemoryPreference = Cpu, StreamingCaptureMode = Video }`,
|
||||
frames pulled via `CreateFrameReaderAsync(colorSource, MediaEncodingSubtypes.Bgra8)` — the pipeline does
|
||||
any format conversion, so every `FrameArrived` yields a ready BGRA8 `SoftwareBitmap` (bytes read via
|
||||
- **CPU-first:** `MediaCaptureInitializationSettings { MemoryPreference = Cpu, StreamingCaptureMode = Video,
|
||||
SharingMode = SharedReadOnly }`, frames pulled via
|
||||
`CreateFrameReaderAsync(colorSource, MediaEncodingSubtypes.Bgra8)` — the pipeline does any format
|
||||
conversion, so every `FrameArrived` yields a ready BGRA8 `SoftwareBitmap` (bytes read via
|
||||
`WindowsRuntimeMarshal.TryGetDataUnsafe`, not marshalled copies).
|
||||
- **Source pick, not first hit:** the frame reader is bound to the first source that is `VideoPreview`
|
||||
(preferred) or `VideoRecord`, not blindly the first preview source. If a camera exposes neither, the
|
||||
failure names the device and the stream types it *does* expose. `SharedReadOnly` lets the capture
|
||||
coexist with other apps that share the camera.
|
||||
- **Known failure: NVIDIA Broadcast** — it opens the physical webcam exclusively, so `InitializeAsync`
|
||||
fails with "camera in use" (or, if init slips through, the device exposes no preview source). Fix:
|
||||
quit Broadcast while streaming, or pick its virtual "NVIDIA Broadcast" device from the picker and the
|
||||
app captures the processed feed. This is a real-device finding (Logitech `VID_046D&PID_082D`).
|
||||
- **TFM:** `net8.0-windows10.0.19041.0` (app + tests) pulls the WinRT projection from the SDK reference
|
||||
packs — no NuGet package, no capability manifest (unpackaged desktop app works; the Windows privacy
|
||||
camera toggle still applies). `EnableWindowsTargeting` keeps WSL builds working.
|
||||
|
||||
Reference in New Issue
Block a user