GDCL Home About GDCL DirectShow WinNt & WDM

Visual Basic Questions

Some DirectShow interfaces were enabled for access from OLE Automation clients such as Visual Basic. Unfortunately, some of them require C/C++ code to access them. By special request I have created a C++ wrapper DLL that allows access to a number of problem interfaces. You can download this DLL here. You can also download capstill.dll -- a frame-grabber dll -- together with a sample VB project, here.

How can I use the File Writer filter from Visual Basic?
How can I select a reference clock from Visual Basic?
How can I show a filter's property pages from Visual Basic?
How can I set the interleaving properties of the AVI Mux filter from Visual Basic?
How can I select the left or right audio channels when playing MPEG-1 
How can I select the video capture format and capture parameters with the "Stream Format" dialog?
How can I specify a capture format from a VB program?
How can I grab still frames from a movie using Visual Basic?
Why does the DirectX Builder sample not work properly?
How can I list all the video capture filters (or any another category of filters)?
How can I remove filters from a graph in VB

How can I use the File Writer filter from Visual Basic?

The File Writer filter needs you to pass in the pathname to use as an output filename, using the IFileSinkFilter interface. Unfortunately, you can't do this from VB without a small C++ wrapper. FSFWrap.zip (11Kb) contains a small DLL that provides this wrapper.

Download FSFWrap and register the dll with regsvr32 fsfwrap.dll, and then add a reference to the FSFWrap type library. You can then create a SinkInfo object, assign an IFilterInfo object to its filter property and then set the output filename.

As an example, open the vb\builder example from the DirectShow SDK, and change AddRegFilter to the following:

Private Sub cmdAddRegFilter_Click()
Dim filter As IRegFilterInfo
For Each filter In g_objRegFilters
' listRegFilters
If filter.Name = listRegFilters.Text Then
Dim f As IFilterInfo
filter.filter f
If f.IsFileSource Then
CommonDialog1.ShowOpen
' handle user cancel
f.FileName = CommonDialog1.FileName
End If
Dim sink As SinkInfo
Set sink = New SinkInfo
sink.filter = f
If sink.IsFileSink Then
CommonDialog1.ShowSave
sink.FileName = CommonDialog1.FileName
End If
Exit For
End If
Next filter
' Set frmRegFilters = g_objMC.RegFilterCollection
RefreshFilters
End Sub
You can then insert Bouncing Ball, AVI Mux and File Writer, connect the ball to the mux and the mux to the file writer and create an output AVI file.

How can I select a reference clock from Visual Basic?
If you need to select a specific filter as the reference clock, the simplest way to do this is to make a filter graph containing only the filter you want as clock, then call Run and Stop on this before making the rest of the graph.
This works because the graph manager selects a clock when the graph goes active, but only if a clock has not already been selected.

How can I  show a filter's property pages from Visual Basic?
This can only be done using C/C++ code I think, so I have extended FSFWrap.dll to support it. Download FSFWrap (11Kb) and register the dll with regsvr32 fsfwrap.dll, and then add a reference to the FSFWrap type library. Then you can show a filter's property page with code such as the following. Add this to a command button in the DirectShow vb\builder example to show the property pages of the selected filter. Note that some property pages are shown on the pin, not the filter - for these, you will need to use the PinPropInfo class (see below).
Private Sub FilterProps_Click()
Dim filterex As SinkInfo
Set filterex = New SinkInfo
filterex.filter = g_objSelFilter
filterex.ShowPropPage hWnd
End Sub

How can I set the interleaving properties of the AVI Mux filter from Visual Basic?
This can only be done using C/C++ code I think, so I have extended FSFWrap.dll to support it. Download FSFWrap and use code like the following:
Dim mux As AVIMuxInfo
Set mux = New AVIMuxInfo
On Error Resume Next
mux.filter = objFI
txtMode.Caption = mux.Mode
txtInterleave.Caption = mux.Interleave txtPreroll.Caption = mux.Preroll

How can I select the left or right audio channels when playing MPEG-1
If you have the dshow 6 or dx8 sdk, you will find that mpegtype.h includes a definition of an interface IMpegAudioDecoder. The DualMode property can be set to AM_MPEG_AUDIO_DUAL_MERGE (0) or ...LEFT (1) or ...(RIGHT).
Alas the interface is not vb compatible. I've added a class to fsfwrap to provide VB access to the DualMode and Stereo methods. I tested it by adding the following code to the dshow builder project, to listFilters_Click in frmMain:
Dim aprops As MpegAudioProps
Set aprops = New MpegAudioProps
aprops.filter = objFI
txtDualMode.Caption = aprops.DualMode

HHow can I select the video capture format with the "Stream Format" dialog?

The Stream Format property page allows you to select the pixel format and image size (using the IAMStreamConfig interface). It is exposed by the preview and capture pins of WDM video capture filters. You need to show the property pages of the pin, and not the filter. I have extended fsfwrap.dll to support this, using the following code to show the property page of a pin. This is also used in the CapStill sample below.

