/// <summary> /// Checks if the pin connections can be kept, or if a graph rebuilding is necessary. /// </summary> /// <param name="baseFilter">Filter to check</param> /// <returns>True if graph needs to be rebuilt</returns> private static bool GraphNeedsRebuild(IBaseFilter baseFilter) { IEnumPins pinEnum; int hr = baseFilter.EnumPins(out pinEnum); if (hr != 0 || pinEnum == null) { return(true); } IPin[] pins = new IPin[1]; IntPtr ptrFetched = Marshal.AllocCoTaskMem(4); for (; ;) { hr = pinEnum.Next(1, pins, ptrFetched); if (hr != 0 || Marshal.ReadInt32(ptrFetched) == 0) { break; } try { IPin other; if (pins[0].ConnectedTo(out other) == 0 && other != null) { try { PinInfo pinInfo; pins[0].QueryPinInfo(out pinInfo); FilterInfo filterInfo = FilterGraphTools.QueryFilterInfoAndFree(pinInfo.filter); try { if (!QueryConnect(pins[0], other)) { ServiceRegistration.Get <ILogger>().Info("Graph needs a rebuild. Filter: {0}, Pin: {1}", filterInfo.achName, pinInfo.name); return(true); } } finally { FilterGraphTools.FreePinInfo(pinInfo); } } finally { Marshal.ReleaseComObject(other); } } } finally { Marshal.ReleaseComObject(pins[0]); } } Marshal.ReleaseComObject(pinEnum); Marshal.FreeCoTaskMem(ptrFetched); ServiceRegistration.Get <ILogger>().Info("Graph does not need a rebuild"); return(false); }
/// <summary> /// QueryConnect checks if two Pins can be connected. /// </summary> /// <param name="pin">Pin 1</param> /// <param name="other">Pin 2</param> /// <returns>True if they accept connection</returns> static bool QueryConnect(IPin pin, IPin other) { IEnumMediaTypes enumTypes; int hr = pin.EnumMediaTypes(out enumTypes); if (hr != 0 || enumTypes == null) { return(false); } int count = 0; IntPtr ptrFetched = Marshal.AllocCoTaskMem(4); try { for (; ;) { AMMediaType[] types = new AMMediaType[1]; hr = enumTypes.Next(1, types, ptrFetched); if (hr != 0 || Marshal.ReadInt32(ptrFetched) == 0) { break; } count++; try { if (other.QueryAccept(types[0]) == 0) { return(true); } } finally { FilterGraphTools.FreeAMMediaType(types[0]); } } PinInfo info; PinInfo infoOther; pin.QueryPinInfo(out info); other.QueryPinInfo(out infoOther); ServiceRegistration.Get <ILogger>().Info("Pins {0} and {1} do not accept each other. Tested {2} media types", info.name, infoOther.name, count); FilterGraphTools.FreePinInfo(info); FilterGraphTools.FreePinInfo(infoOther); return(false); } finally { Marshal.FreeCoTaskMem(ptrFetched); } }
/// <summary> /// Disconnects a single Pin. /// </summary> /// <param name="graphBuilder">IGraphBuilder</param> /// <param name="pin">Pin to disconnect</param> /// <returns>True if successful</returns> bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin) { IntPtr other_ptr; int hr = pin.ConnectedTo(out other_ptr); bool allDisconnected = true; if (hr == 0 && other_ptr != IntPtr.Zero) { IPin other = Marshal.GetObjectForIUnknown(other_ptr) as IPin; PinInfo info; pin.QueryPinInfo(out info); ServiceRegistration.Get <ILogger>().Info("Disconnecting pin {0}", info.name); FilterGraphTools.FreePinInfo(info); other.QueryPinInfo(out info); if (!DisconnectAllPins(graphBuilder, info.filter)) { allDisconnected = false; } FilterGraphTools.FreePinInfo(info); hr = pin.Disconnect(); if (hr != 0) { allDisconnected = false; ServiceRegistration.Get <ILogger>().Error("Error disconnecting: {0:x}", hr); } hr = other.Disconnect(); if (hr != 0) { allDisconnected = false; ServiceRegistration.Get <ILogger>().Error("Error disconnecting other: {0:x}", hr); } Marshal.ReleaseComObject(other); } else { ServiceRegistration.Get <ILogger>().Info(" Not connected"); } return(allDisconnected); }
/// <summary> /// Disconnects all pins of all filters in graph. /// </summary> /// <param name="graphBuilder">IGraphBuilder</param> /// <param name="filter">Current IBaseFilter in graph</param> bool DisconnectAllPins(IGraphBuilder graphBuilder, IBaseFilter filter) { IEnumPins pinEnum; int hr = filter.EnumPins(out pinEnum); if (hr != 0 || pinEnum == null) { return(false); } FilterInfo info = FilterGraphTools.QueryFilterInfoAndFree(filter); ServiceRegistration.Get <ILogger>().Info("Disconnecting all pins from filter {0}", info.achName); bool allDisconnected = true; IntPtr ptrFetched = Marshal.AllocCoTaskMem(4); for (; ;) { IPin[] pins = new IPin[1]; hr = pinEnum.Next(1, pins, ptrFetched); if (hr != 0 || Marshal.ReadInt32(ptrFetched) == 0) { break; } PinInfo pinInfo; pins[0].QueryPinInfo(out pinInfo); if (pinInfo.dir == PinDirection.Output) { if (!DisconnectPin(graphBuilder, pins[0])) { allDisconnected = false; } } FilterGraphTools.FreePinInfo(pinInfo); Marshal.ReleaseComObject(pins[0]); } Marshal.ReleaseComObject(pinEnum); Marshal.FreeCoTaskMem(ptrFetched); return(allDisconnected); }
/// <summary> /// QueryConnect checks if two Pins can be connected. /// </summary> /// <param name="pin">Pin 1</param> /// <param name="other">Pin 2</param> /// <returns>True if they accept connection</returns> static bool QueryConnect(IPin pin, IPin other) { var pin1 = new DSPin(pin); var pinOther = new DSPin(other); foreach (var mediaType in pin1.MediaTypes) { if (pinOther.IsAccepted(mediaType)) { return(true); } } PinInfo info; PinInfo infoOther; pin.QueryPinInfo(out info); other.QueryPinInfo(out infoOther); ServiceRegistration.Get <ILogger>().Info("Pins {0} and {1} do not accept each other. Tested {2} media types", info.name, infoOther.name, pin1.MediaTypes.Count); FilterGraphTools.FreePinInfo(info); FilterGraphTools.FreePinInfo(infoOther); return(false); }
/// <summary> /// Reconnects all filters in graph. /// </summary> /// <param name="graphBuilder">IGraphBuilder</param> /// <param name="filter">Current IBaseFilter in graph</param> static void ReConnectAll(IGraphBuilder graphBuilder, IBaseFilter filter) { IEnumPins pinEnum; FilterInfo info = FilterGraphTools.QueryFilterInfoAndFree(filter); IntPtr ptrFetched = Marshal.AllocCoTaskMem(4); int hr = filter.EnumPins(out pinEnum); if ((hr == 0) && (pinEnum != null)) { ServiceRegistration.Get <ILogger>().Info("got pins"); IPin[] pins = new IPin[1]; int iFetched; int iPinNo = 0; do { // Get the next pin iPinNo++; hr = pinEnum.Next(1, pins, ptrFetched); // In case of error stop the pin enumeration if (hr != 0) { break; } iFetched = Marshal.ReadInt32(ptrFetched); if (iFetched == 1 && pins[0] != null) { PinInfo pinInfo; hr = pins[0].QueryPinInfo(out pinInfo); if (hr == 0) { ServiceRegistration.Get <ILogger>().Info(" got pin#{0}:{1}", iPinNo - 1, pinInfo.name); FilterGraphTools.FreePinInfo(pinInfo); } else { ServiceRegistration.Get <ILogger>().Info(" got pin:?"); } PinDirection pinDir; pins[0].QueryDirection(out pinDir); if (pinDir == PinDirection.Output) { IntPtr other_ptr; hr = pins[0].ConnectedTo(out other_ptr); if (hr == 0 && other_ptr != IntPtr.Zero) { ServiceRegistration.Get <ILogger>().Info("Reconnecting {0}:{1}", info.achName, pinInfo.name); hr = graphBuilder.Reconnect(pins[0]); if (hr != 0) { ServiceRegistration.Get <ILogger>().Warn("Reconnect failed: {0}:{1}, code: 0x{2:x}", info.achName, pinInfo.name, hr); } IPin other = Marshal.GetObjectForIUnknown(other_ptr) as IPin; PinInfo otherPinInfo; other.QueryPinInfo(out otherPinInfo); ReConnectAll(graphBuilder, otherPinInfo.filter); FilterGraphTools.FreePinInfo(otherPinInfo); Marshal.ReleaseComObject(other); } } Marshal.ReleaseComObject(pins[0]); } else { ServiceRegistration.Get <ILogger>().Info("no pins?"); break; } }while (iFetched == 1); FilterGraphTools.TryRelease(ref pinEnum); Marshal.FreeCoTaskMem(ptrFetched); } }