/// <summary>
        /// Erzeugt einen Filter und vermerkt ihn.
        /// </summary>
        /// <param name="name">Der Name des Filters.</param>
        /// <param name="moniker">Der eindeutige Name des Filters.</param>
        private void AddFilter(string name, string moniker)
        {
            // Test
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            if (string.IsNullOrEmpty(moniker))
            {
                throw new ArgumentNullException("moniker");
            }

            // Create
            var filter = ComIdentity.Create <IBaseFilter>(moniker);

            try
            {
                // Process
                AddFilter(name, filter);
            }
            catch
            {
                // Cleanup
                filter.Dispose();

                // Forward
                throw;
            }
        }
Example #2
0
        /// <summary>
        /// Meldet, dass nun eine Verbindung zu einem anderen Endpunkt festgelegt wurde.
        /// </summary>
        /// <param name="connector">Ein anderer Endpunkt.</param>
        /// <param name="mediaType">Die Art der Daten, die zwischen den Endpunkten ausgetauscht werden.</param>
        public void ReceiveConnection(IntPtr connector, IntPtr mediaType)
        {
            // Free
            Disconnect();

            // Remember
            if (connector != null)
            {
                Marshal.AddRef(connector);
            }
            m_Connected = connector;

            // Clone the media type
            m_ConnectType.Dispose();
            m_ConnectType = new MediaType(mediaType);

            // Attach to raw COM interface
            m_MemPin = ComIdentity.QueryInterface(m_Connected, typeof(IMemInputPin));

            // Get the delegate for the calls - dirty but we have to avoid automatic marshalling inside the graph
            IntPtr comFunctionTable = Marshal.ReadIntPtr(m_MemPin);
            IntPtr receiveSingle    = Marshal.ReadIntPtr(comFunctionTable, 24);
            IntPtr notifyAllocator  = Marshal.ReadIntPtr(comFunctionTable, 16);

            m_MemSink    = (MediaSampleSink)Marshal.GetDelegateForFunctionPointer(receiveSingle, typeof(MediaSampleSink));
            m_NotifySink = (NotifyAllocatorSink)Marshal.GetDelegateForFunctionPointer(notifyAllocator, typeof(NotifyAllocatorSink));
        }
Example #3
0
        /// <summary>
        /// Entschlüsselt eine einzelne Quelle.
        /// </summary>
        /// <param name="service">Die Informationen zur Quelle.</param>
        /// <param name="graph">Der zu verwendende Graph.</param>
        public void Decrypt(ushort service, DataGraph graph)
        {
            // Check COM interface
            var controlPtr = ComIdentity.QueryInterface(graph.AdditionalFilters[m_filterIndex].Interface, typeof(KsControl.Interface));

            if (controlPtr != IntPtr.Zero)
            {
                using (var control = new KsControl(controlPtr))
                    control.SetServices(service);
            }
        }
        /// <summary>
        /// Versucht den DVB.NET Datenstrom direkt mit dem zugehörigen Decoder zu verbinden.
        /// </summary>
        /// <param name="decoder">Ein manuell angelegter Decoder.</param>
        /// <param name="source">Der zu verwendende Ausgang.</param>
        /// <param name="mediaType">Das verwendete Format.</param>
        /// <returns>Gesetzt, wenn die Verbindung aufgebaut wurde.</returns>
        private bool TryDirectConnect(TypedComIdentity <IBaseFilter> decoder, OutputPin source, MediaType mediaType)
        {
            // In normal cases we should directly connect to the filter so try
            var connected = false;

            // Try manual connect
            decoder.InspectAllPins(p => p.QueryDirection() == PinDirection.Input,
                                   pin =>
            {
                // Skip on error
                try
                {
                    // Get the raw interface for the media type
                    var type = mediaType.GetReference();

                    // Process
                    using (var iFace = ComIdentity.Create <IPin>(pin))
                        source.Connect(iFace.Interface, type);

                    // Did it
                    connected = true;
                }
                catch (Exception)
                {
                }

                // First pin only - even if it can not be used!
                return(false);
            });

            // Failed
            if (!connected)
            {
                return(false);
            }

            // Find the output of the decoder and render it
            decoder.InspectAllPins(p => p.QueryDirection() == PinDirection.Output,
                                   pin =>
            {
                // Create helper
                using (var pinWrapper = ComIdentity.Create <IPin>(pin))
                    DirectShowObject.Render(pinWrapper.Interface);

                // Did it
                return(false);
            });

            // Report
            return(connected);
        }
        /// <summary>
        /// Erzeugt eine neue Instanz.
        /// </summary>
        /// <typeparam name="DataType">Die Art der Daten.</typeparam>
        /// <param name="interface">Die zu verwendende Schnittstelle.</param>
        /// <returns>Eine neue Zugriffsinstanz.</returns>
        public static IKsPropertySet <DataType> Create <DataType>(IntPtr @interface)
            where DataType : struct
        {
            // None
            if (@interface == null)
            {
                return(null);
            }

            // Try to access the interface
            var com = ComIdentity.TryQueryInterface(@interface, typeof(IKsPropertySet));

            if (com == IntPtr.Zero)
            {
                return(null);
            }

            // Be safe
            try
            {
                // Create the wrapper
                using (var typed = new TypedComIdentity <IKsPropertySet>(com))
                {
                    // No longer needed to release
                    com = IntPtr.Zero;

                    // Create wrapper
                    var wrapper = typed.MarshalToManaged();
                    try
                    {
                        // Safe process
                        return(new Typed <DataType>(wrapper));
                    }
                    catch
                    {
                        // Cleanup
                        wrapper.Dispose();

                        // Forward
                        throw;
                    }
                }
            }
            finally
            {
                // Cleanup
                BDAEnvironment.Release(ref com);
            }
        }
