crossbar.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:9k
源码类别:

多媒体

开发平台:

MultiPlatform

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