Dim pinOut As IPinInfo
<...code to set pinOut...>
Dim ppropOut As PinPropInfo
Set ppropOut = New PinPropInfo
ppropOut.Pin = pinOut
ppropOut.ShowPropPage 0

How can I specify a capture format and capture parameters from a VB program?

Some VB programs need to specify a capture format such as RGB24 320x240, rather than simply showing the Stream Format dialog for the user to select a type. The media type is a complex structure which is hard to deal with directly in VB. I have provided a simple but effective method for using them: a tool that saves the current media type to a file and restores from a file.

The capstill sample demonstrates this in use. The application shows the Stream Format dialog (see here) and then saves to a file the format that the user selects. Next time the app is run, before showing the Stream Format dialog, the app restores and selects the saved media type.

The fsfwrap dll contains a StreamConfig object. The program creates one of these and assigns an IPinInfo to its Pin property, and then uses the SaveCurrentFormat and Restore methods. This only works with pins that support the IAMStreamConfig interface (typically on video capture filters).

The latest version of FSFWrap.dll also allows you to control the crossbar settings (to select between eg Composite and S-Video input), and the video standard (PAL, NTSC). This is demonstrated in the capstill sample.


How can I grab still frames from a movie using Visual Basic?

DirectX 8 includes a SampleGrabber filter. This is a pass-through filter that allows an application to view frames as they pass through the graph. However, it is hard to use from Visual Basic. I've written a small dll that, when called from VB, saves the next frame to a .BMP file. To use it, you need to add the SampleGrabber filter to the graph, then construct a VBGrabber object and set the sample grabber to the VBGrabber.FilterInfo property.

I've also written a small test app in VB that demonstrates how to use capstill.dll. To use the demo app, you need to select a source filter (Bouncing Ball works) and then press Preview to build and run a preview graph. Press Snap to save the next frame to a bitmap file. The sample also uses the Stream Format property page on the pin, if present, to allow you to select the image size (the format of the file will always be RGB24). Clearly for a real app you will need a more sophisticated way of selecting the source filter and output pin.

New! you can now also capture still frames to memory. It returns an IBitmapAccess COM object containing the bitmap, from which you can get an HBITMAP (a DIB Section) and also a pointer directly to the bits, and there is an updated sample that demonstrates this, including a dreadful hack which creates a byte array from the bits

Download capstill.dll and the vbcap demo app here.


Why does the DirectX Builder sample not work properly?

The DirectShow VB sample Builder does not work with live graphs because it tries to set the file position, and if this fails, it silently does not start the graph. Change the code in the builder’s mnu_FilterGraphRun_Click method to the following

Case GraphState.StateStopped
If Not m_objMediaControl Is Nothing Then
'obtain the current position
Set objPosition = m_objMediaControl
If Not objPosition Is Nothing Then
'reset the position to zero
On Local Error Resume Next
objPosition.CurrentPosition = 0
On Local Error GoTo ErrLine
End If
'set state to running
m_objMediaControl.Run
'reset module-level variable
m_GraphState = StateRunning
End If

Also the "Connect One Pin" implementation in the v8.1 sdk is broken. This code (in frmSelectPins, method listFilters_Click) is intended to show all the unconnected pins that you could connect to. To do this, it uses the pin.ConnectedTo method and then shows the pin if there is an error. Unfortunately a statement "On Local Error Goto Errline" was added which means that when a useful pin is found, the error handler jumps out of the loop. You need to add On Error Resume Next instead:

For Each pin In pfilter.Pins
On Error Resume Next
Set pinOther = pin.ConnectedTo
If Err.Number <> 0 Then
If pin.Direction <> OtherDir Then
'append the pin's name to the listbox
listPins.AddItem pin.Name
End If
End If
Next


How can I list all the video capture filters (or any another category of filters)?

FSFWrap now contains a FilterCatEnumerator object that allows VB programs to enumerate filters by category. Examples of categories include Video Capture sources, Audio input and output devices and audio or video compressors. A modified version of the DirectShow 8.1 SDK sample builder is included in the zip, which shows how to use this feature. The category is specified by a GUID in text form. The most common categories are given in the builder example.


How can I remove filters from a graph in VB

The VBGraphHelper (in FSFWrap) has a method RemoveChain(pFilter). This removes from the graph the specified filter, and all filters downstream of it, and returns the output pin that was connected to pFilter.

Dim fg As VBGraphHelper
Set g_FilGraph = New FilgraphManager
Set fg = New VBGraphHelper
fg.Graph = g_FilGraph
Sub Rebuild (pF as IFilterInfo)
Dim pOut As IPinInfo
Set pOut = fg.RemoveChain(pF)

Then you can render pOut using a different set of transforms or whatever. At this point, you might want to add your own transform by class id:

Dim fMyTransform as IFilterInfo
Set fMyTransform = fg.FilterByClsid("{34aa6f94-7778-4cb8-99FB-F2799AAEC64B}", "My Transform")

Then use pOut.Connect to connect the output pin to the new transform.