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