]> git.sesse.net Git - vlc/blob - modules/access/dshow/crossbar.cpp
Removes trailing spaces. Removes tabs.
[vlc] / modules / access / dshow / crossbar.cpp
1 /*****************************************************************************
2  * crossbar.c : DirectShow access module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 the VideoLAN team
5  * $Id$
6  *
7  * Author: Damien Fouilleul <damien dot fouilleul at laposte dot net>
8  *
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.
13  *
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.
18  *
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #include <vlc/vlc.h>
29 #include <vlc_vout.h>
30
31 #ifndef _MSC_VER
32     /* Work-around a bug in w32api-2.5 */
33 #   define QACONTAINERFLAGS QACONTAINERFLAGS_ANOTHERSOMETHINGELSE
34 #endif
35
36 #include "common.h"
37
38 /*****************************************************************************
39  * DeleteCrossbarRoutes
40  *****************************************************************************/
41 void DeleteCrossbarRoutes( access_sys_t *p_sys )
42 {
43     /* Remove crossbar filters from graph */
44     for( int i = 0; i < p_sys->i_crossbar_route_depth; i++ )
45     {
46         p_sys->crossbar_routes[i].pXbar->Release();
47     }
48     p_sys->i_crossbar_route_depth = 0;
49 }
50
51 /*****************************************************************************
52  * RouteCrossbars (Does not AddRef the returned *Pin)
53  *****************************************************************************/
54 static HRESULT GetCrossbarIPinAtIndex( IAMCrossbar *pXbar, LONG PinIndex,
55                                        BOOL IsInputPin, IPin ** ppPin )
56 {
57     LONG         cntInPins, cntOutPins;
58     IPin        *pP = 0;
59     IBaseFilter *pFilter = NULL;
60     IEnumPins   *pins=0;
61     ULONG        n;
62
63     if( !pXbar || !ppPin ) return E_POINTER;
64
65     *ppPin = 0;
66
67     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) ) return E_FAIL;
68
69     LONG TrueIndex = IsInputPin ? PinIndex : PinIndex + cntInPins;
70
71     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
72     {
73         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
74         {
75             LONG i = 0;
76             while( pins->Next(1, &pP, &n) == S_OK )
77             {
78                 pP->Release();
79                 if( i == TrueIndex )
80                 {
81                     *ppPin = pP;
82                     break;
83                 }
84                 i++;
85             }
86             pins->Release();
87         }
88         pFilter->Release();
89     }
90
91     return *ppPin ? S_OK : E_FAIL;
92 }
93
94 /*****************************************************************************
95  * GetCrossbarIndexFromIPin: Find corresponding index of an IPin on a crossbar
96  *****************************************************************************/
97 static HRESULT GetCrossbarIndexFromIPin( IAMCrossbar * pXbar, LONG * PinIndex,
98                                          BOOL IsInputPin, IPin * pPin )
99 {
100     LONG         cntInPins, cntOutPins;
101     IPin        *pP = 0;
102     IBaseFilter *pFilter = NULL;
103     IEnumPins   *pins = 0;
104     ULONG        n;
105     BOOL         fOK = FALSE;
106
107     if(!pXbar || !PinIndex || !pPin )
108         return E_POINTER;
109
110     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) )
111         return E_FAIL;
112
113     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
114     {
115         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
116         {
117             LONG i=0;
118
119             while( pins->Next(1, &pP, &n) == S_OK )
120             {
121                 pP->Release();
122                 if( pPin == pP )
123                 {
124                     *PinIndex = IsInputPin ? i : i - cntInPins;
125                     fOK = TRUE;
126                     break;
127                 }
128                 i++;
129             }
130             pins->Release();
131         }
132         pFilter->Release();
133     }
134
135     return fOK ? S_OK : E_FAIL;
136 }
137
138 /*****************************************************************************
139  * FindCrossbarRoutes
140  *****************************************************************************/
141 HRESULT FindCrossbarRoutes( vlc_object_t *p_this, access_sys_t *p_sys,
142                             IPin *p_input_pin, LONG physicalType, int depth )
143 {
144     HRESULT result = S_FALSE;
145
146     IPin *p_output_pin;
147     if( FAILED(p_input_pin->ConnectedTo(&p_output_pin)) ) return S_FALSE;
148
149     // It is connected, so now find out if the filter supports IAMCrossbar
150     PIN_INFO pinInfo;
151     if( FAILED(p_output_pin->QueryPinInfo(&pinInfo)) ||
152         PINDIR_OUTPUT != pinInfo.dir )
153     {
154         p_output_pin->Release ();
155         return S_FALSE;
156     }
157
158     IAMCrossbar *pXbar=0;
159     if( FAILED(pinInfo.pFilter->QueryInterface(IID_IAMCrossbar,
160                                                (void **)&pXbar)) )
161     {
162         pinInfo.pFilter->Release();
163         p_output_pin->Release ();
164         return S_FALSE;
165     }
166
167     LONG inputPinCount, outputPinCount;
168     if( FAILED(pXbar->get_PinCounts(&outputPinCount, &inputPinCount)) )
169     {
170         pXbar->Release();
171         pinInfo.pFilter->Release();
172         p_output_pin->Release ();
173         return S_FALSE;
174     }
175
176     LONG inputPinIndexRelated, outputPinIndexRelated;
177     LONG inputPinPhysicalType = 0, outputPinPhysicalType;
178     LONG inputPinIndex = 0, outputPinIndex;
179     if( FAILED(GetCrossbarIndexFromIPin( pXbar, &outputPinIndex,
180                                          FALSE, p_output_pin )) ||
181         FAILED(pXbar->get_CrossbarPinInfo( FALSE, outputPinIndex,
182                                            &outputPinIndexRelated,
183                                            &outputPinPhysicalType )) )
184     {
185         pXbar->Release();
186         pinInfo.pFilter->Release();
187         p_output_pin->Release ();
188         return S_FALSE;
189     }
190
191     /*
192     ** if physical type is 0, then use default/existing route to physical connector
193     */
194     if( physicalType == 0 )
195     {
196         /* use following as default connector type if we fail to find an existing route */
197         physicalType = PhysConn_Video_Tuner;
198         if( SUCCEEDED(pXbar->get_IsRoutedTo(outputPinIndex, &inputPinIndex)) )
199         {
200
201             if( SUCCEEDED( pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
202                            &inputPinIndexRelated, &inputPinPhysicalType )) )
203             {
204                 // remember connector type
205                 physicalType = inputPinPhysicalType;
206  
207                 msg_Dbg( p_this, "found existing route for output %ld (type %ld) to input %ld (type %ld)",
208                          outputPinIndex, outputPinPhysicalType, inputPinIndex,
209                          inputPinPhysicalType );
210  
211                 // fall through to for loop, note 'inputPinIndex' is set to the pin we are looking for
212                 // hence, loop iteration should not wind back
213
214             }
215         }
216         else {
217             // reset to first pin for complete loop iteration
218             inputPinIndex = 0;
219         }
220     }
221  
222     //
223     // for all input pins
224     //
225     for( /* inputPinIndex has been set */ ; (S_OK != result) && (inputPinIndex < inputPinCount); ++inputPinIndex )
226     {
227         if( FAILED(pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
228             &inputPinIndexRelated, &inputPinPhysicalType )) ) continue;
229
230         // Is this pin matching required connector physical type?
231         if( inputPinPhysicalType != physicalType ) continue;
232
233         // Can we route it?
234         if( FAILED(pXbar->CanRoute(outputPinIndex, inputPinIndex)) ) continue;
235  
236  
237         IPin *pPin;
238         if( FAILED(GetCrossbarIPinAtIndex( pXbar, inputPinIndex,
239                                            TRUE, &pPin)) ) continue;
240
241         result = FindCrossbarRoutes( p_this, p_sys, pPin,
242                                      physicalType, depth+1 );
243
244         if( S_OK == result || (S_FALSE == result &&
245             physicalType == inputPinPhysicalType &&
246             (p_sys->i_crossbar_route_depth = depth+1) < MAX_CROSSBAR_DEPTH) )
247         {
248             // hold on crossbar, will be released when graph is destroyed
249             pXbar->AddRef();
250
251             // remember crossbar route
252             p_sys->crossbar_routes[depth].pXbar = pXbar;
253             p_sys->crossbar_routes[depth].VideoInputIndex = inputPinIndex;
254             p_sys->crossbar_routes[depth].VideoOutputIndex = outputPinIndex;
255             p_sys->crossbar_routes[depth].AudioInputIndex = inputPinIndexRelated;
256             p_sys->crossbar_routes[depth].AudioOutputIndex = outputPinIndexRelated;
257
258             msg_Dbg( p_this, "crossbar at depth %d, found route for "
259                      "output %ld (type %ld) to input %ld (type %ld)", depth,
260                      outputPinIndex, outputPinPhysicalType, inputPinIndex,
261                      inputPinPhysicalType );
262
263             result = S_OK;
264         }
265     }
266
267     pXbar->Release();
268     pinInfo.pFilter->Release();
269     p_output_pin->Release ();
270
271     return result;
272 }