1 /*****************************************************************************
2 * crossbar.c : DirectShow access module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
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>
37 /*****************************************************************************
38 * DeleteCrossbarRoutes
39 *****************************************************************************/
40 void DeleteCrossbarRoutes( access_sys_t *p_sys )
42 /* Remove crossbar filters from graph */
43 for( int i = 0; i < p_sys->i_crossbar_route_depth; i++ )
45 p_sys->crossbar_routes[i].pXbar->Release();
47 p_sys->i_crossbar_route_depth = 0;
50 /*****************************************************************************
51 * RouteCrossbars (Does not AddRef the returned *Pin)
52 *****************************************************************************/
53 static HRESULT GetCrossbarIPinAtIndex( IAMCrossbar *pXbar, LONG PinIndex,
54 BOOL IsInputPin, IPin ** ppPin )
56 LONG cntInPins, cntOutPins;
58 IBaseFilter *pFilter = NULL;
62 if( !pXbar || !ppPin ) return E_POINTER;
66 if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) ) return E_FAIL;
68 LONG TrueIndex = IsInputPin ? PinIndex : PinIndex + cntInPins;
70 if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
72 if( SUCCEEDED(pFilter->EnumPins(&pins)) )
75 while( pins->Next(1, &pP, &n) == S_OK )
90 return *ppPin ? S_OK : E_FAIL;
93 /*****************************************************************************
94 * GetCrossbarIndexFromIPin: Find corresponding index of an IPin on a crossbar
95 *****************************************************************************/
96 static HRESULT GetCrossbarIndexFromIPin( IAMCrossbar * pXbar, LONG * PinIndex,
97 BOOL IsInputPin, IPin * pPin )
99 LONG cntInPins, cntOutPins;
101 IBaseFilter *pFilter = NULL;
106 if(!pXbar || !PinIndex || !pPin )
109 if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) )
112 if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
114 if( SUCCEEDED(pFilter->EnumPins(&pins)) )
118 while( pins->Next(1, &pP, &n) == S_OK )
123 *PinIndex = IsInputPin ? i : i - cntInPins;
134 return fOK ? S_OK : E_FAIL;
137 /*****************************************************************************
139 *****************************************************************************/
140 HRESULT FindCrossbarRoutes( vlc_object_t *p_this, access_sys_t *p_sys,
141 IPin *p_input_pin, LONG physicalType, int depth )
143 HRESULT result = S_FALSE;
146 if( FAILED(p_input_pin->ConnectedTo(&p_output_pin)) ) return S_FALSE;
148 // It is connected, so now find out if the filter supports IAMCrossbar
150 if( FAILED(p_output_pin->QueryPinInfo(&pinInfo)) ||
151 PINDIR_OUTPUT != pinInfo.dir )
153 p_output_pin->Release ();
157 IAMCrossbar *pXbar=0;
158 if( FAILED(pinInfo.pFilter->QueryInterface(IID_IAMCrossbar,
161 pinInfo.pFilter->Release();
162 p_output_pin->Release ();
166 LONG inputPinCount, outputPinCount;
167 if( FAILED(pXbar->get_PinCounts(&outputPinCount, &inputPinCount)) )
170 pinInfo.pFilter->Release();
171 p_output_pin->Release ();
175 LONG inputPinIndexRelated, outputPinIndexRelated;
176 LONG inputPinPhysicalType, outputPinPhysicalType;
177 LONG inputPinIndex, outputPinIndex;
178 if( FAILED(GetCrossbarIndexFromIPin( pXbar, &outputPinIndex,
179 FALSE, p_output_pin )) ||
180 FAILED(pXbar->get_CrossbarPinInfo( FALSE, outputPinIndex,
181 &outputPinIndexRelated,
182 &outputPinPhysicalType )) )
185 pinInfo.pFilter->Release();
186 p_output_pin->Release ();
191 // for all input pins
193 for( inputPinIndex = 0; S_OK != result && inputPinIndex < inputPinCount;
196 if( FAILED(pXbar->get_CrossbarPinInfo( TRUE, inputPinIndex,
197 &inputPinIndexRelated, &inputPinPhysicalType )) ) continue;
199 // Is the pin a video pin?
200 if( inputPinPhysicalType != physicalType ) continue;
203 if( FAILED(pXbar->CanRoute(outputPinIndex, inputPinIndex)) ) continue;
206 if( FAILED(GetCrossbarIPinAtIndex( pXbar, inputPinIndex,
207 TRUE, &pPin)) ) continue;
209 result = FindCrossbarRoutes( p_this, p_sys, pPin,
210 physicalType, depth+1 );
212 if( S_OK == result || (S_FALSE == result &&
213 physicalType == inputPinPhysicalType &&
214 (p_sys->i_crossbar_route_depth = depth+1) < MAX_CROSSBAR_DEPTH) )
219 // remember crossbar route
220 p_sys->crossbar_routes[depth].pXbar = pXbar;
221 p_sys->crossbar_routes[depth].VideoInputIndex = inputPinIndex;
222 p_sys->crossbar_routes[depth].VideoOutputIndex = outputPinIndex;
223 p_sys->crossbar_routes[depth].AudioInputIndex = inputPinIndexRelated;
224 p_sys->crossbar_routes[depth].AudioOutputIndex = outputPinIndexRelated;
226 msg_Dbg( p_this, "Crossbar at depth %d, Found Route For "
227 "ouput %ld (type %ld) to input %ld (type %ld)", depth,
228 outputPinIndex, outputPinPhysicalType, inputPinIndex,
229 inputPinPhysicalType );
236 pinInfo.pFilter->Release();
237 p_output_pin->Release ();