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