Skip to content

Conversation

@cmorillas
Copy link

@cmorillas cmorillas commented Oct 15, 2025

Partially addresses #95 - Adds NV12 format support and fixes continuous frame delivery

Problem

The current Windows DirectShow implementation has three critical issues:

  1. Single-frame capture: Streaming stops after the first frame due to Null Renderer connection
  2. No virtual camera support: Only YUY2 format supported, preventing OBS Virtual Camera from working
  3. Unfriendly device names: Shows DirectShow paths instead of readable camera names

Solution

This PR fixes all three issues:

  • ✅ Removes Null Renderer connection to enable continuous frame delivery
  • ✅ Auto-detects NV12 and YUY2 formats based on buffer size
  • ✅ Converts both formats to I420 (4:2:0) for consistency
  • ✅ Uses IPropertyBag FriendlyName property for readable camera names
  • ✅ Fixes memory leak in Open() if listResolution fails
  • ✅ Optimizes NV12 conversion with loop unrolling
  • ✅ Adds channel buffer to reduce frame drops

Testing

Tested on Windows 10/11 with:

  • ✅ OBS Virtual Camera (NV12 format) - now works
  • ✅ Physical webcams (YUY2 format) - continue working
  • ✅ Device enumeration - shows friendly names
  • ✅ Continuous streaming - sustained 30+ FPS

Before/After

Device names:

Before: @device_sw_{860BB310-5D01-11D0-BD3B-00A0C911CE86}\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}
After:  OBS Virtual Camera

Streaming:

Before: Stops after 1 frame ❌
After:  Continuous 30+ FPS ✅

Files Modified

  • pkg/driver/camera/camera_windows.cpp (~90 lines changed)
  • pkg/driver/camera/camera_windows.go (~25 lines changed)

Breaking Changes

None - 100% backward compatible

Notes

This patch was developed with Claude AI assistance through extensive testing and iteration. I'm not a C programmer, so please review carefully. Happy to address any feedback!

Co-authored-by: Claude AI https://claude.ai

Fix three critical issues in Windows DirectShow camera driver:

1. Single-frame capture bug - streaming stopped after first frame
2. No virtual camera support - OBS Virtual Camera didn't work
3. Unfriendly device names - showed DirectShow paths instead of camera names

Changes:
- Remove Null Renderer connection to enable continuous frame delivery
- Auto-detect NV12 and YUY2 formats based on buffer size
- Convert both formats to I420 (4:2:0) for consistency
- Use IPropertyBag FriendlyName property for readable camera names
  (e.g., "OBS Virtual Camera" instead of "@device_sw_{...}\{...}")
- Fix memory leak in Open() if listResolution fails
- Optimize NV12 conversion with loop unrolling
- Add channel buffer to reduce frame drops
- Add oleaut32 library dependency for VARIANT functions

Tested on:
- Windows 10/11
- OBS Virtual Camera (NV12 format) - now works
- Physical webcams (YUY2 format) - continue working
- Device enumeration shows friendly names
- Sustained 30+ FPS streaming

Files modified:
- pkg/driver/camera/camera_windows.cpp
- pkg/driver/camera/camera_windows.go
@codecov
Copy link

codecov bot commented Oct 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 42.52%. Comparing base (a68a5ba) to head (bb4bc95).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #657   +/-   ##
=======================================
  Coverage   42.52%   42.52%           
=======================================
  Files          84       84           
  Lines        5703     5703           
=======================================
  Hits         2425     2425           
  Misses       3130     3130           
  Partials      148      148           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@at-wat at-wat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing windows code!
(Most of the active developers don't use windows)

memset(&mediaType, 0, sizeof(mediaType));
mediaType.majortype = MEDIATYPE_Video;
mediaType.subtype = MEDIASUBTYPE_YUY2;
// Accept any format by leaving subtype as zeros (equivalent to GUID_NULL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that an incompatible format is chosen?

Comment on lines +380 to +381
// FIX: Don't connect to null renderer
// Null renderer causes DirectShow to pause after one frame
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought output pins should be terminated by connecting to null renderer when I wrote this long ago. (I'm not familiar with windows API)
If it's not necessary, please remove the code instead of commenting out.

Comment on lines +505 to +507
fprintf(stderr, "Unexpected buffer size: %d (expected NV12=%d or YUY2=%d)\n",
len, expectedNV12, expectedYUY2);
return S_OK;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the whole program should fail instead of ignoring the data if an incompatible format is selected.

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.

2 participants