|
|
//---------------------------------------------------------------------------
//
// Module: sn.cpp
//
// Description:
//
//
//@@BEGIN_MSINTERNAL
// Development Team:
// Mike McLaughlin
//
// History: Date Author Comment
//
// To Do: Date Author Comment
//
//@@END_MSINTERNAL
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#include "common.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
NTSTATUS CStartNode::Create( PPIN_NODE pPinNode, PCONNECT_NODE pConnectNode, PGRAPH_PIN_INFO pGraphPinInfo, ULONG ulFlagsCurrent, ULONG ulOverhead, PGRAPH_NODE pGraphNode ) { PTOPOLOGY_CONNECTION pTopologyConnection; NTSTATUS Status = STATUS_SUCCESS; PSTART_NODE pStartNode = NULL;
Assert(pPinNode); Assert(pGraphNode);
if((pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_SOURCE)) { ASSERT(NT_SUCCESS(Status)); ASSERT(pStartNode == NULL); goto exit; }
if(pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_SINK || pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_BOTH) {
// Don't create a sysaudio pin if OUT/RENDER or IN/CAPTURER
if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT && ulFlagsCurrent & LFN_FLAGS_CONNECT_RENDER) { DPF1(50, "CStartNode::Create PN %08x - out/render", pPinNode); ASSERT(NT_SUCCESS(Status)); ASSERT(pStartNode == NULL); goto exit; } if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN && ulFlagsCurrent & LFN_FLAGS_CONNECT_CAPTURE) { DPF1(50, "CStartNode::Create PN %08x - in/capturer", pPinNode); ASSERT(NT_SUCCESS(Status)); ASSERT(pStartNode == NULL); goto exit; } }
FOR_EACH_LIST_ITEM( &pPinNode->pPinInfo->lstTopologyConnection, pTopologyConnection) {
// Only check physical connections
if(!IS_CONNECTION_TYPE(pTopologyConnection, PHYSICAL)) { continue; }
// If there is one connection that is valid for this GraphNode
if(pTopologyConnection->IsTopologyConnectionOnGraphNode(pGraphNode)) {
// Don't create a sysaudio pin
DPF4(80, "CStartNode::Create %s PN %08x TC %08x GN %08x connected", pPinNode->pPinInfo->pFilterNode->DumpName(), pPinNode, pTopologyConnection, pGraphNode);
ASSERT(NT_SUCCESS(Status)); ASSERT(pStartNode == NULL); goto exit; } } END_EACH_LIST_ITEM
pStartNode = new START_NODE( pPinNode, pConnectNode, ulOverhead, pGraphNode);
if(pStartNode == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto exit; } Status = CStartInfo::Create( pStartNode, pConnectNode->GetConnectInfo(), pGraphPinInfo, pGraphNode);
if(!NT_SUCCESS(Status)) { Trap(); goto exit; } DPF3(80, "CStartNode::Create %08x PN %08x O %08x", pStartNode, pPinNode, pStartNode->ulOverhead);
//
// For capture graphs only.
//
if (pStartNode->pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) { pStartNode->SetSpecialFlags(); } exit: if(!NT_SUCCESS(Status)) { if (pStartNode) { pStartNode->Destroy(); } } return(Status); }
CStartNode::CStartNode( PPIN_NODE pPinNode, PCONNECT_NODE pConnectNode, ULONG ulOverhead, PGRAPH_NODE pGraphNode ) { Assert(pPinNode); Assert(pGraphNode); this->pPinNode = pPinNode; this->ulOverhead = ulOverhead + pPinNode->GetOverhead(); this->pConnectNodeHead = pConnectNode; this->ulFlags = 0; this->fRender = (pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN); this->ulSpecialFlags = STARTNODE_SPECIALFLAG_NONE; pConnectNode->AddRef(); if(pPinNode->GetType() & FILTER_TYPE_VIRTUAL) { AddListEnd(&pGraphNode->lstStartNode); } else { AddList(&pGraphNode->lstStartNode); } DPF3(80, "CStartNode: %08x PN %08x O %08x", this, pPinNode, ulOverhead); }
CStartNode::~CStartNode( ) { DPF1(80, "~CStartNode: %08x", this); Assert(this); RemoveList(); pStartInfo->Destroy(); pConnectNodeHead->Destroy(); }
void CStartNode::SetSpecialFlags() { //
// STARTNODE_SPECIALFLAG_STRICT
// Get the last ConnectNode in connection list and check if the
// source pin is splitter.
// Also the first pin should be splitter pin.
//
//
// STARTNODE_SPECIALFLAG_AEC
// If the StartNode contains Aec mark the StartNode with this flag.
//
//
// ISSUE-2001/03/09-alpers
// In the future two splitters in the graph will not work
// with this logic.
// We need a way of knowing if a filter does SRC upfront.
//
if (pConnectNodeHead) { PCONNECT_NODE pConnectNode;
for(pConnectNode = pConnectNodeHead; pConnectNode->GetNextConnectNode() != NULL; pConnectNode = pConnectNode->GetNextConnectNode()) {
if (pConnectNode->pPinNodeSource->pLogicalFilterNode-> pFilterNode->GetType() & FILTER_TYPE_AEC) {
ulSpecialFlags |= STARTNODE_SPECIALFLAG_AEC; } }
ulSpecialFlags |= (pConnectNode->pPinNodeSource->pPinInfo-> pFilterNode->GetType() & FILTER_TYPE_SPLITTER) && (pPinNode->pPinInfo->pFilterNode->GetType() & FILTER_TYPE_SPLITTER) ? STARTNODE_SPECIALFLAG_STRICT : STARTNODE_SPECIALFLAG_NONE; }
DPF3(50, "CStartNode: %08x %s SpecialFlags %X", this, DbgUnicode2Sz(pPinNode->pPinInfo->pFilterNode->GetFriendlyName()), ulSpecialFlags); }
ENUMFUNC CStartNode::RemoveBypassPaths( PVOID pReference ) { PGRAPH_NODE pGraphNode = PGRAPH_NODE(pReference); PLOGICAL_FILTER_NODE pLogicalFilterNode; PCONNECT_NODE pConnectNode; ULONG cLfnNoBypassTotal = 0; ULONG cLfnNoBypass = 0; ULONG ulFlags; ULONG cAecFilterCount = 0; BOOL fDestroy;
Assert(this); Assert(pGraphNode);
if(pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_NONE || pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_BRIDGE || pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_SOURCE) { return(STATUS_CONTINUE); }
if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN) { ulFlags = LFN_FLAGS_CONNECT_RENDER; DPF(60,"RBP - for Render"); } else { ASSERT(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT); ulFlags = LFN_FLAGS_CONNECT_CAPTURE; DPF(60,"RBP - for Capture"); }
FOR_EACH_LIST_ITEM( &pGraphNode->lstLogicalFilterNodeNoBypass, pLogicalFilterNode) {
if(pLogicalFilterNode->GetFlags() & ulFlags) { ++cLfnNoBypassTotal; }
} END_EACH_LIST_ITEM
DPF1(60,"RBP:NoBypassTotal = %08x", cLfnNoBypassTotal);
for(pConnectNode = GetFirstConnectNode(); pConnectNode != NULL; pConnectNode = pConnectNode->GetNextConnectNode()) {
Assert(pConnectNode); FOR_EACH_LIST_ITEM( &pGraphNode->lstLogicalFilterNodeNoBypass, pLogicalFilterNode) {
if(pLogicalFilterNode->GetFlags() & ulFlags) { Assert(pConnectNode->pPinNodeSource); Assert(pConnectNode->pPinNodeSource->pLogicalFilterNode); if(pConnectNode->pPinNodeSource->pLogicalFilterNode == pLogicalFilterNode) { cLfnNoBypass++; } }
} END_EACH_LIST_ITEM
DPF1(60,"RBP:FilterInPath = %s", DbgUnicode2Sz(pConnectNode->pPinNodeSource->pLogicalFilterNode->pFilterNode->GetFriendlyName()));
//
// In capture paths count AEC filters to avoid conflict with GFXes
//
if((ulFlags & LFN_FLAGS_CONNECT_CAPTURE) && (pConnectNode->pPinNodeSource->pLogicalFilterNode->pFilterNode->GetType() & FILTER_TYPE_AEC)) { ++cAecFilterCount; } }
ASSERT(cAecFilterCount < 2);
DPF2(60,"RBP:NBPCount=%08x, AECCount=%08x", cLfnNoBypass, cAecFilterCount);
//
// Mark all the paths with NO Gfx as second pass candidates
// We do this to support the following sequence of capture pin creations
// 1. Client installs GFX(es) on a capture device
// 2. Client creates a pin with AEC
// This would result in creating a Capture->Splitter->AEC path
// 3. Client tries to create a regular capture pin (with GFX)
// In this case we want to create a regular path (but since no GFX
// hooked up between capture and splitter. We create a capture->splitter->[kmixer] path
// These special paths are marked as secondpass. And we try these paths
// only if all the primary start nodes failed to instantiate a pin.
// (look in pins.cpp - PinDispatchCreateKP()
//
if(cLfnNoBypassTotal != 0) { if(cLfnNoBypass == 0) { this->ulFlags |= STARTNODE_FLAGS_SECONDPASS; } }
//
// Assume that this path is going to be OK
//
fDestroy = FALSE;
if (cAecFilterCount == 0) { //
// There is no AEC in this path
// We have to make sure that we have all the necessary
// GFXs loaded in this path. (Else destroy the path)
//
if(cLfnNoBypass != cLfnNoBypassTotal) { fDestroy = TRUE; } } else { //
// There is an AEC in this path
// No GFXs should be there in this path. If there is even one GFX
// destroy the path
//
if ((cLfnNoBypass != 0) || (cAecFilterCount > 1)) { fDestroy = TRUE; } }
if ((fDestroy) && ((this->ulFlags & STARTNODE_FLAGS_SECONDPASS) == 0)) { Destroy(); DPF(60,"RBP:PathDestroyed"); }
DPF(60,"RBP:Done"); return(STATUS_CONTINUE); }
ENUMFUNC CStartNode::RemoveConnectedStartNode( PVOID pReference ) { PGRAPH_NODE pGraphNode = PGRAPH_NODE(pReference); PCONNECT_NODE pConnectNode; PSTART_NODE pStartNode;
Assert(this); Assert(pGraphNode);
FOR_EACH_LIST_ITEM(&pGraphNode->lstStartNode, pStartNode) {
if(this == pStartNode) { continue; } for(pConnectNode = pStartNode->GetFirstConnectNode(); pConnectNode != NULL; pConnectNode = pConnectNode->GetNextConnectNode()) {
if(this->pPinNode == pConnectNode->pPinNodeSink) { DPF3(50, "CStartNode::RemoveConnectedSN %08x GN %08x %s", this, pGraphNode, pPinNode->pPinInfo->pFilterNode->DumpName());
Destroy(); return(STATUS_CONTINUE); } }
} END_EACH_LIST_ITEM
return(STATUS_CONTINUE); }
//---------------------------------------------------------------------------
|