Example #6
0
        /// <summary>
        /// Wird zur eigentlichen Steuerung der Entschlüsselung aufgerufen.
        /// </summary>
        /// <param name="pmt">Die Informationen zur Quelle.</param>
        /// <param name="reset">Gesetzt, um einen Neustart der Entschlüsselung zu erzwingen.</param>
        private void Decrypt(EPG.Tables.PMT pmt, bool reset)
        {
            // Check the interface
            var setPtr = ComIdentity.QueryInterface(m_DataGraph.TunerFilter.Interface, typeof(KsPropertySetFireDTV.Interface));

            if (setPtr == IntPtr.Zero)
            {
                return;
            }

            // Process
            using (var propertySet = new KsPropertySetFireDTV(setPtr))
                try
                {
                    // Load property identifier
                    var propSetId = PropertySetId;
                    var supported = propertySet.QuerySupported(ref propSetId, BDAProperties.SendCA);
                    if ((PropertySetSupportedTypes.Set & supported) != PropertySetSupportedTypes.Set)
                    {
                        return;
                    }

                    // Process reset
                    if (reset)
                    {
                        propertySet.Send(CACommand.CreateReset());
                    }
                    else if (pmt == null)
                    {
                        propertySet.Send(CACommand.StopDecryption());
                    }
                    else
                    {
                        propertySet.Send(CACommand.CreateDecrypt(pmt));
                    }
                }
                catch
                {
                    // Forward if not resetting
                    if (pmt != null)
                    {
                        throw;
                    }
                }
        }
        /// <summary>
        /// Ermittelt einen einzelnen Endpunkt.
        /// </summary>
        /// <param name="filter">Der zu betrachtende Filter.</param>
        /// <param name="direction">Die zu untersuchende Seite des Filters.</param>
        /// <returns>Eine Referenz auf den gewünschten Endpunkt.</returns>
        /// <exception cref="ArgumentNullException">Es wurde kein Filter angegeben.</exception>
        /// <exception cref="InvalidOperationException">Der angegeben Endpunkt existiert nicht.</exception>
        public static TypedComIdentity <IPin> GetSinglePin(this TypedComIdentity <IBaseFilter> filter, PinDirection direction)
        {
            // Validate
            if (filter == null)
            {
                throw new ArgumentNullException("filter");
            }

            // Result to use
            TypedComIdentity <IPin> result = null;

            // Use helper to check all of it
            filter.InspectAllPins(p => p.QueryDirection() == direction, p =>
            {
                // At most one hit is allowed
                if (result != null)
                {
                    // Cleanup
                    result.Dispose();

                    // Report error
                    throw new InvalidOperationException(Properties.Resources.Exception_DuplicateEndpoint);
                }

                // Remember the first one
                result = ComIdentity.Create(p);
            });

            // Ups
            if (result != null)
            {
                return(result);
            }
            else
            {
                throw new InvalidOperationException(Properties.Resources.Exception_NoEndpoint);
            }
        }
        /// <summary>
        /// Lädt einen bestimmten Decoderfilter, sofern explicit konfiguriert.
        /// </summary>
        /// <param name="moniker">Der eindeutige Name des Filters.</param>
        /// <param name="forType">Die Art des Filters - nur zur Benennung im Graphen verwendet.</param>
        /// <param name="processor">Optionale Verarbeitungsmethode für den neuen Filter.</param>
        private void LoadDecoder(string moniker, string forType, Action <TypedComIdentity <IBaseFilter> > processor = null)
        {
            // Not set
            if (string.IsNullOrEmpty(moniker))
            {
                return;
            }

            // Check it
            var name = string.Format("{0}Decoder", forType);

            // Process
            using (var decoder = ComIdentity.Create <IBaseFilter>(moniker))
            {
                // Create
                DirectShowObject.AddFilter(decoder.Interface, name);

                // Call helper
                if (processor != null)
                {
                    processor(decoder);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Aktiviert die Entschlüsselung einer Quelle.
        /// </summary>
        /// <param name="token">Informationen zur gewählten Quelle.</param>
        public PipelineResult Decrypt(DataGraph.DecryptToken token)
        {
            // Load graph
            if (token != null)
            {
                m_dataGraph = token.Pipeline.Graph;
            }

            // Get unique call identifier
            var callIdentifier = Interlocked.Increment(ref m_changeCounter);

            // See if we can do anything
            if (m_dataGraph == null)
            {
                return(PipelineResult.Continue);
            }
            if (m_filterIndex < 0)
            {
                return(PipelineResult.Continue);
            }
            if (m_filterIndex >= m_dataGraph.AdditionalFilters.Count)
            {
                return(PipelineResult.Continue);
            }

            // Deactivate if CAM reset is forbidden
            var sources   = (token == null) ? null : token.Sources;
            var noSources = (sources == null) || (sources.Length < 1);

            if ((noSources && (m_suppress != SuppressionMode.Complete)) || !m_hasBeenReset)
            {
                lock (m_deviceAccess)
                {
                    // Check COM interface
                    var controlPtr = ComIdentity.QueryInterface(m_dataGraph.AdditionalFilters[m_filterIndex].Interface, typeof(KsControl.Interface));
                    if (controlPtr == IntPtr.Zero)
                    {
                        return(PipelineResult.Continue);
                    }

                    // Process
                    using (var control = new KsControl(controlPtr))
                    {
                        // Report
                        if (BDASettings.BDATraceSwitch.Enabled)
                        {
                            Trace.WriteLine(Properties.Resources.Trace_ResetCAM, BDASettings.BDATraceSwitch.DisplayName);
                        }

                        // Reset the CAM
                        control.Reset();

                        // We did it once
                        m_hasBeenReset = true;
                    }
                }
            }

            // Start processor
            token.WaitForPMTs(
                (pmt, first) =>
            {
                // See if we are still allowed to process and do so
                lock (m_deviceAccess)
                {
                    // No longer current
                    if (Thread.VolatileRead(ref m_changeCounter) != callIdentifier)
                    {
                        return(false);
                    }

                    // Try reset
                    if (!first)
                    {
                        if (m_disableOnChange)
                        {
                            Decrypt(0, m_dataGraph);
                        }
                    }

                    // Wait for it
                    if (m_changeDelay > 0)
                    {
                        Thread.Sleep(m_changeDelay);
                    }

                    // Regular
                    Decrypt(pmt.ProgramNumber, m_dataGraph);
                }

                // Next
                return(true);
            }, sources);

            // Next
            return(PipelineResult.Continue);
        }
Example #10
0
        /// <summary>
        /// Erzeugt den zugehörigen Filter.
        /// </summary>
        /// <returns>Der gewünschte Filter.</returns>
        /// <exception cref="NotSupportedException">Der angeforderte Filter existiert.</exception>
        public TypedComIdentity <IBaseFilter> CreateFilter()
        {
            // Create system device enumerator
            var devEnum = (ICreateDevEnum)Activator.CreateInstance(System.Type.GetTypeFromCLSID(BDAEnvironment.SystemDeviceEnumeratorClassIdentifier));

            try
            {
                // Helper
                var category = Category;

                // Get the enumerator
                IEnumMoniker monikers;
                if (devEnum.CreateClassEnumerator(ref category, out monikers, 0) >= 0)
                {
                    if (monikers != null)
                    {
                        try
                        {
                            // Process all
                            for (; ;)
                            {
                                using (var array = new COMArray(1))
                                {
                                    // Load
                                    uint count;
                                    if (monikers.Next(1, array.Address, out count) != 0)
                                    {
                                        break;
                                    }
                                    if (count != 1)
                                    {
                                        break;
                                    }

                                    // Load object
                                    var moniker = array.GetObject <IMoniker>(0);
                                    try
                                    {
                                        // Check name
                                        if (string.Equals(Moniker, moniker.ReadProperty("DevicePath")))
                                        {
                                            // Create the instance
                                            var iid    = new Guid("56a86895-0ad4-11ce-b03a-0020af0ba770");
                                            var filter = moniker.BindToObject(null, null, ref iid);

                                            // Report safely
                                            try
                                            {
                                                // Construct
                                                return(ComIdentity.Create((IBaseFilter)filter));
                                            }
                                            catch
                                            {
                                                // Cleanup
                                                BDAEnvironment.Release(ref filter);

                                                // Forward
                                                throw;
                                            }
                                        }
                                    }
                                    finally
                                    {
                                        // Release
                                        BDAEnvironment.Release(ref moniker);
                                    }
                                }
                            }
                        }
                        finally
                        {
                            // Cleanup
                            BDAEnvironment.Release(ref monikers);
                        }
                    }
                }
            }
            finally
            {
                // Back to COM
                BDAEnvironment.Release(ref devEnum);
            }

            // Not found
            throw new NotSupportedException(string.Format(Properties.Resources.Exception_BadFilter, this));
        }
        /// <summary>
        /// Erzuegt den Anzeigegraphen.
        /// </summary>
        /// <param name="mpeg4">Gesetzt für H.264 Bildinformationen - ansonsten wird MPEG-2 erwartet.</param>
        /// <param name="ac3">Gesetzt für AC3 Toninformationen - ansonsten wird MP2 erwartet.</param>
        public void Show(bool mpeg4, bool ac3)
        {
            // Startup
            bool firstCall = PrepareShow();

            // Leave fullscreen before stopping graph
            bool fullscreen = FullScreen;

            if (fullscreen)
            {
                FullScreen = false;
            }

            // Stop the graph
            Stop();

            // Forget the clock
            DisposeClock();

            // Remove all filters not created by us
            var noRemove = new HashSet <IntPtr>(m_Filters.Values.Select(f => f.Interface));

            ((IFilterGraph)m_Graph).InspectFilters(filter =>
            {
                // Create report structure
                var info = new FilterInfo();

                // Load it
                filter.QueryFilterInfo(ref info);

                // Forget about graph
                BDAEnvironment.Release(ref info.Graph);

                // Process using raw interfaces
                using (var id = ComIdentity.Create(filter))
                    if (!noRemove.Contains(id.Interface))
                    {
                        try
                        {
                            // Repoert
                            if (DirectShowTraceSwitch.Enabled)
                            {
                                Trace.WriteLine(string.Format(Properties.Resources.Trace_RemoveFilter, info.Name), DirectShowTraceSwitch.DisplayName);
                            }

                            // Process
                            DirectShowObject.RemoveFilter(id.Interface);
                        }
                        catch (Exception e)
                        {
                            // Report
                            Trace.WriteLine(string.Format(Properties.Resources.Trace_Exception_RemoveFilter, info.Name, e.Message), DirectShowTraceSwitch.DisplayName);
                        }
                    }
            });

            // Create media types
            var videoType = CreateVideoType(mpeg4, UseCyberlink);
            var audioType = CreateAudioType(ac3);

            // Configure injection pins
            InjectorFilter.SetAudioType(audioType);
            InjectorFilter.SetVideoType(videoType);

            // Helper
            var audioConnected = false;
            var videoConnected = false;

            // Pre-loaded decoders
            LoadDecoder(mpeg4 ? H264Decoder : MPEG2Decoder, mpeg4 ? "HDTV-Video" : "SDTV-Video", decoder => videoConnected = TryDirectConnect(decoder, InjectorFilter.VideoPin, videoType));
            LoadDecoder(ac3 ? AC3Decoder : MP2Decoder, ac3 ? "AC3-Audio" : "MP2-Audio", decoder => audioConnected          = TryDirectConnect(decoder, InjectorFilter.AudioPin, audioType));

            // Create display
            if (!audioConnected)
            {
                DirectShowObject.Render(InjectorFilter.AudioPin.Interface);
            }
            if (!videoConnected)
            {
                DirectShowObject.Render(InjectorFilter.VideoPin.Interface);
            }

            // Show for the first time
            var vmr = VMR;

            if (firstCall)
            {
                if (vmr != null)
                {
                    if (m_VideoWindow != null)
                    {
                        // Respect window settings
                        vmr.ClippingWindow = m_VideoWindow;
                        vmr.AdjustSize(m_VideoWindow);
                    }
                }
            }

            // Use it
            m_Clock = new NoMarshalComObjects.ReferenceClock(Activator.CreateInstance(Type.GetTypeFromCLSID(Constants.CLSID_SystemClock)), true);

            // Attach to graph
            GraphAsFilter.SetSyncSource(m_Clock.ComInterface);

            // Time to restart the graph
            Run();

            // Reinstall volume
            if (m_LastVolume.HasValue)
            {
                Volume = m_LastVolume.Value;
            }

            // Reinstall picture parameters
            if (m_PictureParameters != null)
            {
                if (vmr != null)
                {
                    m_PictureParameters.Update(vmr);
                }
            }

            // Back to full screen mode
            if (fullscreen)
            {
                FullScreen = true;
            }
        }