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