Skip to content

Refine media capture interop source placement and startup fallback#57

Merged
General-Fault merged 10 commits into
mainfrom
feature/48-implement-media-capture-api
Jun 5, 2026
Merged

Refine media capture interop source placement and startup fallback#57
General-Fault merged 10 commits into
mainfrom
feature/48-implement-media-capture-api

Conversation

@General-Fault
Copy link
Copy Markdown
Owner

Summary

Moves CameraVideoSource from WebRtcInterop\Media to WebRtcInterop\ to reflect that it is a WebRTC capture-source primitive, and keeps MediaDevices as the consumer. This also includes the recent capture capability fallback startup flow (tiered capabilities + best-match probing) so camera startup is more resilient.

Change Area (required)

  • API-only managed change (WebRtcNet.Api / managed-only behavior)
  • Interop / marshaling / native-boundary change
  • Docs/infra only (no behavior change)

Required Evidence (for behavioral/API changes)

1) W3C reference (required when applicable)

2) Google source reference (required when applicable)

Provide pinned references: path + revision context (commit SHA or branch/tag).

  • Source path(s):
    • modules/video_capture/video_capture_factory.*
    • modules/video_capture/video_capture_defines.h
    • api/media_stream_interface.h
  • Revision context (SHA/branch/tag):
    • WebRTC branch branch-heads/7778 (repo pipeline target used by this project)
  • Notes on alignment:
    • Uses libwebrtc VideoCaptureFactory::Create(...), CreateDeviceInfo(), and capability matching/start semantics as the primary implementation reference.

3) Intended observable behavior (required when applicable)

Describe externally observable behavior (state transitions, event ordering, timing, errors).

  • Behavior summary:
    • GetUserMedia(audio/video) creates a local stream with requested tracks; video uses camera-backed capture source and now attempts fallback capture capabilities when preferred mode cannot start.
    • Device enumeration returns available audio/video devices and raises OnDeviceChange on detected device set changes.
  • Why this behavior is correct:
    • Maintains requested-track semantics and explicit failures when requested device kinds are unavailable, while improving startup robustness on variable camera capability sets.

4) Divergence from Google reference (required if diverging)

  • No divergence
  • Divergence exists (explain below)
  • Divergence details (what differs, why .NET/runtime needs require it, and which web-observable semantics are preserved):
    • N/A.

Test Evidence (required)

Tests added/updated

  • No new tests in this PR.

Commands run + results

  • dotnet test WebRtcNet.Api.UnitTests\WebRtcNet.Api.UnitTests.csproj → Passed (214/214)
  • MSBuild.exe WebRtcInterop\WebRtcInterop.Framework.vcxproj -p:Configuration=Debug -p:Platform=x64 → Succeeded

Change-area test gate confirmation

  • API-only managed change: ran managed NUnit tests
  • Interop/native-boundary change: ran interop unit tests (when environment available)
  • Required environment unavailable (explain below)

If environment unavailable (required when checked above)

  • Missing environment/dependency:
    • Interop Google Test binary execution (WebRtcInterop.UnitTests) is not currently available in this environment.
  • What was run instead:
    • Managed NUnit suite + interop framework project build.
  • Residual risk:
    • Interop runtime behavior is build-validated but not covered by native interop unit execution in this run.

Documentation

  • No external docs impact.
  • I updated documentation for externally visible behavior changes.

Spec/Crosswalk Review (required for W3C-aligned behavior changes)

  • Reviewed docs\standards\crosswalk\webrtcnet-api-to-spec.md
  • Reviewed docs\standards\specs\index\spec-map.md
  • Refreshed/checked local spec snapshots (.\scripts\update-spec-docs.ps1) when needed

Media capture API status (not implemented / partially implemented)

Current known gaps in the Media Capture surface:

  1. MediaStreamConstraints.AudioConstraints / VideoConstraints are accepted but not fully enforced in interop; current selection is primarily kind-based (Audio/Video) with capability fallback for video startup.
  2. MediaDevices.GetSupportedConstraints() currently returns default MediaTrackSupportedConstraints without mapping real supported constraint flags.
  3. InputDeviceInfo.GetCapabilities() is not implemented and throws NotImplementedException (WebRtcNet.Api\Media\InputDeviceInfo.cs).
  4. MediaStreamTrack capability/settings/constraint application is partial:
    • GetCapabilities() returns an empty default object.
    • GetSettings() returns an empty default object.
    • ApplyConstraints(...) stores constraints locally but does not apply them to native tracks.
  5. Error/logging behavior in device enumeration is still basic (several native failures are swallowed with retry-oriented fallback behavior) pending the logging work tracked in Add structured logging infrastructure using Microsoft.Extensions.Logging #56.

