1 /*****************************************************************************
2 * crossbar.c : DirectShow access module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 the VideoLAN team
7 * Author: Damien Fouilleul <damien dot fouilleul at laposte dot net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc/input.h>
36 /* Work-around a bug in w32api-2.5 */
37 # define QACONTAINERFLAGS QACONTAINERFLAGS_ANOTHERSOMETHINGELSE
42 /*****************************************************************************
43 * DeleteCrossbarRoutes
44 *****************************************************************************/
45 void DeleteCrossbarRoutes( access_sys_t *p_sys )
47 /* Remove crossbar filters from graph */
48 for( int i = 0; i < p_sys->i_crossbar_route_depth; i++ )
50 p_sys->crossbar_routes[i].pXbar->Release();
52 p_sys->i_crossbar_route_depth = 0;
55 /*****************************************************************************
56 * RouteCrossbars (Does not AddRef the returned *Pin)
57 *****************************************************************************/
58 static HRESULT GetCrossbarIPinAtIndex( IAMCrossbar *pXbar, LONG PinIndex,
59 BOOL IsInputPin, IPin ** ppPin )
61 LONG cntInPins, cntOutPins;
63 IBaseFilter *pFilter = NULL;
67 if( !pXbar || !ppPin ) return E_POINTER;
71 if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) ) return E_FAIL;
73 LONG TrueIndex = IsInputPin ? PinIndex : PinIndex + cntInPins;
75 if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
77 if( SUCCEEDED(pFilter->EnumPins(&pins)) )
80 while( pins->Next(1, &pP, &n) == S_OK )
95 return *ppPin ? S_OK : E_FAIL;
98 /*****************************************************************************
99 * GetCrossbarIndexFromIPin: Find corresponding index of an IPin on a crossbar
100 *****************************************************************************/
101 static HRESULT GetCrossbarIndexFromIPin( IAMCrossbar * pXbar, LONG * PinIndex,
102 BOOL IsInputPin, IPin * pPin )
104 LONG cntInPins, cntOutPins;
106 IBaseFilter *pFilter = NULL;
111 if(!pXbar || !PinIndex || !pPin )
114 if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) )
117 if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
119 if( SUCCEEDED(pFilter->EnumPins(&pins)) )
123 while( pins->Next(1, &pP, &n) == S_OK )
128 *PinIndex = IsInputPin ? i : i - cntInPins;
139 return fOK ? S_OK : E_FAIL;
142 /*****************************************************************************
144 *****************************************************************************/
145 HRESULT FindCrossbarRoutes( vlc_object_t *p_this, access_sys_t *p_sys,
146 IPin *p_input_pin, LONG physicalType, int depth )
148 HRESULT result = S_FALSE;
151 if( FAILED(p_input_pin->ConnectedTo(&p_output_pin)) ) return S_FALSE;
153 // It is connected, so now find out if the filter supports IAMCrossbar
155 if( FAILED(p_output_pin->QueryPinInfo(&pinInfo)) ||
156 PINDIR_OUTPUT != pinInfo.dir )
158 p_output_pin->Release ();
162 IAMCrossbar *pXbar=0;
163 if( FAILED(pinInfo.pFilter->QueryInterface(IID_IAMCrossbar,
166 pinInfo.pFilter->Release();
167 p_output_pin->Release ();
171 LONG inputPinCount, outputPinCount;
172 if( FAILED(pXbar->get_PinCounts(&outputPinCount, &inputPinCount)) )
175 pinInfo.pFilter->Release();
176 p_output_pin->Release ();
180 LONG inputPinIndexRelated, outputPinIndexRelated;
181 LONG inputPinPhysicalType = 0, outputPinPhysicalType;
182 LONG inputPinIndex = 0, outputPinIndex;
183 if( FAILED(GetCrossbarIndexFromIPin( pXbar, &outputPinIndex,
184 FALSE, p_output_pin )) ||
185 FAILED(pXbar->get_CrossbarPinInfo( FALSE, outputPinIndex,
186 &outputPinIndexRelated,
187 &outputPinPhysicalType )) )
190 pinInfo.pFilter->Release();
191 p_output_pin->Release ();
196 ** if physical type is 0, then use default/existing route to physical connector
198 if( physicalType == 0 )
200 /* use following as default connector type if we fail to find an existing route */
201 physicalType = PhysConn_Video_Tuner;
202 if( SUCCEEDED(pXbar->get_IsRoutedTo(outputPinIndex, &inputPinIndex)) )
205 if( SUCCEEDED( pXbar->get_CrossbarPinInfo( TRUE, inputPinIndex,
206 &inputPinIndexRelated, &inputPinPhysicalType )) )
208 // remember connector type
209 physicalType = inputPinPhysicalType;
211 msg_Dbg( p_this, "Found Existing Route For ouput %ld (type %ld) to input %ld (type %ld)",
212 outputPinIndex, outputPinPhysicalType, inputPinIndex,
213 inputPinPhysicalType );
215 // fall through to for loop, note 'inputPinIndex' is set to the pin we are looking for
216 // hence, loop iteration should not wind back
221 // reset to first pin for complete loop iteration
227 // for all input pins
229 for( /* inputPinIndex has been set */ ; (S_OK != result) && (inputPinIndex < inputPinCount); ++inputPinIndex )
231 if( FAILED(pXbar->get_CrossbarPinInfo( TRUE, inputPinIndex,
232 &inputPinIndexRelated, &inputPinPhysicalType )) ) continue;
234 // Is this pin matching required connector physical type?
235 if( inputPinPhysicalType != physicalType ) continue;
238 if( FAILED(pXbar->CanRoute(outputPinIndex, inputPinIndex)) ) continue;
242 if( FAILED(GetCrossbarIPinAtIndex( pXbar, inputPinIndex,
243 TRUE, &pPin)) ) continue;
245 result = FindCrossbarRoutes( p_this, p_sys, pPin,
246 physicalType, depth+1 );
248 if( S_OK == result || (S_FALSE == result &&
249 physicalType == inputPinPhysicalType &&
250 (p_sys->i_crossbar_route_depth = depth+1) < MAX_CROSSBAR_DEPTH) )
252 // hold on crossbar, will be released when graph is destroyed
255 // remember crossbar route
256 p_sys->crossbar_routes[depth].pXbar = pXbar;
257 p_sys->crossbar_routes[depth].VideoInputIndex = inputPinIndex;
258 p_sys->crossbar_routes[depth].VideoOutputIndex = outputPinIndex;
259 p_sys->crossbar_routes[depth].AudioInputIndex = inputPinIndexRelated;
260 p_sys->crossbar_routes[depth].AudioOutputIndex = outputPinIndexRelated;
262 msg_Dbg( p_this, "Crossbar at depth %d, Found Route For "
263 "ouput %ld (type %ld) to input %ld (type %ld)", depth,
264 outputPinIndex, outputPinPhysicalType, inputPinIndex,
265 inputPinPhysicalType );
272 pinInfo.pFilter->Release();
273 p_output_pin->Release ();