Skip to content
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 Microsoft Media Foundation on camera_win.cpp #44498

Open
wants to merge 3 commits into
base: 3.x
Choose a base branch
from

Conversation

choonway
Copy link

@choonway choonway commented Dec 18, 2020

Proof of concept for webcam on windows on media foundation based on their examples (MFCaptureD3D)
quality is Frankenstein.
not able to test on master branch due to bugs (texture related?)
test files can be obtained from https://github.com/choonway/godot-camera_win-test

tested to work on camera on HTC Vive.
If camera can't be accessed by camera app on windows, chances are that it won't work.

limitations:
virtual cameras and some webcams don't work (HTC Vive Pro Eye cameras)
hotplug not working/implemented

proof of concept for webcam on ms windows
@choonway choonway changed the title Implemented microsoft media foundation Implemented microsoft media foundation on Camera_win.cpp Dec 18, 2020
set attribute to prevent shudown
formatting changes
@BastiaanOlij
Copy link
Contributor

This looks really good at first glance, thanks !

I get why some of the stuff is all done within the CPP source file while it should really be split into a header file I can see that can be an issue with some of the MF stuff.

This won't work on the master branch because the camera server at it's heart is still very much based on OpenGL, That said if this all works fine and has its rough sides polished a bit we should merge it into master even if disabled so we can make it all work on both OpenGL and Vulkan renderers.

Definitely would suggest getting the logic to work to detect when cameras are attached after Godot has started running.

}

