DirectShow USB webcam changing video source - c#

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();
}
}

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);

Related

Access mobile device property data

Is there a way to access a mobile devices properties through C#. The purpose would be to display the device's serial number and iOS version for USB connected like an iPhone.
Using a WMI query like below access is given to the basic info accessible through the Computer Manager like DeviceID or PnpDeviceID. However I have been unable to find a property that gives the device serial number etc.
ManagementObjectSearcher(#"Select * From Win32_USBHub WHERE Description LIKE 'Apple Mobile Device%'")
or
ManagementObjectSearcher(#"Select * From Win32_PnPEntity")
or
ManagementObjectSearcher("#Select * From Win32_USBControllerDevice")
The device property menu I am referring to is in the picture below accessed by right click on a device and then clicking properties.
Placing the code below after lockdown.lockdownd_client_new_with_handshake(deviceHandle, out lockdownHandle, "Quamotion").ThrowOnError(); you will be able to access values like the serial number or iOS version. This is only a crude example:
string t1;
string t2;
PlistHandle tested1;
PlistHandle tested2;
//Find serial number in plist
lockdown.lockdownd_get_value(lockdownHandle, null, "SerialNumber", out
tested1);
//Find IOS version in plist
lockdown.lockdownd_get_value(lockdownHandle, null, "ProductVersion", out
tested2);
//Get string values from plist
tested1.Api.Plist.plist_get_string_val(tested1, out t1);
tested2.Api.Plist.plist_get_string_val(tested2, out t2);
//Place data in textboxes
serialTXT.Text = t1.Trim();
verTXT.Text = t2.Trim();
If you want to access properties such as the iOS version, your best bet may be to use imobiledevice-net.
You can install the imobiledevice-net NuGet package and then run a command like this:
ReadOnlyCollection<string> udids;
int count = 0;
var idevice = LibiMobileDevice.Instance.iDevice;
var lockdown = LibiMobileDevice.Instance.Lockdown;
var ret = idevice.idevice_get_device_list(out udids, ref count);
if (ret == iDeviceError.NoDevice)
{
// Not actually an error in our case
return;
}
ret.ThrowOnError();
// Get the device name
foreach (var udid in udids)
{
iDeviceHandle deviceHandle;
idevice.idevice_new(out deviceHandle, udid).ThrowOnError();
LockdownClientHandle lockdownHandle;
lockdown.lockdownd_client_new_with_handshake(deviceHandle, out lockdownHandle, "Quamotion").ThrowOnError();
string deviceName;
lockdown.lockdownd_get_device_name(lockdownHandle, out deviceName).ThrowOnError();
deviceHandle.Dispose();
lockdownHandle.Dispose();
}
The lockdown class will allow you to access other properties, such as the iOS version, as well.
It does come with a dependency on iTunes, though.

Getting Camera Resolutions Using Accord.Video.DirectShow

I am evaluating the Accord.NET Framework (https://github.com/accord-net/framework/) for use in an imaging application. At the moment I have some basic requirements - capture video from a USB camera to display on the UI and view/change all camera properties.
Accord.Video.DirectShow.VideoCaptureDevice.DisplayPropertyPage works well for showing the camera properties, such as brightness, contrast, hue etc. but does not show available camera resolutions.
Accord.Video.DirectShow.VideoCaptureDevice.VideoCapabilities is returning only one resolution but I was expecting several more.
I have tried the VideoCapx (http://videocapx.com/) ActiveX control and using its ShowVideoFormatDlg method I can display a dialog which shows all available resolutions, framerates etc. I understand this is a dialog provided by the manufacturer and accessed via OLE\COM. What I am looking for is a way of accessing this via .NET, hopefully through the Accord framework.
I understand the additional resolutions might be properties of a transform filter however I am new to DirectShow and COM interfaces in .NET so I am looking for some pointers.
I use to wrap DirectShow code for .NET.
For sure with DirectShow it is possible to get, set ,and retrieve a/v source capabilities.
Have You tried using IAMStreamConfig video interface to set output format on certain capture and compression filters?
I use this code to get resolutions and set it on different sources.
where m_pVCap: source filter
hr = m_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,
m_pVCap, IID_IAMVideoCompression,(void **)&m_pVC);
if (hr != S_OK)
hr = m_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
m_pVCap,IID_IAMVideoCompression,(void **)&m_pVC);
// !!! What if this interface isn't supported?
// we use this interface to set the frame rate and get the capture size
hr = m_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,
m_pVCap, IID_IAMStreamConfig, (void **)&m_pVSC);
if (hr != NOERROR)
{
hr = m_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
m_pVCap, IID_IAMStreamConfig,(void **)&m_pVSC);
if (hr != NOERROR)
{
LogDXError(hr, false, FILELINE);
}
}
To get current source format
hr = m_pVSC->GetFormat(&pmt);
// DV capture does not use a VIDEOINFOHEADER
if (hr == NOERROR)
{
if (pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
pvi->AvgTimePerFrame = (LONGLONG)(10000000 / m_FrameRate);
hr = m_pVSC->SetFormat(pmt);
if (hr != NOERROR)
(NotifyNewError) (FILELINE, "", LOG_ALL, ERR_GRAVE, false,
"Cannot set frame rate for capture");
hr = m_pVSC->GetFormat(&pmt);
pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
pvi->bmiHeader.biWidth = g_SizeOutput.cx;
pvi->bmiHeader.biHeight = g_SizeOutput.cy;
pvi->bmiHeader.biSizeImage = DIBSIZE(pvi->bmiHeader);
hr = m_pVSC->SetFormat(pmt);
if (hr != NOERROR)
{
char ErrTxt[MAX_ERROR_TEXT_LEN];
AMGetErrorText(hr, ErrTxt,MAX_ERROR_TEXT_LEN);
wsprintf(szError, "Error %x: %s\nCannot set frame rate (%d)for
prev", hr, ErrTxt,m_FrameRate);
(NotifyNewError)(FILELINE, "", LOG_ALL, ERR_GRAVE, false, szError);
}
DeleteMediaType(pmt);
}
To get sources capabilities you can use:
IAMStreamConfig::GetNumberOfCapabilities and then IAMStreamConfig::GetStreamCaps

SharpDx direct3d11 how to start rendering

I want to use directx on C# and I am using SharpDX wrapper. I got a book called Direct3D rendering cookbook and I got the basic code from it. I want to create a 3d world view. For that I will need a camera view and a grid that helps to recognize world position just like in Autodesk Maya but I do not know how to do that. My mind is rally mixed what should I do to start ?
Here I have code that is ready to render something I think:
using System;
using SharpDX.Windows;
using SharpDX.DXGI;
using SharpDX.Direct3D11;
using Device = SharpDX.Direct3D11.Device;
using Device1 = SharpDX.Direct3D11.Device1;
namespace CurrencyConverter
{
static class Program
{[STAThread]
static void Main()
{
// Enable object tracking
SharpDX.Configuration.EnableObjectTracking = true;
SharpDX.Animation.Timer timer = new SharpDX.Animation.Timer();
#region Direct3D Initialization
// Create the window to render to
Form1 form = new Form1();
form.Text = "D3DRendering - EmptyProject";
form.Width = 640;
form.Height = 480;
// Declare the device and swapChain vars
Device device;
SwapChain swapChain;
// Create the device and swapchain
// First create a regular D3D11 device
using (var device11 = new Device(
SharpDX.Direct3D.DriverType.Hardware,
DeviceCreationFlags.None,
new[] {
SharpDX.Direct3D.FeatureLevel.Level_11_1,
SharpDX.Direct3D.FeatureLevel.Level_11_0,
}))
{
// Query device for the Device1 interface (ID3D11Device1)
device = device11.QueryInterfaceOrNull<Device1>();
if (device == null)
throw new NotSupportedException(
"SharpDX.Direct3D11.Device1 is not supported");
}// Rather than create a new DXGI Factory we reuse the
// one that has been used internally to create the device
using (var dxgi = device.QueryInterface<SharpDX.DXGI.Device2>())
using (var adapter = dxgi.Adapter)
using (var factory = adapter.GetParent<Factory2>())
{
var desc1 = new SwapChainDescription1()
{
Width = form.ClientSize.Width,
Height = form.ClientSize.Height,
Format = Format.R8G8B8A8_UNorm,
Stereo = false,
SampleDescription = new SampleDescription(1, 0),
Usage = Usage.BackBuffer | Usage.RenderTargetOutput,
BufferCount = 1,
Scaling = Scaling.Stretch,
SwapEffect = SwapEffect.Discard,
};
swapChain = new SwapChain1(factory,
device,
form.Handle,
ref desc1,
new SwapChainFullScreenDescription()
{
RefreshRate = new Rational(60, 1),
Scaling = DisplayModeScaling.Centered,
Windowed = true
},
// Restrict output to specific Output (monitor)
adapter.Outputs[0]);
}
// Create references for backBuffer and renderTargetView
var backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain,
0);
var renderTargetView = new RenderTargetView(device,
backBuffer);
#endregion
// Setup object debug names
device.DebugName = "The Device";
swapChain.DebugName = "The SwapChain";
backBuffer.DebugName = "The Backbuffer";
renderTargetView.DebugName = "The RenderTargetView";
#region Render loop
// Create and run the render loop
RenderLoop.Run(form, () =>
{
// Clear the render target with...
var lerpColor = SharpDX.Color.Lerp(SharpDX.Color.White,
SharpDX.Color.DarkBlue,
(float)((timer.Time) / 10.0 % 1.0));
device.ImmediateContext.ClearRenderTargetView(
renderTargetView,
lerpColor);
// Execute rendering commands here...
//...
//I DO NOT HAVE ANY IDEA
//...
// Present the frame
swapChain.Present(0, PresentFlags.RestrictToOutput);
});
#endregion
#region Direct3D Cleanup
// Release the device and any other resources created
renderTargetView.Dispose();
backBuffer.Dispose();
device.Dispose();
swapChain.Dispose();
#endregion
}
}
}
Generally speaking, with Direct3D you need a substantial amount of code before to have anything happening on the screen.
In the SharpDX repository you have the MiniCube sample which contains enough to really get you started, as it has all the elements required to draw a 3d scene.
I recommend to particularily look for:
Depth buffer creation (DepthStencilView)
fx file, as you need shaders to have anything on the screen (no more fixed funtion)
How the Vertex Buffer is created, you need to split geometry in triangles (in common cases, there are other possibilities).
Don't forget the SetViewport (it's really common to have it omitted)
The calls referring to Input Assembler are assigning the geometry to be drawn
Constant buffer creation : this is to pass matrices and changing data (like diffuse)
Also make sure to have DeviceCreationFlags.None with the Device.CreateWithSwapChain call, and in visual studio debug options, use "Enable Native Code Debugging". This will give you errors and warnings if something is not set properly, plus a meaningful reason in case any for the resource creation fails (instead of "Invalid Args", which is quite pointless).
As another recommendation, all the Direct3D11 resource creation parameters are incredibly error prone and tedious (many options are non compatible between each other), so it quite important to wrap those into some easier to use helper functions (and make a small amount of unit tests to validate them once and for all). The old Toolkit has quite some of those examples
SharpDX wrapper is relatively close to the c++ counterpart, so anything in the c++ documentation applies to it too.

