-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[3.x] Implement CameraServer on Windows #49763
base: 3.x
Are you sure you want to change the base?
[3.x] Implement CameraServer on Windows #49763
Conversation
Webcams that go above 1080p are still not that common right now, so I think it's fine to limit the maximum supported resolution to 4K 🙂 |
3381e6e
to
97f3f11
Compare
97f3f11
to
71d2ee8
Compare
Cleaned up a bit, fixed formatting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still impressed that you got this running on other compilers. I tried to write this myself a while ago and threw in the towel after a few days.
I do have some experience with patchy Windows APIs in MinGW from #38210, but this was so much harder.
To be honest if I knew how difficult this would be I probably wouldn't have done it. The Media Foundation functions and GUIDs implemented varies wildly across different MinGW versions, and in some rare cases symbols are incorrectly defined. In addition there are sometimes function prototypes without implementations (depending on the mingw version) which is why I resort to run-time linking for some functions. I haven't fought a compiler that hard since the time I tried to learn rust. |
When I activate the camera in the editor it works, but in the game it is not there or a green rectangle. If I deactivate it in the editor and run
it works in the game. |
@Gamemap
I think so, especially if this behavior is on macOS and Windows (possibly Linux once it gets a CameraServer implementation).
^ I think this would be the solution to the problem. It would fix it on all platforms exhibiting this issue. |
IIRC, the green screen fallback is drawn by Godot. Maybe we could change this fallback texture to have some text like "No cameras available". |
Stumbled over this before trying to implement something similar. So I toyed around with it a bit and wanted to note a few points:
|
Thanks for doing this. It is a big help. I tested this last night, and it works, but the feed is pretty slow. Many cameras perform much faster at MJPG. If there were a way to work that in, it would help quite a bit. |
Was this added to Godot 3.4? I tried using printing CameraServer.get_feed[0] in 3.4 and it is empty, despite my laptop having a webcam. |
This pull request wasn't merged yet, so no. Since 3.4 is in feature freeze with a RC expected soon, this pull request is more likely to be merged in 3.5 instead. |
71cb8d3
to
c58391c
Compare
Thanks, I'll be sure to make these changes and update the PR edit: I probably won't get around to doing depth sensors. Maybe in a future commit |
Heya, can we contribute or sponsor development to get this PR merged into 3.5? We'd love to be able to use it. |
It's a similar situation as #47967 (comment), except this PR targets Still, nothing prevents you from creating custom editor and export template binaries with this PR included 🙂 As for sponsoring development, see "Commercial support" on the Contact page. This is intended to be used for larger features though, and not finishing up a PR that is already mostly complete. |
@bnolan
The master branch has improved a lot since I wrote this. If/when it's ready I'll bring it forward to master branch at some point (along with changes suggested by people here) then update this PR to 3.X
If you need it right now then this is the way to go (it's what our team is doing) If you really need it in a more up-to-date 3.X version and are willing to experiment you could copy-paste the modules/camera folder from this PR into a modern 3.x version and see if it compiles (I know for sure that hot-plugging won't work). |
public: | ||
CameraWindows(); | ||
~CameraWindows(); | ||
|
||
void update_feeds(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be marked as override, I think.
Are you still interested in working on this PR? If not, I'm willing to port it to master, as I need it for a project that I'm working on. |
@TechnoPorg I've got a working version for master on my fork. It probably is a better basis than this PR. |
Great, thanks! |
Currently testing this with the latest 3.x changes.
I'm not sure that virtual cameras are working anymore. I have tested with OBS and NVIDIA Broadcast; in both cases only the real camera is being detected. Is there anything I need to do to get virtual cameras to show up? |
@RedMser I've rebased your branch against
Edit: This is because this PR doesn't extend the interface like #53666 did. I don't know how I'm supposed to use the webcam stream then... I've tried using a TextureRect + CameraTexture setup, but changing the camera feed ID to
Footnotes
|
@Calinou I don't think the changes in my fork are complete (it's been a while, so I forgot how much of it is just a port of this PR). My test project did something like this (note I don't have it set up right now, so I can't guarantee this to work as-is): A scene with multiple texture rects. Following code files: # root.gd
## run e.g. when changing a value on a SpinBox. use CameraServer.get_feed_count() to check if out of bounds
func load_feed(value: int):
var feed := CameraServer.get_feed(value)
if feed == null:
$HBoxContainer/TextureRect.texture = null
$HBoxContainer/TextureRect2.texture = null
return
for f in CameraServer.feeds():
f.feed_is_active = false
feed.feed_is_active = true
var ctY := CameraTexture.new()
ctY.camera_feed_id = feed.get_id()
ctY.which_feed = CameraServer.FEED_Y_IMAGE
$HBoxContainer/TextureRect.texture = ctY
var ctB := CameraTexture.new()
ctB.camera_feed_id = feed.get_id()
ctB.which_feed = CameraServer.FEED_CBCR_IMAGE
$HBoxContainer/TextureRect2.texture = ctB
$HBoxContainer/TextureRect3.material.set_shader_param("tex_Y", ctY)
$HBoxContainer/TextureRect3.material.set_shader_param("tex_CbCr", ctB) // root.gdshader on TextureRect3
shader_type canvas_item;
uniform sampler2D tex_Y;
uniform sampler2D tex_CbCr;
void fragment() {
COLOR.r = texture(tex_Y, UV).r;
COLOR.gb = texture(tex_CbCr, UV).rg - vec2(0.5, 0.5);
COLOR.a = 1.0;
// Using BT.601, which is the standard for SDTV is provided as a reference
COLOR.rgb = mat3(
vec3(1.00000, 1.00000, 1.00000),
vec3(0.00000, -0.34413, 1.77200),
vec3(1.40200, -0.71414, 0.00000)) *
COLOR.rgb;
} So likely the interface needs to be extended, and some of this math should be done by the C++ code and not by the user in shaders. |
This PR implements webcam support on Windows via the Media Foundation API and partially solves #46531.
Tested on both virtual and real cameras, compiled with both MSVC and MinGW/Linux. Supports hot-plugging and performs YUV to RGB conversion on the GPU (massive thanks to whoever wrote those shaders).
The actual code for acquiring/decoding/releasing streams has been tested thoroughly as I’ve been using it for a work project for a few weeks. The main issue is getting MinGW to compile and link with the Media Foundation libraries. I’ve got it to a point where it seems to build on MinGW W64 major version 5 and newer. The MinGW workarounds are as elegant as I could get them but they're still pretty ugly. I would appreciate any testing to find a MinGW version under which it breaks.
I’m aware that there are currently other pull requests and forks for this, however they all convert YUV to RGB on the CPU (can't be used for higher resolutions), have no hot-plugging support and require MSVC to compile.
I understand PRs should generally be for the master branch and cherry-picked, but I checked quite recently and a lot of the CameraServer implementation in master was missing due to 4.0 refactoring. If the CameraFeed methods stay the same in 4.0, this should be trivial to bring port to it.
Some things I’m not entirely sure about: