Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

crossbar.cpp

00001 /*****************************************************************************
00002  * crossbar.c : DirectShow access module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2002 the VideoLAN team
00005  * $Id: crossbar.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Author: Damien Fouilleul <damien dot fouilleul at laposte dot net>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 
00031 #include <vlc/vlc.h>
00032 #include <vlc/input.h>
00033 #include <vlc/vout.h>
00034 
00035 #ifndef _MSC_VER
00036     /* Work-around a bug in w32api-2.5 */
00037 #   define QACONTAINERFLAGS QACONTAINERFLAGS_ANOTHERSOMETHINGELSE
00038 #endif
00039 
00040 #include "common.h"
00041 
00042 /*****************************************************************************
00043  * DeleteCrossbarRoutes
00044  *****************************************************************************/
00045 void DeleteCrossbarRoutes( access_sys_t *p_sys )
00046 {
00047     /* Remove crossbar filters from graph */
00048     for( int i = 0; i < p_sys->i_crossbar_route_depth; i++ )
00049     {
00050         p_sys->crossbar_routes[i].pXbar->Release();
00051     }
00052     p_sys->i_crossbar_route_depth = 0;
00053 }
00054 
00055 /*****************************************************************************
00056  * RouteCrossbars (Does not AddRef the returned *Pin)
00057  *****************************************************************************/
00058 static HRESULT GetCrossbarIPinAtIndex( IAMCrossbar *pXbar, LONG PinIndex,
00059                                        BOOL IsInputPin, IPin ** ppPin )
00060 {
00061     LONG         cntInPins, cntOutPins;
00062     IPin        *pP = 0;
00063     IBaseFilter *pFilter = NULL;
00064     IEnumPins   *pins=0;
00065     ULONG        n;
00066 
00067     if( !pXbar || !ppPin ) return E_POINTER;
00068 
00069     *ppPin = 0;
00070 
00071     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) ) return E_FAIL;
00072 
00073     LONG TrueIndex = IsInputPin ? PinIndex : PinIndex + cntInPins;
00074 
00075     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
00076     {
00077         if( SUCCEEDED(pFilter->EnumPins(&pins)) ) 
00078         {
00079             LONG i = 0;
00080             while( pins->Next(1, &pP, &n) == S_OK ) 
00081             {
00082                 pP->Release();
00083                 if( i == TrueIndex ) 
00084                 {
00085                     *ppPin = pP;
00086                     break;
00087                 }
00088                 i++;
00089             }
00090             pins->Release();
00091         }
00092         pFilter->Release();
00093     }
00094 
00095     return *ppPin ? S_OK : E_FAIL; 
00096 }
00097 
00098 /*****************************************************************************
00099  * GetCrossbarIndexFromIPin: Find corresponding index of an IPin on a crossbar
00100  *****************************************************************************/
00101 static HRESULT GetCrossbarIndexFromIPin( IAMCrossbar * pXbar, LONG * PinIndex,
00102                                          BOOL IsInputPin, IPin * pPin )
00103 {
00104     LONG         cntInPins, cntOutPins;
00105     IPin        *pP = 0;
00106     IBaseFilter *pFilter = NULL;
00107     IEnumPins   *pins = 0;
00108     ULONG        n;
00109     BOOL         fOK = FALSE;
00110 
00111     if(!pXbar || !PinIndex || !pPin )
00112         return E_POINTER;
00113 
00114     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) )
00115         return E_FAIL;
00116 
00117     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
00118     {
00119         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
00120         {
00121             LONG i=0;
00122 
00123             while( pins->Next(1, &pP, &n) == S_OK )
00124             {
00125                 pP->Release();
00126                 if( pPin == pP )
00127                 {
00128                     *PinIndex = IsInputPin ? i : i - cntInPins;
00129                     fOK = TRUE;
00130                     break;
00131                 }
00132                 i++;
00133             }
00134             pins->Release();
00135         }
00136         pFilter->Release();
00137     }
00138 
00139     return fOK ? S_OK : E_FAIL; 
00140 }
00141 
00142 /*****************************************************************************
00143  * FindCrossbarRoutes
00144  *****************************************************************************/
00145 HRESULT FindCrossbarRoutes( vlc_object_t *p_this, access_sys_t *p_sys,
00146                             IPin *p_input_pin, LONG physicalType, int depth )
00147 {
00148     HRESULT result = S_FALSE;
00149 
00150     IPin *p_output_pin;
00151     if( FAILED(p_input_pin->ConnectedTo(&p_output_pin)) ) return S_FALSE;
00152 
00153     // It is connected, so now find out if the filter supports IAMCrossbar
00154     PIN_INFO pinInfo;
00155     if( FAILED(p_output_pin->QueryPinInfo(&pinInfo)) ||
00156         PINDIR_OUTPUT != pinInfo.dir )
00157     {
00158         p_output_pin->Release ();
00159         return S_FALSE;
00160     }
00161 
00162     IAMCrossbar *pXbar=0;
00163     if( FAILED(pinInfo.pFilter->QueryInterface(IID_IAMCrossbar,
00164                                                (void **)&pXbar)) )
00165     {
00166         pinInfo.pFilter->Release();
00167         p_output_pin->Release ();
00168         return S_FALSE;
00169     }
00170 
00171     LONG inputPinCount, outputPinCount;
00172     if( FAILED(pXbar->get_PinCounts(&outputPinCount, &inputPinCount)) )
00173     {
00174         pXbar->Release();
00175         pinInfo.pFilter->Release();
00176         p_output_pin->Release ();
00177         return S_FALSE;
00178     }
00179 
00180     LONG inputPinIndexRelated, outputPinIndexRelated;
00181     LONG inputPinPhysicalType = 0, outputPinPhysicalType;
00182     LONG inputPinIndex = 0, outputPinIndex;
00183     if( FAILED(GetCrossbarIndexFromIPin( pXbar, &outputPinIndex,
00184                                          FALSE, p_output_pin )) ||
00185         FAILED(pXbar->get_CrossbarPinInfo( FALSE, outputPinIndex,
00186                                            &outputPinIndexRelated,
00187                                            &outputPinPhysicalType )) )
00188     {
00189         pXbar->Release();
00190         pinInfo.pFilter->Release();
00191         p_output_pin->Release ();
00192         return S_FALSE;
00193     }
00194 
00195     /*
00196     ** if physical type is 0, then use default/existing route to physical connector
00197     */
00198     if( physicalType == 0 )
00199     {
00200         /* use following as default connector type if we fail to find an existing route */
00201         physicalType = PhysConn_Video_Tuner;
00202         if( SUCCEEDED(pXbar->get_IsRoutedTo(outputPinIndex, &inputPinIndex)) )
00203         {
00204 
00205             if( SUCCEEDED( pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
00206                            &inputPinIndexRelated, &inputPinPhysicalType )) )
00207             {
00208                 // remember connector type
00209                 physicalType = inputPinPhysicalType;
00210                 
00211                 msg_Dbg( p_this, "Found Existing Route For ouput %ld (type %ld) to input %ld (type %ld)",
00212                          outputPinIndex, outputPinPhysicalType, inputPinIndex,
00213                          inputPinPhysicalType );
00214                          
00215                 // fall through to for loop, note 'inputPinIndex' is set to the pin we are looking for
00216                 // hence, loop iteration should not wind back
00217 
00218             }
00219         }
00220         else {
00221             // reset to first pin for complete loop iteration
00222             inputPinIndex = 0;
00223         }
00224     }                  
00225          
00226     //
00227     // for all input pins
00228     //
00229     for( /* inputPinIndex has been set */ ; (S_OK != result) && (inputPinIndex < inputPinCount); ++inputPinIndex )
00230     {
00231         if( FAILED(pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
00232             &inputPinIndexRelated, &inputPinPhysicalType )) ) continue;
00233 
00234         // Is this pin matching required connector physical type?
00235         if( inputPinPhysicalType != physicalType ) continue;
00236 
00237         // Can we route it?
00238         if( FAILED(pXbar->CanRoute(outputPinIndex, inputPinIndex)) ) continue;
00239             
00240    
00241         IPin *pPin;
00242         if( FAILED(GetCrossbarIPinAtIndex( pXbar, inputPinIndex,
00243                                            TRUE, &pPin)) ) continue;
00244 
00245         result = FindCrossbarRoutes( p_this, p_sys, pPin,
00246                                      physicalType, depth+1 );
00247 
00248         if( S_OK == result || (S_FALSE == result &&
00249             physicalType == inputPinPhysicalType &&
00250             (p_sys->i_crossbar_route_depth = depth+1) < MAX_CROSSBAR_DEPTH) )
00251         {
00252             // hold on crossbar, will be released when graph is destroyed
00253             pXbar->AddRef();
00254 
00255             // remember crossbar route
00256             p_sys->crossbar_routes[depth].pXbar = pXbar;
00257             p_sys->crossbar_routes[depth].VideoInputIndex = inputPinIndex;
00258             p_sys->crossbar_routes[depth].VideoOutputIndex = outputPinIndex;
00259             p_sys->crossbar_routes[depth].AudioInputIndex = inputPinIndexRelated;
00260             p_sys->crossbar_routes[depth].AudioOutputIndex = outputPinIndexRelated;
00261 
00262             msg_Dbg( p_this, "Crossbar at depth %d, Found Route For "
00263                      "ouput %ld (type %ld) to input %ld (type %ld)", depth,
00264                      outputPinIndex, outputPinPhysicalType, inputPinIndex,
00265                      inputPinPhysicalType );
00266 
00267             result = S_OK;
00268         }
00269     }
00270 
00271     pXbar->Release();
00272     pinInfo.pFilter->Release();
00273     p_output_pin->Release ();
00274 
00275     return result;
00276 }

Generated on Tue Dec 20 10:14:24 2005 for vlc-0.8.4a by  doxygen 1.4.2