Directshow Filter Selection

Windows specific forum
normen
New User
New User
Posts: 7
Joined: Mon Feb 28, 2005 7:00 am

Directshow Filter Selection

Post by normen »

Hi,
I am a newbie, so please excuse any unqualified remarks.
I am trying to write a little movie player and want it to play ANY media file imaginable. After installing Real Alternative, I was hoping that I could play rm files, but there seems to be a bit of a problem. The sound is OK, yet the picture stays black. GraphEdit shows that by default the AVI decoder filter is being used, even with rm files. Removing this filter in GraphEdit solves the problem, the picture is OK.
My question is, Does PB offer a way to "disable" a certain filter? Or would there be a way to build a custom graph for a media file?
Any help will be appreciated.
The manual said 'Windows XP or better' ... so I used Linux.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Re: Directshow Filter Selection

Post by traumatic »

Here's some code (from the german forums) using a dedicated filtergraph, maybe that helps:

http://forums.purebasic.com/german/viewtopic.php?t=1054

Code: Select all

;
; http://forums.purebasic.com/german/viewtopic.php?t=1054
;
#CLSCTX_INPROC_SERVER        = $1
#VFW_E_NOT_FOUND             = $80040216
#MAX_FILTER_NAME             = 128

Structure FilterInfo
 achName.b[#MAX_FILTER_NAME]
 lpFilterGraph.IFilterGraph
EndStructure

Enumeration
 #PINDIR_INPUT
 #PINDIR_OUTPUT
EndEnumeration

CoInitialize_(0)
Debug CoCreateInstance_(?CLSID_FilterGraph, #NULL,#CLSCTX_INPROC_SERVER,?IID_IGraphBuilder,@lpGB.IGraphBuilder)
Debug lpGB\QueryInterface(?IID_IMediaControl,@lpMC.IMediaControl)

Debug CoCreateInstance_(?CLSID_Source_Filter, #NULL, #CLSCTX_INPROC_SERVER,?IID_IBaseFilter,@lpSource_Filter.IBaseFilter)
Debug CoCreateInstance_(?CLSID_Avi_Decompressor, #NULL, #CLSCTX_INPROC_SERVER,?IID_IBaseFilter,@lpAvi_Decompressor.IBaseFilter)
Debug CoCreateInstance_(?CLSID_VideoRenderer, #NULL, #CLSCTX_INPROC_SERVER,?IID_IBaseFilter,@lpVRender.IBaseFilter)

file.s = "I:\Clock.avi"

; SOURCE Filter

Dim wavFile.w(Len(file))
MultiByteToWideChar_(#CP_ACP, 0, file, -1, wavFile(), Len(file))
Debug lpGB\AddSourceFilter(@wavFile(), @wavFile(), @lpSource_Filter)
lpSource_Filter\EnumPins(@lpNUM.IEnumPins)
While lpNUM\Next(1,@lpPin.IPin,0) = #S_OK
 lpPin\QueryDirection(@a)
 If a = #PINDIR_OUTPUT
  lpSource_FilterPinOut = lpPin
 EndIf
Wend
Debug lpSource_FilterPinOut

;AVI_Decompressor

Debug lpGB\AddFilter(lpAvi_Decompressor, @"AVI_Decompressor")
lpAvi_Decompressor\EnumPins(@lpNUM.IEnumPins)
While lpNUM\Next(1,@lpPin.IPin,0) = #S_OK
 lpPin\QueryDirection(@a)
 If a = #PINDIR_OUTPUT
  lpAvi_DecompressorPinOut = lpPin
 EndIf
 If a = #PINDIR_INPUT
   lpAvi_DecompressorPinIn  = lpPin
 EndIf
Wend
Debug lpAvi_DecompressorPinIn
Debug lpAvi_DecompressorPinOut

; Renderer

Debug lpGB\AddFilter(lpVRender, @"Video_Renderer")
lpVRender\EnumPins(@lpNUM.IEnumPins)
While lpNUM\Next(1,@lpPin.Ipin,0) = #S_OK
 lpPin\QueryDirection(@a)
If a =  #PINDIR_INPUT
 lpVRenderPinIn = lpPin
EndIf
Wend

Debug lpVRenderPinIn

; Pins verbinden

Debug lpGB\Connect(lpSource_FilterPinOut,lpAvi_DecompressorPinIn)
Debug lpGB\Connect(lpAvi_DecompressorPinOut,lpVRenderPinIn)

; Verwendete Filter anzeigen

Debug lpGB\EnumFilters(@lpEnum.IEnumFilters)
While lpEnum\Next(1,@lpFilter.IBaseFilter,0) = #S_OK
 lpFilter\QueryFilterinfo(@info.FilterInfo)
 Debug PeekS(@info\achName)
Wend

; Wiedergabe starten

lpMC\Run()

; Freigabe

lpFilter\Release()
lpEnum\Release()
lpPin\Release()
lpNUM\Release()
lpVRender\Release()
lpAvi_Decompressor\Release()
lpSource_Filter\Release()
lpMC\Release()
lpGB\Release()

CoUninitialize_()

DataSection
 CLSID_FilterGraph:
 Data.l $E436EBB3
 Data.w $524F,$11CE
 Data.b $9F,$53,$00,$20,$AF,$0B,$A7,$70
 IID_IGraphBuilder:
 Data.l $56A868A9
 Data.W $0AD4,$11CE
 Data.b $B0,$3A,$00,$20,$AF,$0B,$A7,$70
 CLSID_Source_Filter:
 Data.l $D3588AB0
 Data.w $0781,$11CE
 Data.b $B0,$3A,$00,$20,$AF,$0B,$A7,$70
 CLSID_Avi_Splitter:
 Data.l $1B544C20
 Data.w $FD0B,$11CE
 Data.b $8C,$63,$00,$AA,$00,$44,$B5,$1E
 IID_IBaseFilter:
 Data.l $56A86895
 Data.w $0AD4,$11CE
 Data.b $B0,$3A,$00,$20,$AF,$0B,$A7,$70
 CLSID_Avi_Decompressor:
 Data.l $CF49D4E0
 Data.w $1115,$11CE
 Data.b $B0,$3A,$00,$20,$AF,$0B,$A7,$70
 CLSID_VideoRenderer:
 Data.l $70E102B0
 Data.w $5556,$11CE
 Data.b $97,$C0,$00,$AA,$00,$55,$59,$5A
 IID_IMediaControl:
 Data.l $56A868B1
 Data.w $0AD4,$11CE
 Data.b $B0,$3A,$00,$20,$AF,$0B,$A7,$70
EndDataSection 
Last edited by traumatic on Tue Mar 15, 2005 9:33 am, edited 1 time in total.
Good programmers don't comment their code. It was hard to write, should be hard to read.
normen
New User
New User
Posts: 7
Joined: Mon Feb 28, 2005 7:00 am

Post by normen »

This looks exactly like what I was hoping to find. I'll try and let you guys know.
Thanks for the help.
The manual said 'Windows XP or better' ... so I used Linux.
normen
New User
New User
Posts: 7
Joined: Mon Feb 28, 2005 7:00 am

Post by normen »

Hey, it works. Thanks for your help!
The manual said 'Windows XP or better' ... so I used Linux.
normen
New User
New User
Posts: 7
Joined: Mon Feb 28, 2005 7:00 am

Post by normen »

I have another question. For debug purposes, is there a simple way in PureBasic to either save the used gragh to a .grf file to be opened later in GraphEdit or add the running graph to the Running Objects Table in order to connect GraphEdit to the graph.
I did find c++ functions on the Microsoft website for this, but neither am I overly familiar with c++ nor do I know PureBasic well enough to convert these funtions from c++.
The manual said 'Windows XP or better' ... so I used Linux.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

normen wrote:[...] or add the running graph to the Running Objects Table in order to connect GraphEdit to the graph.
Here's the MS-code to add a graph to the table
(see http://forums.purebasic.com/german/view ... 6301#26301 for further explanations in german)

Code: Select all

#ROTFLAGS_REGISTRATIONKEEPSALIVE = $01

Structure WCHAR
  c.w[#MAX_PATH]
EndStructure

Procedure.l AddToRot(*pUnkGraph.IUnknown, *pdwRegister.l)
  *pMoniker.IMoniker
  *pROT.IRunningObjectTable

  If GetRunningObjectTable_(0, @*pROT) <> 0
    ProcedureReturn #E_FAIL
  EndIf

  sz.s = "FilterGraph "+LCase(RSet(Hex(*pUnkGraph), 8, "0"))+" pid "+LCase(RSet(Hex(GetCurrentProcessId_()), 8, "0"))
  MultiByteToWideChar_(#CP_ACP, 0, sz, -1, @wsz.WCHAR, Len(sz))

  MultiByteToWideChar_(#CP_ACP, 0, "!", -1, @wsz2.WCHAR, 1)
  hr.l = CreateItemMoniker_(wsz2, wsz, @*pMoniker)

  If hr = 0
    hr = *pROT\Register(#ROTFLAGS_REGISTRATIONKEEPSALIVE, *pUnkGraph, *pMoniker, *pdwRegister)
    *pMoniker\Release()
  EndIf

  *pROT\Release()
  ProcedureReturn hr
EndProcedure 
Don't forget to Revoke() and Release() the RunningObjectTable once done.

BTW: Does anyone have a good (a really good ;)) idea to simplify the widechar mess?
Good programmers don't comment their code. It was hard to write, should be hard to read.
normen
New User
New User
Posts: 7
Joined: Mon Feb 28, 2005 7:00 am

Post by normen »

The manual said 'Windows XP or better' ... so I used Linux.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

You're welcome :)
Good programmers don't comment their code. It was hard to write, should be hard to read.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

traumatic wrote:BTW: Does anyone have a good (a really good ;)) idea to simplify the widechar mess?
Maybe something like this:

Code: Select all

Procedure.l L(string.s)
  *out = AllocateMemory(Len(string)*2 * #SIZEOF_WORD)
  MultiByteToWideChar_(#CP_ACP, 0, string, -1, *out, Len(string))  
  ProcedureReturn *out  
EndProcedure

Code: Select all

.
.
.

Code: Select all

  wsz.l = L("FilterGraph "+LCase(RSet(Hex(*pUnkGraph), 8, "0"))+" pid "+LCase(RSet(Hex(GetCurrentProcessId_()), 8, "0")))
  hr.l  = CreateItemMoniker_(L("!"), wsz, @*pMoniker)
Good programmers don't comment their code. It was hard to write, should be hard to read.
Post Reply