How to use function D3DXSaveSurfaceToFile() in C#

I use directx 9 to build model.
I want to save it to bmp file. I found the function D3DXSaveSurfaceToFile()
But I do not know how to use it in C#.
How can I use it?
Unfortunately, there is no such function in c#.
Try the following code instead:
try
{
// initialize D3D device
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
Device myDevice = new
Device(0,DeviceType.Hardware,this,CreateFlags.SoftwareVertexProcessing,presentParams);
// create a surface the size of screen,
// format had to be A8R8G8B8, as the GetFrontBufferData returns
// only memory pool types allowed are Pool.Scratch or Pool.System memory
Surface mySurface =
myDevice.CreateOffscreenPlainSurface(SystemInformation.PrimaryMonitorSize.Width,SystemInformation.PrimaryMonitorSize.Height,Format.A8R8G8B8,Pool.SystemMemory);
//Get the front buffer.
myDevice.GetFrontBufferData(0,mySurface);
//saves surface to file
SurfaceLoader.Save("surface.bmp",ImageFileFormat.Bmp,mySurface);
}
catch
{
//whatever
}

DirectShow GUID missing for DVR device

I am using DShowNET in a C# project and I have been trying multiple cards. The Card I am trying to access is a GV-800_4A, which is a a capture card normally used by GeoVision CCTV software.
The problem is it is recognized in the device manager as a 'DVR Device' with a different guid than the normal video input devices I have been using and I do NOT know the DShowNET guid, but believe it may relate to this guid.
My question is 'How do I convert the 'Device class guid' seen in devices properties the windows device manager to the Guid used in DirectShow? or are these even equatable?'
GUIDs in device manager
GeoVision GV-800A {4d36e96c-e325-11ce-bfc1-0123456789ab}
AVerMedia {4d36e96c-e325-11ce-bfc1-08002be10318}
Dazzle USB {4d36e96c-e325-11ce-bfc1-08002be10318}
GUID in DShowLib
VideoInputDevice (0x860BB310, 0x5D01,
0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9,
0x11, 0xCE, 0x86)
EDIT
Basically the end goal is to be able to connect this as a capture filter to a graph to save FilterCatergory.VideoInputDevice, but now this device (GeoVision) does NOT appear on the list of available capture devices, but it IS a capture device just the drivers recognize it as a 'DVR Device'
I use the CLSID by passing it into the DShowNET function for returning an ArrayList of available devices of that type :
DsDev.GetDevicesOfCat(FilterCategory.VideoInputDevice, out m_capDevices)
I need to know the CLSID_[** DVR Device **] or where to get that. I thought it could be derived from the 'Device class guid', but I am getting told this is not possible.
You could use something like this:
const string CAPTURE = "•GeoVision GV-800A";
s_CaptureDevices = BuildDeviceList(FilterCategory.AMKSCapture, CAPTURE);
private static List<DsDevice> BuildDeviceList(Guid category, string name)
{
var list = new List<DsDevice>();
DsDevice[] devices = DsDevice.GetDevicesOfCat(category);
for (int i = 0; i < devices.Length; i++)
{
if (!string.IsNullOrEmpty(devices[i].Name) && devices[i].Name.Equals(name))
{
list.Add(devices[i]);
}
}
return list;
}
Another option would be use GraphEditPlus and add the capture filter to a graph. You can then find out the GUID to create the filter object directly using code like this:
var captureFilter = (IBaseFilter) Activator.CreateInstance(Type.GetTypeFromCLSID(new DsGuid("...guid...")));

Categories