-
Notifications
You must be signed in to change notification settings - Fork 29
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
add Camera settings #42
Conversation
|
||
for (int i = 0; i < cElems; i++) | ||
{ | ||
#pragma warning disable CS0618 |
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 can't find a way to call the Marshal.<T>
ones
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 extremely late in responding due to a lot of private work. My apologies 😵💫
Is it correct that what you want to do here is to copy the GUID structure pointed to by pElems into an array and return it? If so, how about this code for example?
public unsafe Guid[] ToGuidArray()
{
var retval = new Guid[cElems];
fixed (Guid* pr = &retval[0])
{
Guid* pd = pr;
Guid* ps = (Guid*)pElems;
for (var index = 0; index < this.cElems; index++)
{
*pd = *ps;
ps++;
pd++;
}
}
return retval;
}
- We can use the unsafe block in FlashCap, It is used it a lot. (although care must be taken in implementation)
- There should have been compatibility between the layout of the GUID structure in native code and the internal layout of the Guid structure in .
@ldlac Thanks for the PR! 😄 I haven't checked the commits yet, but is this implemented to display the DS properties page? When I looked into this before, I had delved into the possibility of doing something like that. For example:.
(Whether If this can be done, not only can the user define their own configuration dialog, but also multi-platform support is possible (e.g., the V4L2 API may also provide the ability to expose and set property values). Of course, there can and should also be a method to display native property pages (in a platform-specific manner), as in this case. Because there are some poorly implemented DS capture device drivers that do not provide a dictionary of property values and only expose their own property pages. |
Thanks for your feedback @kekyo ! My current implementation is surely not ready for FlashCap, I've only implemented it for DS. I love the idea to expose the properties and be able to display/set them in the proprietary app instead of showing the basic native window. |
I've also implemented the support of crossbar filter, is this something you want to add to FlashCap? With the possibility of showing up the property page (ugly native) |
In the meantime, please try adding that implementation (if possible, I'd appreciate it if you could finish the current implementation once it's all good and split the commits so it's easier for us to review). It would be helpful if you could change the PR branch origin to |
&& graphBuilder != null | ||
&& captureGraphBuilder != null) | ||
{ | ||
graphBuilder.FindFilterByName("Capture source", out NativeMethods_DirectShow.IBaseFilter? captureSourceFilter); |
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.
in my application (wpf), it's working fine, but in the the sample I've created based on OneShot, I'm getting this
Unable to cast COM object of type 'System.__ComObject' to interface type 'IBaseFilter'.
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.
@kekyo I was currently stuck here, any idea why I'm experiencing this?
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.
OK, I will check it.
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.
@ldlac In this source file, there are 3 places that use FindFilterByName
, do all of them throw the same exception? In my environment, the FindFilterByName
in DisplayPropertyPage_CaptureFilter
also threw an exception.
If so, there may be something wrong with FindFilterByName
(I don't know the cause yet). If not, then we need to suspect another cause...
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.
@ldlac I debugged the code and found a problem with the added property page display and the property getter/setter accesses ignoring the COM apartments, so I fixed it.
472f25d (I think the develop
was badly positioned and that caused the weird merge (My mistake), so I fixed it in another branch. develop
has been repositioned, so please rebase it.)
FlashCap has been modified to initialize another thread as a single-threaded apartment and access DS objects only on it, as past implementation experience has shown that accessing the calling COM apartment as it is causes many frame drops The following is a list of the DS objects that can be accessed beyond the apartment.
When accessing the DS object beyond the apartment, the standard COM way is to marshal the interface, but it is tedious to do this in .NET, so we use SynchronizationContext
to send messages. See IndeependentSingleApartmentContext.InvokeAsync()
.
In the environment at hand, this modification allows the capture filter property page to be displayed.
I have not tested the getter and setter, but the modification should give you an idea of what to do.
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.
@@ -174,7 +175,7 @@ private sealed class SampleGrabberSink : | |||
|
|||
/////////////////////////////// | |||
|
|||
var captureGraphBuilder = NativeMethods_DirectShow.CreateCaptureGraphBuilder(); | |||
captureGraphBuilder = NativeMethods_DirectShow.CreateCaptureGraphBuilder(); |
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 needed a way to access the captureGraph, is there a better way?
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.
@ldlac No problem.
if (captureGraphBuilder.SetFiltergraph(this.graphBuilder) < 0) | ||
{ | ||
throw new ArgumentException( | ||
$"FlashCap: Couldn't set graph builder: DevicePath={devicePath}"); | ||
} | ||
|
||
/////////////////////////////// | ||
|
||
captureGraphBuilder.FindInterface(Guid.Empty, Guid.Empty, captureSource, NativeMethods_DirectShow.IAMVideoProcAmpHelper.GUID, out object? videoProcAmpObject); |
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.
on initialize, we can feed the properties dictionary
I've decided to start with IAMVideoProcAmp
I've defined a CaptureDeviceProperty which is implemented for each devices, directshow in this case, the abstraction is based on this one since it's the only one I know of. slightly opiniated.
if (captureGraphBuilder.SetFiltergraph(this.graphBuilder) < 0) | ||
{ | ||
throw new ArgumentException( | ||
$"FlashCap: Couldn't set graph builder: DevicePath={devicePath}"); | ||
} | ||
|
||
/////////////////////////////// | ||
|
||
captureGraphBuilder.FindInterface(Guid.Empty, Guid.Empty, captureSource, NativeMethods_DirectShow.IAMVideoProcAmpHelper.GUID, out object? videoProcAmpObject); |
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 can't use typeof(IAMVideoProcAmp).GUID
because of .netstandard 1.3
any alternative to NativeMethods_DirectShow.IAMVideoProcAmpHelper.GUID
?
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.
@ldlac There is no elegant way to do this, but it can be redefined in the same way as IID_IBaseFilter
.
if (videoProcAmpObject != null) | ||
{ | ||
var videoProcAmp = (NativeMethods_DirectShow.IAMVideoProcAmp)videoProcAmpObject; | ||
videoProcAmp.Get(DirectShowProperty.FromVideoProcessingAmplifierProperty(property), out int value, out NativeMethods_DirectShow.VideoProcAmpFlags _); |
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 don't really know the use of this one yet, NativeMethods_DirectShow.VideoProcAmpFlags
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.
Even in the environment at hand, I was able to obtain a range of values that we believe to be brightness. Nice work!
{ | ||
public DirectShowProperty(VideoProcessingAmplifierProperty property, int min, int max, int step) : base(property, min, max, step) { } | ||
|
||
internal static NativeMethods_DirectShow.VideoProcAmpProperty FromVideoProcessingAmplifierProperty(VideoProcessingAmplifierProperty property) |
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.
each device property should be able to map from VideoProcessingAmplifierProperty
to their own implementation
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.
Perhaps there is a more desirable interface, but this is fine for now 👍
FlashCap.Core/CaptureDevice.cs
Outdated
@@ -66,6 +66,11 @@ public async Task DisposeAsync() | |||
|
|||
protected abstract Task OnStartAsync(CancellationToken ct); | |||
protected abstract Task OnStopAsync(CancellationToken ct); | |||
public abstract void DisplayPropertyPage_CaptureFilter(IntPtr hwndOwner); | |||
public abstract int GetPropertyValue(VideoProcessingAmplifierProperty property); | |||
public abstract void SetPropertyValue(VideoProcessingAmplifierProperty property, object? value); |
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.
eventually SetPropertyValue
if more properties are supported, it should receive a wider Type/Enum
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.
Yes, I agree. Perhaps the key that is considered standard is Enum, and we need to consider a separate specifiable interface if the device provides an extended key, but we have not yet figured out how far to abstract it. So we can reserve this issue here.
@ldlac Request when available for review (no rush, go at your own pace) |
@@ -263,7 +263,7 @@ public interface IEnumFilters | |||
{ | |||
[PreserveSig] int Next( | |||
int request, | |||
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] IPin?[] filters, | |||
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] IBaseFilter?[] filters, |
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 found out this typing error while experimenting
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.
@ldlac Thanks, it is my mistake and your changes are correct.
https://learn.microsoft.com/en-us/windows/win32/api/strmif/nf-strmif-ienumfilters-next
48b9e51
to
5bee4b4
Compare
inspired from this awesome library https://github.com/free5lot/Camera_Net