void TransformImage_YUY2(
BYTE *pDest,
Copy link
Contributor

Choose a reason for hiding this comment

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

For the MacOS camera stuff I made a shader that can handle YUV so we didn't need to do conversions on the CPU side. Is it worth looking at this further and adding YUY2 support as well or does it make more sense to have this RGB conversion in?

I believe there is a conversion library already linked in as a 3rd party module?

Copy link
Author

Choose a reason for hiding this comment

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

can't seem to find the conversion library, but found some reference code to do it within MF itself. Curious why the provided sample files didn't use them. Going to implement them.

if (SUCCEEDED(hr)) {
hr = pAttributes->SetUINT32(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN, TRUE);
if (FAILED(hr)) {
printf("Set attribute (disable shutdown on disconnect) failed\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpicking but it is better to use Godots internal print methods so the messages get locked to the log in the editor. You can also switch between what is considered info and what is actually an error.

Copy link
Author

Choose a reason for hiding this comment

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

ok. i am going to do some tidying up as well.

};

CameraWindows::CameraWindows() {
// Find cameras active right now
HRESULT hr = MFStartup(MF_VERSION);
add_active_cameras();

// need to add something that will react to devices being connected/removed...
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes we should add logic that ensures we detect cameras being connected or disconnected to the PC.

Copy link
Author

Choose a reason for hiding this comment

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

there is an existing mechanism - the one used by the joypad to detect hotplug hardware - using WM_DEVICECHANGE - but it seems it's going to touch a lot of other files so I'll leave it for some other time.

Copy link
Contributor

@BastiaanOlij BastiaanOlij left a comment

Choose a reason for hiding this comment

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

I've left a few remarks for improvements, I hope others have some time to put this through its paces, but it looks good enough to me for a first version on which we can improve.

@Chaosus
Copy link
Member

Chaosus commented Dec 20, 2020

@choonway Please, merge commits together as required by our pipeline (https://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html#modifying-a-pull-request)

@choonway
Copy link
Author

@BastiaanOlij There is also a bug with the R and B swapped. Give me a few days to implement the changes.

@Ansraer
Copy link
Contributor

Ansraer commented Feb 25, 2021

@choonway Hey, are you still working on this?

@choonway choonway requested a review from a team as a code owner March 12, 2021 12:26
Base automatically changed from 3.2 to 3.x March 16, 2021 11:11
@aaronfranke aaronfranke modified the milestones: 3.2, 3.3 Mar 16, 2021
@akien-mga akien-mga modified the milestones: 3.3, 3.4 Mar 26, 2021
@Chaosus Chaosus modified the milestones: 3.4, 3.5 Nov 8, 2021
@akien-mga akien-mga force-pushed the 3.x branch 2 times, most recently from 71cb8d3 to c58391c Compare January 6, 2022 22:40
@gotnospirit
Copy link
Contributor

@BastiaanOlij There is also a bug with the R and B swapped

this is because RGBQUAD is a BGR struct

typedef struct tagRGBQUAD {
        BYTE    rgbBlue;
        BYTE    rgbGreen;
        BYTE    rgbRed;
        BYTE    rgbReserved;
} RGBQUAD;

The problem with WM_DEVICECHANGE is we need the HWND handler in order to register
https://github.com/microsoft/Windows-classic-samples/blob/7cbd99ac1d2b4a0beffbaba29ea63d024ceff700/Samples/Win7Samples/multimedia/mediafoundation/MFCaptureD3D/winmain.cpp#L260-L264

For joypad, this is directly handled by OS_windows (or DisplayServerWindows in master) because its a member of this class

case WM_DEVICECHANGE: {
joypad->probe_joypads();
} break;

case WM_DEVICECHANGE: {
joypad->probe_joypads();
} break;

but Camera is a module!

We could maybe introduce a signal to solve this

@KnightNine
Copy link

Wanted to try this out, but trying to compile: https://github.com/godotengine/godot/tree/23e3ce8d8724ee3965dceeed3fc5bbbc84793083
results in this error:

scons: Reading SConscript files ...
Configuring for Windows: target=debug, bits=default
AttributeError: 'SConsEnvironment' object has no attribute 'has_key':
  File "C:\Users\User\Desktop\Godot_v3.1.1-stable_mono_win64\Camera Godot\SConstruct", line 348:
    detect.configure(env)
  File "C:\Users\User\Desktop\Godot_v3.1.1-stable_mono_win64\Camera Godot\./platform/windows\detect.py", line 445:
    setup_msvc_auto(env)
  File "C:\Users\User\Desktop\Godot_v3.1.1-stable_mono_win64\Camera Godot\./platform/windows\detect.py", line 153:
    if env.has_key("msvc_version"):

I tried adding the changes to Camera_win.cpp manually to my 3.5 build to run the demo project, and it results in a monochromatic camera:
monocolor cam
😕

@saierXP
Copy link

saierXP commented Jul 21, 2023

@KnightNine Can you test this? I tried this last year.But I can't remember if I tested the #49763 or this. The conversion shader from yuv to rgb is used.
testcam.zip

@KnightNine
Copy link

KnightNine commented Jul 22, 2023

@saierXP

monocolor cam2

oh good, i'll try #49763 instead.

@KnightNine
Copy link

KnightNine commented Jul 22, 2023

@saierXP
here it is with #49763 instead:
monocolor cam3

Your shader was probably meant to work with this PR which I can't get the CbCr feed from. so it only appears in monocolor.
Whereas 49763 just gives me the formatted colors from the first which_feed.

Color cam!

thus this shader works with 49763:

shader_type canvas_item;

uniform sampler2D camera;



void fragment() {
	vec3 color;
	color.rgb = texture(camera, UV).rgb;
	
	COLOR = vec4(color,1.0);	
}

@akien-mga akien-mga changed the title Implemented microsoft media foundation on Camera_win.cpp [3.x] Implemented Microsoft Media Foundation on camera_win.cpp Jan 5, 2024
@fire
Copy link
Member

fire commented Nov 7, 2024

Is there interest in migrating this to godot engine master 4? I am also investigating video playback.

@AThousandShips AThousandShips changed the title [3.x] Implemented Microsoft Media Foundation on camera_win.cpp [3.x] Implement Microsoft Media Foundation on camera_win.cpp Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.