- Add MarshalMedia.h with marshalling for MediaDeviceKind enum and media state enums
- Implement EnumerateDevices() to query Windows audio devices using WASAPI
- Add MediaDeviceInfo.Create() factory method for interop to create device info records
- Support both audio input and audio output device enumeration
- Add placeholder for video device enumeration (future work)
- All compilation warnings only, no errors

Related to issue #49
BugzId:48
Add minimal GetUserMedia implementation that validates input arguments.
Full implementation will require:
- Native WebRTC VideoTrackSourceInterface/AudioSourceInterface implementations
- Audio/video device source creation using Windows APIs (WASAPI for audio, DirectShow/WinRT for video)
- MediaStream construction with tracks from sources
- PeerConnectionFactory::CreateVideoTrack and CreateAudioTrack integration

Builds successfully with no errors.
BugzId:48
Implement MVP GetUserMedia that creates audio and video tracks using the
native WebRTC PeerConnectionFactory API.

New files:
- WebRtcInterop/Media/SimpleVideoSource.h/cpp: Minimal VideoTrackSourceInterface
  implementation that satisfies the WebRTC API contract without capturing video.
  Can be upgraded to real capture (DirectShow/WinRT) later.

Changes:
- MediaDevices::GetUserMedia() now:
  * Validates audio/video constraints (at least one must be true)
  * Gets the native PeerConnectionFactory instance
  * Creates a native MediaStream
  * Creates audio track with null source (allowed by WebRTC API)
  * Creates video track with SimpleVideoSource
  * Returns managed MediaStream wrapper

Benefits:
- Unblocks BasicVideoChat rendering and track management
- MediaStream tracks can be enumerated, muted, and events fire
- Real audio/video capture can be integrated later as an upgrade
- No dependency on DirectShow or WASAPI yet

Tests: All 107 managed API tests pass

BugzId:48
Implement MVP constrainable behavior for MediaStreamTrack by removing
NotImplementedException paths in constraint APIs.

- Add per-track applied_constraints_ state in WebRtcInterop::Media::MediaStreamTrack
- Initialize to empty MediaTrackConstraints in constructors
- Implement GetConstraints() to return current applied constraints
- Implement ApplyConstraints(null) to clear constraints to an empty set
- Implement ApplyConstraints(non-null) to persist supplied constraints

This provides a stable, non-throwing baseline for apps using the constraint
APIs while full native capability/settings marshalling is completed later.

BugzId:48
Use Google WebRTC's own VideoCaptureFactory::CreateDeviceInfo path to
enumerate Windows video input devices instead of the local stub.

- Implement EnumerateVideoDevices() via VideoCaptureModule::DeviceInfo
  NumberOfDevices/GetDeviceName and map to MediaDeviceInfo
- Populate video device id/label/groupId from WebRTC-provided unique/product ids
- Fix managed->native string conversion in GetUserMedia track/stream ids using
  marshal_as<std::string> instead of wide-char reinterpret casts
- Add strmiids.lib to interop link dependencies (required by DirectShow IIDs
  referenced by webrtc.lib device_info_ds/video_capture_ds objects)

BugzId:48
Implement the next post-MVP MediaDevices hardening items.

- Add MediaDevices lifetime management with timer-based device polling
- Track known devices and raise OnDeviceChange when device snapshots differ
- Populate DeviceChangeEventArgs with full current list and inserted-device subset
- Enforce requested device availability in GetUserMedia (audio/video)
- Convert track creation/add failures to MediaStreamException instead of
  returning partial/empty streams

This keeps MediaDevices behavior predictable for app callers while preserving
MVP capture architecture.

BugzId:48
@General-Fault General-Fault merged commit 136e02b into main Jun 5, 2026
1 check failed
@General-Fault General-Fault deleted the feature/48-implement-media-capture-api branch June 5, 2026 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant