crossbar.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:11k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * crossbar.c : DirectShow access module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 the VideoLAN team
  5.  * $Id: c34b2902859926db148d870f363c4ff6a6771c30 $
  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.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_vout.h>
  31. #ifndef _MSC_VER
  32.     /* Work-around a bug in w32api-2.5 */
  33. #   define QACONTAINERFLAGS QACONTAINERFLAGS_ANOTHERSOMETHINGELSE
  34. #endif
  35. #include "common.h"
  36. // Helper function to associate a crossbar pin name with the type.
  37. static const char * GetPhysicalPinName(long lType)
  38. {
  39.     switch (lType)
  40.     {
  41.     case PhysConn_Video_Tuner:            return "Video Tuner";
  42.     case PhysConn_Video_Composite:        return "Video Composite";
  43.     case PhysConn_Video_SVideo:           return "S-Video";
  44.     case PhysConn_Video_RGB:              return "Video RGB";
  45.     case PhysConn_Video_YRYBY:            return "Video YRYBY";
  46.     case PhysConn_Video_SerialDigital:    return "Video Serial Digital";
  47.     case PhysConn_Video_ParallelDigital:  return "Video Parallel Digital";
  48.     case PhysConn_Video_SCSI:             return "Video SCSI";
  49.     case PhysConn_Video_AUX:              return "Video AUX";
  50.     case PhysConn_Video_1394:             return "Video 1394";
  51.     case PhysConn_Video_USB:              return "Video USB";
  52.     case PhysConn_Video_VideoDecoder:     return "Video Decoder";
  53.     case PhysConn_Video_VideoEncoder:     return "Video Encoder";
  54.     case PhysConn_Audio_Tuner:            return "Audio Tuner";
  55.     case PhysConn_Audio_Line:             return "Audio Line";
  56.     case PhysConn_Audio_Mic:              return "Audio Microphone";
  57.     case PhysConn_Audio_AESDigital:       return "Audio AES/EBU Digital";
  58.     case PhysConn_Audio_SPDIFDigital:     return "Audio S/PDIF";
  59.     case PhysConn_Audio_SCSI:             return "Audio SCSI";
  60.     case PhysConn_Audio_AUX:              return "Audio AUX";
  61.     case PhysConn_Audio_1394:             return "Audio 1394";
  62.     case PhysConn_Audio_USB:              return "Audio USB";
  63.     case PhysConn_Audio_AudioDecoder:     return "Audio Decoder";
  64.     default:                              return "Unknown Type";
  65.     }
  66. }
  67. /*****************************************************************************
  68.  * DeleteCrossbarRoutes
  69.  *****************************************************************************/
  70. void DeleteCrossbarRoutes( access_sys_t *p_sys )
  71. {
  72.     /* Remove crossbar filters from graph */
  73.     for( int i = 0; i < p_sys->i_crossbar_route_depth; i++ )
  74.     {
  75.         p_sys->crossbar_routes[i].pXbar->Release();
  76.     }
  77.     p_sys->i_crossbar_route_depth = 0;
  78. }
  79. /*****************************************************************************
  80.  * RouteCrossbars (Does not AddRef the returned *Pin)
  81.  *****************************************************************************/
  82. static HRESULT GetCrossbarIPinAtIndex( IAMCrossbar *pXbar, LONG PinIndex,
  83.                                        BOOL IsInputPin, IPin ** ppPin )
  84. {
  85.     LONG         cntInPins, cntOutPins;
  86.     IPin        *pP = NULL;
  87.     IBaseFilter *pFilter = NULL;
  88.     IEnumPins   *pins = NULL;
  89.     ULONG        n;
  90.     if( !pXbar || !ppPin ) return E_POINTER;
  91.     *ppPin = 0;
  92.     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) ) return E_FAIL;
  93.     LONG TrueIndex = IsInputPin ? PinIndex : PinIndex + cntInPins;
  94.     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
  95.     {
  96.         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
  97.         {
  98.             LONG i = 0;
  99.             while( pins->Next(1, &pP, &n) == S_OK )
  100.             {
  101.                 pP->Release();
  102.                 if( i == TrueIndex )
  103.                 {
  104.                     *ppPin = pP;
  105.                     break;
  106.                 }
  107.                 i++;
  108.             }
  109.             pins->Release();
  110.         }
  111.         pFilter->Release();
  112.     }
  113.     return *ppPin ? S_OK : E_FAIL;
  114. }
  115. /*****************************************************************************
  116.  * GetCrossbarIndexFromIPin: Find corresponding index of an IPin on a crossbar
  117.  *****************************************************************************/
  118. static HRESULT GetCrossbarIndexFromIPin( IAMCrossbar * pXbar, LONG * PinIndex,
  119.                                          BOOL IsInputPin, IPin * pPin )
  120. {
  121.     LONG         cntInPins, cntOutPins;
  122.     IPin        *pP = NULL;
  123.     IBaseFilter *pFilter = NULL;
  124.     IEnumPins   *pins = NULL;
  125.     ULONG        n;
  126.     BOOL         fOK = FALSE;
  127.     if(!pXbar || !PinIndex || !pPin )
  128.         return E_POINTER;
  129.     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) )
  130.         return E_FAIL;
  131.     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
  132.     {
  133.         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
  134.         {
  135.             LONG i=0;
  136.             while( pins->Next(1, &pP, &n) == S_OK )
  137.             {
  138.                 pP->Release();
  139.                 if( pPin == pP )
  140.                 {
  141.                     *PinIndex = IsInputPin ? i : i - cntInPins;
  142.                     fOK = TRUE;
  143.                     break;
  144.                 }
  145.                 i++;
  146.             }
  147.             pins->Release();
  148.         }
  149.         pFilter->Release();
  150.     }
  151.     return fOK ? S_OK : E_FAIL;
  152. }
  153. /*****************************************************************************
  154.  * FindCrossbarRoutes
  155.  *****************************************************************************/
  156. HRESULT FindCrossbarRoutes( vlc_object_t *p_this, access_sys_t *p_sys,
  157.                             IPin *p_input_pin, LONG physicalType, int depth )
  158. {
  159.     HRESULT result = S_FALSE;
  160.     IPin *p_output_pin;
  161.     if( FAILED(p_input_pin->ConnectedTo(&p_output_pin)) ) return S_FALSE;
  162.     // It is connected, so now find out if the filter supports IAMCrossbar
  163.     PIN_INFO pinInfo;
  164.     if( FAILED(p_output_pin->QueryPinInfo(&pinInfo)) ||
  165.         PINDIR_OUTPUT != pinInfo.dir )
  166.     {
  167.         p_output_pin->Release ();
  168.         return S_FALSE;
  169.     }
  170.     IAMCrossbar *pXbar = NULL;
  171.     if( FAILED(pinInfo.pFilter->QueryInterface(IID_IAMCrossbar,
  172.                                                (void **)&pXbar)) )
  173.     {
  174.         pinInfo.pFilter->Release();
  175.         p_output_pin->Release ();
  176.         return S_FALSE;
  177.     }
  178.     LONG inputPinCount, outputPinCount;
  179.     if( FAILED(pXbar->get_PinCounts(&outputPinCount, &inputPinCount)) )
  180.     {
  181.         pXbar->Release();
  182.         pinInfo.pFilter->Release();
  183.         p_output_pin->Release ();
  184.         return S_FALSE;
  185.     }
  186.     LONG inputPinIndexRelated, outputPinIndexRelated;
  187.     LONG inputPinPhysicalType = 0, outputPinPhysicalType;
  188.     LONG inputPinIndex = 0, outputPinIndex;
  189.     if( FAILED(GetCrossbarIndexFromIPin( pXbar, &outputPinIndex,
  190.                                          FALSE, p_output_pin )) ||
  191.         FAILED(pXbar->get_CrossbarPinInfo( FALSE, outputPinIndex,
  192.                                            &outputPinIndexRelated,
  193.                                            &outputPinPhysicalType )) )
  194.     {
  195.         pXbar->Release();
  196.         pinInfo.pFilter->Release();
  197.         p_output_pin->Release ();
  198.         return S_FALSE;
  199.     }
  200.     /*
  201.     ** if physical type is 0, then use default/existing route to physical connector
  202.     */
  203.     if( physicalType == 0 )
  204.     {
  205.         /* use following as default connector type if we fail to find an existing route */
  206.         physicalType = PhysConn_Video_Tuner;
  207.         if( SUCCEEDED(pXbar->get_IsRoutedTo(outputPinIndex, &inputPinIndex)) )
  208.         {
  209.             if( SUCCEEDED( pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
  210.                            &inputPinIndexRelated, &inputPinPhysicalType )) )
  211.             {
  212.                 // remember connector type
  213.                 physicalType = inputPinPhysicalType;
  214.  
  215.                 msg_Dbg( p_this, "found existing route for output %ld (type %s) to input %ld (type %s)",
  216.                          outputPinIndex, GetPhysicalPinName( outputPinPhysicalType ),
  217.                          inputPinIndex, GetPhysicalPinName( inputPinPhysicalType ) );
  218.  
  219.                 // fall through to for loop, note 'inputPinIndex' is set to the pin we are looking for
  220.                 // hence, loop iteration should not wind back
  221.             }
  222.         }
  223.         else {
  224.             // reset to first pin for complete loop iteration
  225.             inputPinIndex = 0;
  226.         }
  227.     }
  228.  
  229.     //
  230.     // for all input pins
  231.     //
  232.     for( /* inputPinIndex has been set */ ; (S_OK != result) && (inputPinIndex < inputPinCount); ++inputPinIndex )
  233.     {
  234.         if( FAILED(pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
  235.             &inputPinIndexRelated, &inputPinPhysicalType )) ) continue;
  236.         // Is this pin matching required connector physical type?
  237.         if( inputPinPhysicalType != physicalType ) continue;
  238.         // Can we route it?
  239.         if( FAILED(pXbar->CanRoute(outputPinIndex, inputPinIndex)) ) continue;
  240.  
  241.  
  242.         IPin *pPin;
  243.         if( FAILED(GetCrossbarIPinAtIndex( pXbar, inputPinIndex,
  244.                                            TRUE, &pPin)) ) continue;
  245.         result = FindCrossbarRoutes( p_this, p_sys, pPin,
  246.                                      physicalType, depth+1 );
  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.             // 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.             msg_Dbg( p_this, "crossbar at depth %d, found route for "
  260.                      "output %ld (type %s) to input %ld (type %s)", depth,
  261.                      outputPinIndex, GetPhysicalPinName( outputPinPhysicalType ),
  262.                      inputPinIndex, GetPhysicalPinName( inputPinPhysicalType ) );
  263.             result = S_OK;
  264.         }
  265.     }
  266.     pXbar->Release();
  267.     pinInfo.pFilter->Release();
  268.     p_output_pin->Release ();
  269.     return result;
  270. }