Balluff - BVS CA-MLC / BVS CA-IGC Technical Documentation
DirectShow Interface
Note
DirectShow can only be used in combination with the Microsoft Windows operating system.
Since Windows Vista, Movie Maker does not support capturing from a device registered for DirectShow anymore.

This is the documentation of the Balluff DirectShow_acquire interface. A Balluff specific property interface based on the IKsPropertySet has been added. All other features are related to standard DirectShow programming.

Supported Interfaces

  • IAMCameraControl
  • IAMDroppedFrames
  • IAMStreamConfig
  • IAMVideoProcAmp
  • ISpecifyPropertyPages
  • IKsPropertySet (for further information please refer to the Microsoft DirectX 9.0 Programmer's Reference). Supported property set GUID's:
    • AMPROPERTY_PIN_CATEGORY
    • DIRECT_SHOW_ACQUIRE_PROPERTYSET

C++ Example Code Using the IKsPropertySet Interface

This section provides a small C++ code snippet showing how the DirectShow interface could be used e.g. to query all properties from a device or how to set the value of a certain property

#include <DSImpactAcquire/Include/DirectShowAcquire.h>
//------------------------------------------------------------------------------
// macro for writing the properties, feel free to replace the macros in the code
//------------------------------------------------------------------------------
#define _WRITE_STRING_PROPERTY(iksprop,prop,str)\
if( prop != 0 )\
{\
prop->value.s = str;\
hr = iksprop->Set(DIRECT_SHOW_ACQUIRE_PROPERTYSET, MVPropIDWrite, NULL, 0, prop, sizeof(MVProperty));\
}
//------------------------------------------------------------------------------
#define _WRITE_FLOAT_PROPERTY(iksprop,prop,fval)\
if( prop != 0 )\
{\
prop->value.f = fval;\
hr = iksprop->Set(DIRECT_SHOW_ACQUIRE_PROPERTYSET, MVPropIDWrite, NULL, 0, prop, sizeof(MVProperty));\
}
//------------------------------------------------------------------------------
#define _DELETE_POINTER_ARRAY(prop_array,cnt)\
for( unsigned long pr = 0; pr < cnt; pr++ )\
{\
if( prop_array[pr].stringArraySize > 0 )\
delete [] prop_array[pr].stringArray;\
}
//------------------------------------------------------------------------------
// scanning the property list props for a property with name property_name
MVProperty* GetProperty( MVProperty* props, unsigned int property_count, char* property_name )
//------------------------------------------------------------------------------
{
for( unsigned int pr = 0; pr < property_count && props != 0; pr++ )
{
// please feel free to replace standard c string handling to Standard C++ Library strings
if( strcmp( props[pr].propertyName, property_name ) == 0 )
{
return &props[pr];
}
}
return 0;
}
//------------------------------------------------------------------------------
// asking the ds-interface for the property list
unsigned long ScanAllProperties( IAMStreamConfig* pvsc, MVProperty* props, unsigned int property_count )
//------------------------------------------------------------------------------
{
IKsPropertySet* ksProp;
unsigned long propCnt = 0;
// try to get the ikspropertyset pointer
HRESULT hr = pvsc->QueryInterface( IID_IKsPropertySet, ( void** )&ksProp );
if( SUCCEEDED( hr ) )
{
DWORD cbReturned;
ZeroMemory( props, property_count * sizeof( MVProperty ) );
// asking for the property interface. If one could be found then fill the propertylist props
hr = ksProp->Get( DIRECT_SHOW_ACQUIRE_PROPERTYSET, MVPropIDReadProperties, NULL, 0,
props, property_count * sizeof( MVProperty ), &cbReturned );
//if successful returned then our list shows something like this
//props[0x0] {propertyName="IOSubSystem/DigitalInputThreshold" value={s= "2V" }...
//props[0x1] {propertyName="IOSubSystem/DigitalInputs" value={s= "Off" }...
//props[0x2] {propertyName="IOSubSystem/DigitalOutputs" value={s= "Off" }...
//props[0x3] {propertyName="IOSubSystem/HardwareRealTimeController/HRTCtrl_0/Filename" value={s= "default.rtp" }...
//props[0x4] {propertyName="IOSubSystem/HardwareRealTimeController/HRTCtrl_0/Mode" value={s= "Stop" } ...
//props[0x5] {propertyName="IOSubSystem/HardwareRealTimeController/HRTCtrl_0/ProgramSize" value={i=0x5 }...
//...
//props[0x40] {propertyName="ImagingSubsystem/Setting/Base/Camera/AutoExposeControl" value={s= "Off" } ...
//props[0x41] {propertyName="ImagingSubsystem/Setting/Base/Camera/AutoGainControl" value={s= "Off" } ...
//props[0x42] {propertyName="ImagingSubsystem/Setting/Base/Camera/BinningMode" value={s= "Off" } ...
//props[0x43] {propertyName="ImagingSubsystem/Setting/Base/Camera/ExposeMode" value={s= "Standard" } ...
//props[0x44] {propertyName="ImagingSubsystem/Setting/Base/Camera/Expose_us" value={i=0xea60 } ...
//props[0x45] {propertyName="ImagingSubsystem/Setting/Base/Camera/FlashMode" value={s= "Off" } ...
//props[0x46] {propertyName="ImagingSubsystem/Setting/Base/Camera/FrameDelay_us" value={i=0x0 } ...
//props[0x47] {propertyName="ImagingSubsystem/Setting/Base/Camera/Gain_dB" value={ f=0.0 } ...
propCnt = cbReturned / sizeof( MVProperty );
for( DWORD pr = 0; pr < propCnt; pr++ )
{
//asking for the actual values of all properties
hr = ksProp->Get( DIRECT_SHOW_ACQUIRE_PROPERTYSET, MVPropIDRead, NULL, 0, &props[pr], sizeof( props[pr] ), &cbReturned );
//if stringArraySize is greater than 0 this property is from type stringarray.
if( props[pr].stringArraySize > 0 )
{
//allocate some buffer for the stringArray
props[pr].stringArray = new const char* [props[pr].stringArraySize];
//fill the allocate stringArray with references to the pointers from the internal properties,
//do not change or free these pointers
hr = ksProp->Get( DIRECT_SHOW_ACQUIRE_PROPERTYSET, MVPropIDReadStringArray, NULL, 0, &props[pr], sizeof( props[pr] ), &cbReturned );
}
}
ksProp->Release();
}
return propCnt;
}
//------------------------------------------------------------------------------
unsigned long functionXY( ..., bool bBayerOFF, double gain )
//------------------------------------------------------------------------------
{
// ...
IKsPropertySet* ks_prop;
hr = gcap.pVSC->QueryInterface( IID_IKsPropertySet, ( void** )&ks_prop );
if( SUCCEEDED( hr ) )
{
const int max_prop = 500;
MVProperty props[max_prop];
unsigned int propCnt = ScanAllProperties( gcap.pVSC, props, max_prop );
// if successful we get a list something like this otherwise propCnt = 0
//...
//props[0x40] {propertyName="ImagingSubsystem/Setting/Base/Camera/AutoExposeControl" value={s= "Off" } ...
//props[0x41] {propertyName="ImagingSubsystem/Setting/Base/Camera/AutoGainControl" value={s= "Off" } ...
//props[0x42] {propertyName="ImagingSubsystem/Setting/Base/Camera/BinningMode" value={s= "Off" } ...
//props[0x43] {propertyName="ImagingSubsystem/Setting/Base/Camera/ExposeMode" value={s= "Standard" } ...
//props[0x44] {propertyName="ImagingSubsystem/Setting/Base/Camera/Expose_us" value={i=0xea60 } ...
//props[0x45] {propertyName="ImagingSubsystem/Setting/Base/Camera/FlashMode" value={s= "Off" } ...
//props[0x46] {propertyName="ImagingSubsystem/Setting/Base/Camera/FrameDelay_us" value={i=0x0 } ...
//props[0x47] {propertyName="ImagingSubsystem/Setting/Base/Camera/Gain_dB" value={ f=0.0 } ...
//...
// it is strongly recommended to work only with the propertyNames and not with the index from the list.
// The driver for our cameras and grabber will always return same propertyNames.
MVProperty* gain_prop = GetProperty( props, propCnt, "ImagingSubsystem/Setting/Base/Camera/Gain_dB" );
_WRITE_FLOAT_PROPERTY( ks_prop, gain_prop, gain );
MVProperty* bayer_prop = GetProperty( props, propCnt, "ImagingSubsystem/Setting/Base/ImageProcessing/ColorProcessing" );
// The property ColorProcessing is from type stringArray. Please have a look to the stringArray for the different strings.
_WRITE_STRING_PROPERTY( ks_prop, bayer_prop, bBayerOFF ? "Raw" : "Auto" );
// delete the stringarray
_DELETE_POINTER_ARRAY( props, propCnt );
ks_prop->Release();
}
// ...
}

Logging

The DirectShow_acquire logging procedure is equal to the logging of the Balluff products which uses Impact Acquire. The log output itself is based on XML.

If you want more information about the logging please have a look at the Logging chapter of the respective Impact Acquire API manual or read on how to configure the log-output using DeviceConfigure in the "Impact Acquire GUI Applications" manual.

Setting up Devices For DirectShow Usage

In order to be able to access a device through the Impact Acquire driver stack from an application through DirectShow a registration procedure is needed. This can either be done using DeviceConfigure or by a command line tool that is part of the Windows operating system.

Note
Please be sure to register the device for DirectShow with a matching version of DeviceConfigure. I.e. if you have installed the 32-bit version of the VLC Media Player, Virtual Dub, etc., you have to register devices with the 32-bit version of DeviceConfigure ("C:/Program Files/Balluff/Impact Acquire/bin", the 64-bit version resides in "C:/Program Files/Balluff/Impact Acquire/bin/x64")!

Registering Devices

Using DeviceConfigure

To register all devices currently recognized by the Impact Acquire driver stack for access with DirectShow the following registration procedure is needed:

  1. DeviceConfigure needs to be started (with elevated rights).
    If no device has been registered the application will more or less (depending on the installed devices) look like this.

    DeviceConfigure - After Start


  2. To register every installed device for DirectShow access click on the menu item "DirectShow""Register All Devices".

    DeviceConfigure - Register All Devices


  3. After a successful registration the column "Registered For DirectShow" will display "yes" for every device and the devices will be registered with a default DirectShow friendly name which is displayed in the "DirectShow Friendly Name" column.

    DeviceConfigure - All Devices Registered For DirectShow Access


Using regsvr32

To register all devices currently recognized by the Impact Acquire driver stack with auto-assigned names, the Windows tool "regsvr32" can be used from an elevated command shell.

The following command line options are available and can be passed during the silent registration:

EXAMPLES:

Register ALL devices that are recognized by Impact Acquire (this will only register devices which have drivers installed) without any user interaction:

regsvr32 <path>\DirectShow_acquire.ax /s

Unregister ALL devices that have been registered before without any user interaction:

regsvr32 <path>\DirectShow_acquire.ax /u /s

Renaming Devices

To modify the DirectShow friendly name of a device:

  1. DeviceConfigure needs to be started (with elevated rights).
  2. right-click on the device to rename and select "Set DirectShow Friendly Name":

    DeviceConfigure - Set DirectShow Friendly Name


  3. Then, a dialog will appear. Please enter the new name and confirm it with "OK".

    DeviceConfigure - Dialog For New Name


  4. Afterwards the column "DirectShow friendly name" will display the newly assigned friendly name.

    DeviceConfigure - Renamed Device


Note
Please do not select the same friendly name for two different devices. In theory this is possible, however the DeviceConfigure GUI will not allow this to avoid confusion.

DirectShow-based Applications

Applications like the VLC Media Player or VirtualDub can be used to capture images via DirectShow. VirtualDub is a good choice if you want full control over the camera, while VLC Media Player decides some of the DirectShow configuration under the hood, which may lead to undesirable results. (See Wrong Colors in the VLC Media Player)

Note
Some Windows tools like Teams and Outlook also try to get hold of available DirectShow video capture devices. Keep this in mind if you experience strange behavior of any DirectShow device.