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

add Camera settings #42

Closed
wants to merge 14 commits into from
Closed

add Camera settings #42

wants to merge 14 commits into from

Conversation

ldlac
Copy link

@ldlac ldlac commented Apr 5, 2023

inspired from this awesome library https://github.com/free5lot/Camera_Net


for (int i = 0; i < cElems; i++)
{
#pragma warning disable CS0618
Copy link
Author

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

Copy link
Owner

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 .

@kekyo
Copy link
Owner

kekyo commented Apr 6, 2023

@ldlac Thanks for the PR! 😄

I haven't checked the commits yet, but is this implemented to display the DS properties page?
For example, can you have it enumerate a group of DS properties programatically and have it set?

When I looked into this before, I had delved into the possibility of doing something like that. For example:.

  • Information like public IReadOnlyDictionary<string, Type> device.Properties {get;} could be exposed to FlashCap users.
  • The user can look at the above dictionary and set the value of the property with device.SetPropertyValue(string name, object? value).

(Whether Type is appropriate or not may require a little more thought.)

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.

@ldlac
Copy link
Author

ldlac commented Apr 6, 2023

Thanks for your feedback @kekyo !

My current implementation is surely not ready for FlashCap, I've only implemented it for DS.
I needed to change the Video Standard of a Video Capture USB

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'm not sure I'll be able to code this solution thought.

@ldlac
Copy link
Author

ldlac commented Apr 6, 2023

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)

@kekyo
Copy link
Owner

kekyo commented Apr 7, 2023

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).
Perhaps some additional work is needed to make it fit the FlashCap API, but we will do that (we will consider whether to merge it once and then make changes or just keep it in this branch).

It would be helpful if you could change the PR branch origin to develop!

@kekyo kekyo linked an issue Apr 7, 2023 that may be closed by this pull request
@ldlac ldlac changed the base branch from main to develop April 7, 2023 02:57
&& graphBuilder != null
&& captureGraphBuilder != null)
{
graphBuilder.FindFilterByName("Capture source", out NativeMethods_DirectShow.IBaseFilter? captureSourceFilter);
Copy link
Author

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'.

Copy link
Author

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?

Copy link
Owner

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.

Copy link
Owner

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...

Copy link
Owner

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.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for this commit, really helped!

The sample is working fine, I'll need to handle flags

image

@@ -174,7 +175,7 @@ private sealed class SampleGrabberSink :

///////////////////////////////

var captureGraphBuilder = NativeMethods_DirectShow.CreateCaptureGraphBuilder();
captureGraphBuilder = NativeMethods_DirectShow.CreateCaptureGraphBuilder();
Copy link
Author

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?

Copy link
Owner

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);
Copy link
Author

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);
Copy link
Author

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 ?

Copy link
Owner

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 _);
Copy link
Author

@ldlac ldlac Apr 7, 2023

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

Copy link
Owner

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)
Copy link
Author

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

Copy link
Owner

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 👍

@@ -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);
Copy link
Author

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

Copy link
Owner

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.

@kekyo
Copy link
Owner

kekyo commented Apr 11, 2023

@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,
Copy link
Author

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

Copy link
Owner

Choose a reason for hiding this comment

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

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.

change camera settings
2 participants