/// <summary> /// Verbindet zwei Filter. Es wird erwartet, dass jeweils ein einziger Ein-/Ausgang existiert. /// </summary> /// <param name="from">Der Filter, der die Daten produziert.</param> /// <param name="to">Der Filter, der die Daten entgegennimmt.</param> private void Connect(TypedComIdentity <IBaseFilter> from, TypedComIdentity <IBaseFilter> to) { // Attach to pins using (var fromPin = from.GetSinglePin(PinDirection.Output)) using (var toPin = to.GetSinglePin(PinDirection.Input)) ((IGraphBuilder)m_Graph).Connect(fromPin.Interface, toPin.Interface); }
/// <summary> /// Erzeugt einen neuen Filter. /// </summary> /// <param name="name">Der Name des Filters.</param> /// <param name="filter">Der bereits geladene Filter.</param> /// <returns>Die COM Schnittstelle des neuen Filters.</returns> /// <exception cref="ArgumentNullException">Es wurde kein Filter angegeben.</exception> private void AddFilter(string name, TypedComIdentity <IBaseFilter> filter) { // Validate if (filter == null) { throw new ArgumentNullException("filter"); } // Process ((IGraphBuilder)m_Graph).AddFilter(filter.Interface, name); }
/// <summary> /// Beendet den Graphen und gibt alle damit verbundenen Ressourcen frei. /// </summary> public void Destroy() { // Disable decryption callback Interlocked.Exchange(ref m_PMTSink, null); // Pipelines DecryptionPipeline.Terminate(); SignalPipeline.Terminate(); TunePipeline.Terminate(); // External registration using (m_ExternalRegistration) m_ExternalRegistration = null; // Extra filters var additionalFilters = AdditionalFilters.ToArray(); // Reset AdditionalFilters.Clear(); // Filter foreach (var additionalFilter in additionalFilters) { if (additionalFilter != null) { additionalFilter.Dispose(); } } using (m_TIF) m_TIF = null; using (TransportStreamAnalyser) TransportStreamAnalyser = null; using (CaptureFilter) CaptureFilter = null; using (TunerFilter) TunerFilter = null; using (NetworkProvider) NetworkProvider = null; // The graph itself if (m_Graph != null) { try { // Done with it m_Graph.Stop(); } catch (Exception e) { // For now we ignore all errors during shutdown Trace.WriteLine(e.Message); } }
/// <summary> /// Erzeugt einen Graphen und startet ihn. /// </summary> /// <param name="location">Der Ursprung, über den die Quellgruppe empfangen wird.</param> /// <param name="group">Die gewünschte Quellgruppe.</param> /// <exception cref="ArgumentException">Es wurden nicht alle Parameter gesetzt.</exception> public void Create(GroupLocation location, SourceGroup group) { // Get rid of it Destroy(); // Create new graph builder var graph = Activator.CreateInstance(Type.GetTypeFromCLSID(BDAEnvironment.GraphBuilderClassIdentifier)); try { // Convert interface m_Graph = (IMediaFilter)graph; } catch { // Cleanup BDAEnvironment.Release(ref graph); // Forward throw; } // See if we should register the graph m_ExternalRegistration = BDASettings.RegisterBDAGRaph(m_Graph, false); // Attach to alternate interface var builder = (IGraphBuilder)m_Graph; // Check log var logFile = BDASettings.BDALogPath; if (logFile != null) { // Open path m_LogFile = new FileStream(logFile.FullName, FileMode.Create, FileAccess.Write, FileShare.Read); // Enable logging on graph builder builder.SetLogFile(m_LogFile.SafeFileHandle); } // Start with network provider NetworkProvider = AddFilter("Network Provider", BDAEnvironment.GetNetworkProviderMoniker(DVBType)); // Initialize provider Tune(location, group); // Always create the tuner if (TunerInformation != null) { TunerFilter = AddFilter("Tuner", TunerInformation); } else { throw new ArgumentException(Properties.Resources.Exception_MissingTuner, "Tuner"); } // Optionally create capture if (CaptureInformation != null) { CaptureFilter = AddFilter("Capture", CaptureInformation); } // Add additional filter foreach (var additionalFilter in AdditionalFilterInformations) { if (additionalFilter == null) { throw new ArgumentNullException("AdditionalFilters"); } else { AdditionalFilters.Add(AddFilter(additionalFilter.DisplayName, additionalFilter)); } } // Connect network provider to streaming instance Connect(NetworkProvider, CaptureFilter ?? TunerFilter); // Initialize provider Tune(location, group); // Create the primary filter and add it AddFilter("TS", TransportStreamAnalyser = new InputFilter()); // Connect device output for analysis Connect(CaptureFilter ?? TunerFilter, TransportStreamAnalyser); // Create the demultiplexer - needed to keep the infrastructure alive using (var demux = AddFilter("TIF", BDAEnvironment.MicrosoftDemultiplexerMoniker)) { // Connect to the dedicated pin of our analyser TransportStreamAnalyser.DataManager.TIFConnector.Connect(demux, BDAEnvironment.TransportStreamMediaType1); // Pins to remove var remove = new List <string>(); // Prepare the demultiplexer pins demux.InspectAllPins(pin => { // See if this is the SI pin bool isSectionPin = false; pin.InspectAllMediaTypes(type => { // Check major if (!type.MajorType.Equals(BDAEnvironment.DataFormatTypeSections)) { return(true); } // Check minor isSectionPin = type.SubType.Equals(BDAEnvironment.DataFormatSubtypeSI); // Report return(!isSectionPin); }); // Check the mode if (isSectionPin) { // Connect using (var comPin = ComIdentity.Create(pin)) builder.Render(comPin.Interface); // Load connection data IntPtr tifIn = IntPtr.Zero; if (pin.ConnectedTo(ref tifIn) < 0) { throw new InvalidOperationException(Properties.Resources.Exception_TIF); } // Reconstruct var tifPin = Marshal.GetObjectForIUnknown(tifIn); try { // Request pin context var info = new PinInfo(); ((IPin)tifPin).QueryPinInfo(ref info); // Request from pin m_TIF = info.GetAndDisposeFilter(); } finally { // Cleanup BDAEnvironment.Release(ref tifPin); } } else if (pin.QueryDirection() == PinDirection.Output) { // Prepare to kill remove.Add(pin.QueryId()); } }); // Prepare to remove all unconnected pins if (remove.Count > 0) { using (var demuxInstance = demux.MarshalToManaged()) { // Change type var mpeg2 = (IMpeg2Demultiplexer)demuxInstance.Object; // Remove all foreach (var id in remove) { mpeg2.DeleteOutputPin(id); } } } } // Install the PMT watchdog TransportStreamAnalyser.DataManager.TSParser.PMTFound += ProcessPMT; }