📄 crossbar.cpp
字号:
//------------------------------------------------------------------------------
// File: Crossbar.cpp
//
// Desc: A class for controlling video crossbars.
//
// This class creates a single object which encapsulates all connected
// crossbars, enumerates all unique inputs which can be reached from
// a given starting pin, and automatically routes audio when a video
// source is selected.
//
// The class supports an arbitrarily complex graph of crossbars,
// which can be cascaded and disjoint, that is not all inputs need
// to traverse the same set of crossbars.
//
// Given a starting input pin (typically the analog video input to
// the capture filter), the class recursively traces upstream
// searching for all viable inputs. An input is considered viable if
// it is a video pin and is either:
//
// - unconnected
// - connects to a filter which does not support IAMCrossbar
//
// Methods:
//
// CCrossbar (IPin *pPin);
// ~CCrossbar();
//
// HRESULT GetInputCount (LONG *pCount);
// HRESULT GetInputType (LONG Index, LONG * PhysicalType);
// HRESULT GetInputName (LONG Index, TCHAR * pName, LONG NameSize);
// HRESULT SetInputIndex (LONG Index);
// HRESULT GetInputIndex (LONG *Index);
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include <streams.h>
#include "crossbar.h"
//------------------------------------------------------------------------------
// Name: CCrossbar::CCrossbar()
// Desc: Constructor for the CCrossbar class
//------------------------------------------------------------------------------
CCrossbar::CCrossbar(
IPin *pStartingInputPin,
HRESULT *phr
)
: m_pStartingPin (pStartingInputPin)
, m_CurrentRoutingIndex (0)
, m_RoutingList (NULL)
{
HRESULT hr;
ASSERT(phr);
DbgLog((LOG_TRACE,3,TEXT("CCrossbar Constructor")));
ASSERT (pStartingInputPin != NULL);
// Init everything to zero
ZeroMemory (&m_RoutingRoot, sizeof (m_RoutingRoot));
m_RoutingList = new CRoutingList (TEXT("RoutingList"), 5);
if (m_RoutingList)
hr = BuildRoutingList(pStartingInputPin, &m_RoutingRoot, 0 /* Depth */);
else
hr = E_OUTOFMEMORY;
// Return an error/success code from the constructor
if (phr)
*phr = hr;
}
//------------------------------------------------------------------------------
// Name: CCrossbar::CCrossbar()
// Desc: Destructor for the CCrossbar class
//------------------------------------------------------------------------------
CCrossbar::~CCrossbar()
{
DbgLog((LOG_TRACE,3,TEXT("CCrossbar Destructor")));
HRESULT hr = DestroyRoutingList ();
delete m_RoutingList;
}
//
// This function is called recursively, every time a new crossbar is
// entered as we search upstream.
//
// Return values:
//
// S_OK - Returned on final exit after recursive search if at least
// one routing is possible
// S_FALSE - Normal return indicating we've reached the end of a
// recursive search, so save the current path
// E_FAIL - Unable to route anything
HRESULT CCrossbar::BuildRoutingList (
IPin *pStartingInputPin,
CRouting *pRouting,
int Depth
)
{
HRESULT hr;
LONG InputIndexRelated, OutputIndexRelated;
LONG InputPhysicalType, OutputPhysicalType;
LONG Inputs, Outputs, InputIndex, OutputIndex;
IPin *pPin=0;
IPin *pStartingOutputPin=0;
PIN_INFO pinInfo;
CRouting RoutingNext;
IAMCrossbar *pXbar=0;
ASSERT (pStartingInputPin != NULL);
ASSERT (pRouting != NULL);
if (!pStartingInputPin || !pRouting)
return E_POINTER;
//
// If the pin isn't connected, then it's a terminal pin
//
hr = pStartingInputPin->ConnectedTo (&pStartingOutputPin);
if (hr != S_OK)
return (Depth == 0) ? E_FAIL : S_FALSE;
//
// It is connected, so now find out if the filter supports
// IAMCrossbar
//
if (S_OK == pStartingOutputPin->QueryPinInfo(&pinInfo))
{
ASSERT (pinInfo.dir == PINDIR_OUTPUT);
hr = pinInfo.pFilter->QueryInterface(IID_IAMCrossbar, (void **)&pXbar);
if (hr == S_OK)
{
EXECUTE_ASSERT (S_OK == pXbar->get_PinCounts(&Outputs, &Inputs));
EXECUTE_ASSERT (S_OK == GetCrossbarIndexFromIPin (
pXbar,
&OutputIndex,
FALSE, // Input ?
pStartingOutputPin));
EXECUTE_ASSERT (S_OK == pXbar->get_CrossbarPinInfo(
FALSE, // Input ?
OutputIndex,
&OutputIndexRelated,
&OutputPhysicalType));
//
// for all input pins
//
for (InputIndex = 0; InputIndex < Inputs; InputIndex++)
{
EXECUTE_ASSERT (S_OK == pXbar->get_CrossbarPinInfo(
TRUE, // Input?
InputIndex,
&InputIndexRelated,
&InputPhysicalType));
//
// Is the pin a video pin?
//
if (InputPhysicalType < PhysConn_Audio_Tuner)
{
//
// Can we route it?
//
if (S_OK == pXbar->CanRoute(OutputIndex, InputIndex))
{
EXECUTE_ASSERT (S_OK == GetCrossbarIPinAtIndex (
pXbar,
InputIndex,
TRUE, // Input
&pPin));
//
// We've found a route through this crossbar
// so save our state before recusively searching
// again.
//
ZeroMemory (&RoutingNext, sizeof (RoutingNext));
// doubly linked list
RoutingNext.pRightRouting = pRouting;
pRouting->pLeftRouting = &RoutingNext;
pRouting->pXbar = pXbar;
pRouting->VideoInputIndex = InputIndex;
pRouting->VideoOutputIndex = OutputIndex;
pRouting->AudioInputIndex = InputIndexRelated;
pRouting->AudioOutputIndex = OutputIndexRelated;
pRouting->InputPhysicalType = InputPhysicalType;
pRouting->OutputPhysicalType = OutputPhysicalType;
pRouting->Depth = Depth;
hr = BuildRoutingList (pPin, &RoutingNext, Depth + 1);
if (hr == S_FALSE)
{
pRouting->pLeftRouting = NULL;
SaveRouting (pRouting);
}
} // if we can route
} // if its a video pin
} // for all input pins
pXbar->Release();
}
else
{
// The filter doesn't support IAMCrossbar, so this
// is a terminal pin
pinInfo.pFilter->Release();
pStartingOutputPin->Release ();
return (Depth == 0) ? E_FAIL : S_FALSE;
}
pinInfo.pFilter->Release();
}
pStartingOutputPin->Release ();
return S_OK;
}
//
// Make a copy of the current routing, and AddRef the IAMCrossbar
// interfaces.
//
HRESULT CCrossbar::SaveRouting (CRouting *pRoutingNew)
{
int Depth = pRoutingNew->Depth + 1;
CRouting *pr=0;
CRouting *pCurrent = pRoutingNew;
if (!pRoutingNew || !m_RoutingList)
return E_POINTER;
DbgLog((LOG_TRACE,3,TEXT("CCrossbar::SaveRouting, Depth=%d, NumberOfRoutings=%d"),
Depth, m_RoutingList->GetCount() + 1));
pr = new CRouting[Depth];
if (pr == NULL)
return E_FAIL;
m_RoutingList->AddTail (pr);
for (int j = 0; j < Depth; j++, pr++)
{
*pr = *pCurrent;
ASSERT (pCurrent->pXbar != NULL);
//
// We're holding onto this interface, so AddRef
//
pCurrent->pXbar->AddRef();
pCurrent = pCurrent->pRightRouting;
//
// Pointers were stack based during recursive search, so update them
// in the allocated array
//
pr->pLeftRouting = pr - 1;
pr->pRightRouting = pr + 1;
if (j == 0) { // first element
pr->pLeftRouting = NULL;
}
if (j == (Depth - 1)) { // last element
pr->pRightRouting = NULL;
}
}
return S_OK;
}
HRESULT CCrossbar::DestroyRoutingList()
{
int k, Depth;
CRouting *pCurrent=0, *pFirst=0;
if (!m_RoutingList)
return E_POINTER;
DbgLog((LOG_TRACE,3,TEXT("DestroyRoutingList")));
while (m_RoutingList->GetCount())
{
pCurrent = pFirst = m_RoutingList->RemoveHead();
if (pCurrent)
{
Depth = pCurrent->Depth + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -