DirectShow USB webcam changing video source

2020-04-14 06:57发布

问题:

Hey all i am trying to find the setting to change my video source to "composite" on my webcam. Seems that if i unplug the USB and then plug it back in and fire up the code, its just got a blank screen. But once i change the video source (in another program) and then go back and run my code again, it shows up.

So i need something that will allow me to change that in order for that same thing to happen but within my own app without having to start another program that has that feature to set the webcam.

When i pull the USB cable out then put it back in and i run the source code, the app's picturebox is Black.

The "other program" i use to change the video source (that seems to work to bring up the image):

After i use that "other program" i go back to the source code and run it and this is what i get then:

I am using the C# code called dot Net Webcam Library from here: enter link description here

It seems to use the DirectShow from enter link description here

I have noticed in the source for that it lists different types of video settings (found below in the AXExtend.cs):

public enum PhysicalConnectorType
{
    Video_Tuner = 1,
    Video_Composite,
    Video_SVideo,
    Video_RGB,
    Video_YRYBY,
    Video_SerialDigital,
    Video_ParallelDigital,
    Video_SCSI,
    Video_AUX,
    Video_1394,
    Video_USB,
    Video_VideoDecoder,
    Video_VideoEncoder,
    Video_SCART,
    Video_Black,

    Audio_Tuner = 0x1000,
    Audio_Line,
    Audio_Mic,
    Audio_AESDigital,
    Audio_SPDIFDigital,
    Audio_SCSI,
    Audio_AUX,
    Audio_1394,
    Audio_USB,
    Audio_AudioDecoder,
}

But i am unsure of how to call that up in the code here:

Device selectedDevice = device as Device;
imageCapture.Device = selectedDevice as Device;
imageCapture.PerformAutoScale();
imageCapture.Refresh();
imageCapture.Start();

So i am guessing that the "Video_Composite" is what i may need in order to do that?

Any help would be great!!! Thanks!

David

Code update

foreach (Device device in Device.FindDevices())
{
   if (device.ToString() == "BackupCamera")
    {
        Device selectedDevice = device as Device;
        IGraphBuilder graphBuilder = new FilterGraph() as IGraphBuilder;
        DsDevice device1 = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)[1]; // <<--- Your Device
        Guid baseFilterIdentifier = typeof(IBaseFilter).GUID;
        object videoSourceObject;
        device1.Mon.BindToObject(null, null, ref baseFilterIdentifier, out videoSourceObject);
        IBaseFilter videoSourceBaseFilter = videoSourceObject as IBaseFilter;
        graphBuilder.AddFilter(videoSourceBaseFilter, "Source");
        ICaptureGraphBuilder2 captureGraphBuilder = new CaptureGraphBuilder2() as ICaptureGraphBuilder2;
        captureGraphBuilder.SetFiltergraph(graphBuilder);
        object crossbarObject;
        captureGraphBuilder.FindInterface(FindDirection.UpstreamOnly, null, videoSourceBaseFilter, typeof(IAMCrossbar).GUID, out crossbarObject);
        IAMCrossbar crossbar = crossbarObject as IAMCrossbar;
        int inputPinCount, outputPinCount;
        crossbar.get_PinCounts(out inputPinCount, out outputPinCount); // <<-- In/Out Pins
        // Pin Selection: Physical Input 2 (e.g. Composite) to Capture Pin 0 
        crossbar.Route(0, 2);

        imageCapture.Device = selectedDevice as Device;
        imageCapture.PerformAutoScale();
        imageCapture.Refresh();
        imageCapture.Start();
    }
}

回答1:

Before running the filer graph, you need to obtain the crossbar interface. You typically use ICaptureGraphBuilder2::FindInterface for this. This requires an additional filter and the FindInterface method is useful specifically for this reason:

Supporting Filters. If a capture device uses a Windows Driver Model (WDM) driver, the graph may require certain filters upstream from the WDM Video Capture filter, such as a TV Tuner filter or an Analog Video Crossbar filter. If the pCategory parameter does not equal NULL, this method automatically inserts any required WDM filters into the graph.

Having this done, you will have IAMCrossbar interface, and IAMCrossbar::Route method is how you switch the inputs.

See also: Crossbar filter change current input to Composite

Code snippet:

IGraphBuilder graphBuilder = new FilterGraph() as IGraphBuilder;
DsDevice device = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)[1]; // <<--- Your Device
Guid baseFilterIdentifier = typeof(IBaseFilter).GUID;
object videoSourceObject;
device.Mon.BindToObject(null, null, ref baseFilterIdentifier, out videoSourceObject);
IBaseFilter videoSourceBaseFilter = videoSourceObject as IBaseFilter;
graphBuilder.AddFilter(videoSourceBaseFilter, "Source");
ICaptureGraphBuilder2 captureGraphBuilder = new CaptureGraphBuilder2() as ICaptureGraphBuilder2;
captureGraphBuilder.SetFiltergraph(graphBuilder);
object crossbarObject;
captureGraphBuilder.FindInterface(FindDirection.UpstreamOnly, null, videoSourceBaseFilter, typeof(IAMCrossbar).GUID, out crossbarObject);
IAMCrossbar crossbar = crossbarObject as IAMCrossbar;
int inputPinCount, outputPinCount;
crossbar.get_PinCounts(out inputPinCount, out outputPinCount); // <<-- In/Out Pins
// Pin Selection: Physical Input 2 (e.g. Composite) to Capture Pin 0 
crossbar.Route(0, 2);