PDA

View Full Version : Direct access to Firewire Driver Interface?



Learner99
January 23, 2009, 23:11:42
I'm trying to incorporate an Imaging Source Firewire camera (DFK 21BF04-Z2) in my existing C# CLR /C++ COM application. I'm getting video, but it's black and white. I'd like to set the parameters on the driver directly to switch it to color output. But, because I need to use my legacy video renderer, I believe that I cannot use the control itself. I was hoping to access the COM object directly when I insert the DShow video capture filter into the graph. I have done this before using C# interop, where I wrap the COM interface, but I can do this directly in C++/COM as well. I'd really appreciate any help.

Thanks

Stefan Geissler
January 26, 2009, 09:13:53
Hi,

You are right, you must set the video format using some more or less complicated DirectShow code.

Here is some C++ code, that sets a "BY8" video format. The same should be useable for setting "UYVY" too:


HRESULT findMediaType( IAMStreamConfig* pConfig, GUID subtypeToFind, AM_MEDIA_TYPE** pMediaType )
{
HRESULT hr;

if( pConfig != 0 ) // does have a IAMStreamConfig interface
{
// this is needed, cause we want the interface to expose all media types it supports
// and not only the last one set.
pConfig->SetFormat( 0 );

AM_MEDIA_TYPE* pMT = 0;
int caps, confstr_size;

hr = pConfig->GetNumberOfCapabilities( &caps, &confstr_size );
if( FAILED( hr ) ) return hr;

std::auto_ptr<BYTE> pByte( new BYTE[confstr_size] );

for( int i = 0; i < caps; ++i )
{
hr = pConfig->GetStreamCaps( i, &pMT, pByte.get() );

if( pMT->subtype == subtypeToFind )
{
*pMediaType = pMT;
return S_OK;
}

::DeleteMediaType( pMT );
pMT = 0; // just to be on the safe side
}
}

return E_FAIL;
}

// Set the "BY8" video format.
GUID subTypeToSet = MEDIASUBTYPE_BY8;
HRESULT hr;
IPin* pOutPin = 0;
if( SUCCEEDED( findPin( filtertoquery, pOutPin, PINDIR_OUTPUT, 0 ) ) && pOutPin != 0 )
{
IAMStreamConfig* pStrmConfig = 0;
pOutPin->QueryInterface( &pStrmConfig );

AM_MEDIA_TYPE* pmt = 0;

hr = findMediaType( pStrmConfig, subTypeToSet, &pmt );
if( SUCCEEDED( hr ) )
{
pStrmConfig->SetFormat( pmt );
::DeleteMediaType( pmt );
}
}


"filtertoquery" is the video capture filter.

Please understand, that I can not provide DirectShow programming support.

May be http://www.codeproject.com is a helpful source for your problem.

Learner99
January 26, 2009, 16:05:07
Thanks - I had forgotten that your driver supports IAMStreamConfig!! Your example was excellent.

To get this to work in DirectShowNet/C#, I had to do the following:

Insert a definition for BY8 into the Uuids.cs file:
/// <summary> MEDIASUBTYPE_BY8 </summary>
public static readonly Guid BY8 = new Guid(0x20385942, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);

Use the following code, stripped down from the example given:


IPin capture_pin = DsFindPin.ByDirection((IBaseFilter)sourceFilter, PinDirection.Output, 0);

if (capture_pin != null)
{
IAMStreamConfig stream_config = (IAMStreamConfig)capture_pin;
if (stream_config != null)
{
int num_caps = 0;
int size = 0;
int hr1 = stream_config.GetNumberOfCapabilities(out num_caps, out size);
DsError.ThrowExceptionForHR(hr1);

IntPtr scc = Marshal.AllocCoTaskMem(num_caps * size);
for (int i = 0; i < num_caps; i++)
{
AMMediaType mt;

hr1 = stream_config.GetStreamCaps(i, out mt, scc);

if (mt.subType == MediaSubType.BY8)
{
hr1 = stream_config.SetFormat(mt);
DsError.ThrowExceptionForHR(hr1);
}
}
Marshal.FreeCoTaskMem(scc);
}
Marshal.ReleaseComObject(capture_pin);
}