Example #1
0
        /// <summary>
        /// Crée le filtre "File Splitter (demuxer)" et l'ajoute au graphe.
        /// </summary>
        /// <param name="graph">Le graphe.</param>
        /// <param name="filtersConfig">La configuration pour ce fichier.</param>
        /// <param name="sourceOutputPin">Le pin de sortie de la source.</param>
        /// <param name="parserOutputAudioPin">Le pin de sortie audio.</param>
        /// <param name="parserOutputVideoPin">Le pin de sortie vidéo</param>
        /// <returns>Le filtre File SPlitter.</returns>
        internal static IBaseFilter CreateSplitterFilter(IGraphBuilder graph, ExtensionFiltersSource filtersConfig, IPin sourceOutputPin,
                                                         out IPin parserOutputAudioPin, out IPin parserOutputVideoPin)
        {
            Type        filterType   = null;
            IBaseFilter parserFilter = null;

            FilterSource splitterSource = filtersConfig.Splitter;

            if (splitterSource.SourceType != FilterSourceTypeEnum.External)
            {
                throw new InvalidOperationException("The Splitter Filter Source cannot be Automatic");
            }

            CreateFilter(splitterSource.ExternalCLSID, splitterSource.Name, ref filterType, ref parserFilter);

            IPin parserInputPin = DsFindPin.ByDirection(parserFilter, PinDirection.Input, 0);

            int hr = graph.AddFilter(parserFilter, splitterSource.Name);

            DsError.ThrowExceptionForHR(hr);

            // Connectiong FileSource et Splitter
            hr = graph.Connect(sourceOutputPin, parserInputPin);
            DsError.ThrowExceptionForHR(hr);

            SafeRelease(sourceOutputPin);
            SafeRelease(parserInputPin);

            // Pins de sortie

            parserOutputAudioPin = DsFindPin.ByDirection(parserFilter, PinDirection.Output, 0);
            parserOutputVideoPin = DsFindPin.ByDirection(parserFilter, PinDirection.Output, 1);

            // Only video or audio
            if (parserOutputVideoPin == null)
            {
                parserOutputVideoPin = parserOutputAudioPin;
                parserOutputAudioPin = null;
            }

            parserOutputVideoPin.EnumMediaTypes(out IEnumMediaTypes enumMediaTypes);
            AMMediaType[] mts = { null };
            while (enumMediaTypes.Next(1, mts, IntPtr.Zero) == 0)
            {
                if (mts[0].majorType != MediaType.Video)
                {
                    // Invert in case it's not the appropriate media type
                    IPin temp = parserOutputAudioPin;
                    parserOutputAudioPin = parserOutputVideoPin;
                    parserOutputVideoPin = temp;
                    break;
                }
            }

            return(parserFilter);
        }
Example #2
0
        /// <summary>
        /// Obtient les paramètres pour un fichier.
        /// </summary>
        /// <param name="filtersConfiguration">Tous les paramètres.</param>
        /// <param name="fileSource">Le chemin vers le fichier vidéo.</param>
        /// <returns>Les paramètres de filtre pour le fichier.</returns>
        internal static ExtensionFiltersSource GetExtensionFiltersSource(FiltersConfiguration filtersConfiguration, string fileSource)
        {
            string fileExtension = Path.GetExtension(fileSource);
            ExtensionFiltersSource extensionFiltersSources = filtersConfiguration[fileExtension];

            if (extensionFiltersSources == null)
            {
                throw new InvalidOperationException("There is no filter for this file type");
            }
            return(extensionFiltersSources);
        }
Example #3
0
        /// <summary>
        /// Crée le graphe DirectShow
        /// </summary>
        void SetupGraph()
        {
            FiltersConfiguration filtersConfiguration = GraphHelper.GetFiltersConfiguration();

            if (filtersConfiguration == null)
            {
                throw new InvalidOperationException("The filters are not configured");
            }

            //System.IO.FileStream fs = null;

            try
            {
                ExtensionFiltersSource extensionFiltersSources = GraphHelper.GetExtensionFiltersSource(filtersConfiguration, _sourceFilePath);

                try
                {
                    /* Creates the GraphBuilder COM object */
                    _graph = new FilterGraphNoThread() as IGraphBuilder;

                    if (_graph == null)
                    {
                        throw new Exception("Could not create a graph");
                    }

                    //if (_graphLogLocation != null)
                    //{
                    //    fs = System.IO.File.Create(_graphLogLocation);
                    //    int r = _graph.SetLogFile(fs.Handle);
                    //}

                    //
                    // Creating FileSource filter
                    //
                    IBaseFilter sourceFilter = GraphHelper.CreateLAVSplitterSourceFilter(_graph, _sourceFilePath, out IPin parserAudioOutputPin, out IPin parserVideoOutputPin);

                    //
                    // Creating renderer
                    //
                    Type        videoRendererFilterType = null;
                    IBaseFilter videoRenderer           = null;
                    GraphHelper.CreateFilter(NULL_RENDERER, "Null Renderer", ref videoRendererFilterType, ref videoRenderer);
                    int hr = _graph.AddFilter(videoRenderer, "Null Renderer");
                    DsError.ThrowExceptionForHR(hr);

                    IPin videoRendererInputPin = DsFindPin.ByDirection(videoRenderer, PinDirection.Input, 0);

                    //
                    // Creating Video filter
                    //

                    // Connection du sample Grabber
                    IBaseFilter sampleGrabberFilter = (IBaseFilter)_sampleGrabber;
                    hr = _graph.AddFilter(sampleGrabberFilter, "Sample Grabber");
                    DsError.ThrowExceptionForHR(hr);
                    IPin sampleGrabberInputPin = DsFindPin.ByDirection(sampleGrabberFilter, PinDirection.Input, 0);
                    IPin sampleGrabberOuputPin = DsFindPin.ByDirection(sampleGrabberFilter, PinDirection.Output, 0);

                    //Insertion du Color Space Converter
                    Type        filterType          = null;
                    IBaseFilter colorSpaceConverter = null;
                    GraphHelper.CreateFilter(GraphHelper.CLSID_COLOR_SPACE_CONVERTER, GraphHelper.COLOR_SPACE_CONVERTER_FRIENDLYNAME, ref filterType, ref colorSpaceConverter);
                    hr = _graph.AddFilter(colorSpaceConverter, GraphHelper.COLOR_SPACE_CONVERTER_FRIENDLYNAME);
                    DsError.ThrowExceptionForHR(hr);
                    IPin colorSpaceConverterInputPin = DsFindPin.ByDirection(colorSpaceConverter, PinDirection.Input, 0);
                    GraphHelper.ConnectSplitterAndRendererWithDecoder(_graph, extensionFiltersSources, parserVideoOutputPin, colorSpaceConverterInputPin);
                    IPin colorSpaceConverterOutputPin = DsFindPin.ByDirection(colorSpaceConverter, PinDirection.Output, 0);
                    hr = _graph.ConnectDirect(colorSpaceConverterOutputPin, sampleGrabberInputPin, null);
                    DsError.ThrowExceptionForHR(hr);

                    hr = _graph.Connect(sampleGrabberOuputPin, videoRendererInputPin);
                    DsError.ThrowExceptionForHR(hr);

                    // Removes the clock to run the graph as fast as possible
                    ((IMediaFilter)_graph).SetSyncSource(null);

                    GraphHelper.SafeRelease(parserAudioOutputPin);
                    GraphHelper.SafeRelease(parserVideoOutputPin);
                    GraphHelper.SafeRelease(videoRendererInputPin);
                    GraphHelper.SafeRelease(sampleGrabberInputPin);
                    GraphHelper.SafeRelease(sampleGrabberOuputPin);
                    GraphHelper.SafeRelease(colorSpaceConverterInputPin);
                    GraphHelper.SafeRelease(colorSpaceConverterOutputPin);

                    _mediaSeeking = _graph as IMediaSeeking;
                    _mediaControl = _graph as IMediaControl;
                    _mediaEvent   = _graph as IMediaEventEx;

                    /* Attempt to set the time format */
                    hr = _mediaSeeking.SetTimeFormat(TimeFormat.MediaTime);
                    DsError.ThrowExceptionForHR(hr);
                }
                catch (Exception ex)
                {
                    this.TraceError(ex, ex.Message);

                    /* This exection will happen usually if the media does
                     * not exist or could not open due to not having the
                     * proper filters installed */
                    FreeResources();
                }
            }
            finally
            {
                /*if (_graphLogLocation != null && fs != null)
                 *  fs.Close();*/
            }
        }
Example #4
0
        /// <summary>
        /// Connecte le File Splitter et le renderer vidéo en créant le décodeur vidéo.
        /// </summary>
        /// <param name="graph">Le graphe.</param>
        /// <param name="filtersConfig">La configuration pour ce fichier.</param>
        /// <param name="parserOutputVideoPin">Le pin de sortie vidéo</param>
        /// <param name="videoRendererInputPin">Le pin d'entrée du Renderer.</param>
        internal static void ConnectSplitterAndRendererWithDecoder(IGraphBuilder graph, ExtensionFiltersSource filtersConfig,
                                                                   IPin parserOutputVideoPin, IPin videoRendererInputPin)
        {
            FilterSource videoFilterSource = filtersConfig.VideoDecoder;

            switch (videoFilterSource.SourceType)
            {
            case FilterSourceTypeEnum.Auto:

                int hr = graph.Connect(parserOutputVideoPin, videoRendererInputPin);
                DsError.ThrowExceptionForHR(hr);

                break;

            case FilterSourceTypeEnum.External:
                if (new Guid(videoFilterSource.ExternalCLSID) == new Guid(CLSID_VIDEO_DECODER_DMO))
                {
                    // The DMO filter is handled differently
                    DMOWrapperFilter  dmoFilter = new DMOWrapperFilter();
                    IDMOWrapperFilter wrapper   = (IDMOWrapperFilter)dmoFilter;
                    hr = wrapper.Init(new Guid(CLSID_VIDEO_DECODER_DMO), DirectShowLib.DMO.DMOCategory.VideoDecoder);

                    DsError.ThrowExceptionForHR(hr);

                    if (dmoFilter is IBaseFilter decoderFilter)
                    {
                        hr = graph.AddFilter(decoderFilter, "WMVideo Decoder DMO");
                        DsError.ThrowExceptionForHR(hr);

                        IPin wmvDecoderInputPin = DsFindPin.ByDirection(decoderFilter, PinDirection.Input, 0);
                        hr = graph.ConnectDirect(parserOutputVideoPin, wmvDecoderInputPin, null);
                        DsError.ThrowExceptionForHR(hr);

                        IPin wmvDecoderOutputPin = DsFindPin.ByDirection(decoderFilter, PinDirection.Output, 0);
                        hr = graph.ConnectDirect(wmvDecoderOutputPin, videoRendererInputPin, null);
                        DsError.ThrowExceptionForHR(hr);

                        SafeRelease(wmvDecoderInputPin);
                        SafeRelease(wmvDecoderOutputPin);
                    }
                    else
                    {
                        wrapper = null;
                        SafeRelease(dmoFilter);
                        dmoFilter = null;
                    }
                }
                else
                {
                    Type        filterType     = null;
                    IBaseFilter externalFilter = null;

                    CreateFilter(videoFilterSource.ExternalCLSID, videoFilterSource.Name, ref filterType, ref externalFilter);

                    hr = graph.AddFilter(externalFilter, videoFilterSource.Name);
                    DsError.ThrowExceptionForHR(hr);

                    IPin externalDecoderInputPin = DsFindPin.ByDirection(externalFilter, PinDirection.Input, 0);
                    hr = graph.ConnectDirect(parserOutputVideoPin, externalDecoderInputPin, null);
                    DsError.ThrowExceptionForHR(hr);

                    IPin externalDecoderOutputPin = DsFindPin.ByDirection(externalFilter, PinDirection.Output, 0);
                    hr = graph.ConnectDirect(externalDecoderOutputPin, videoRendererInputPin, null);
                    DsError.ThrowExceptionForHR(hr);

                    SafeRelease(externalDecoderInputPin);
                    SafeRelease(externalDecoderOutputPin);
                }


                break;

            default:
                throw new ArgumentOutOfRangeException($"{nameof(videoFilterSource)}.{nameof(FilterSource.SourceType)}");
            }
        }
Example #5
0
        /// <summary>
        /// Parse la configuration DirectShow
        /// </summary>
        public static FiltersConfiguration Parse()
        {
            try
            {
                FiltersConfigurationSection configSection = FiltersConfigurationSection.GetConfiguration();

                FiltersConfiguration conf = new FiltersConfiguration();

                foreach (ExtensionElement extension in configSection.Extensions)
                {
                    var ext = new ExtensionFiltersSource()
                    {
                        Extension     = extension.Extension,
                        MinSpeedRatio = extension.MinSpeedRatio,
                        MaxSpeedRatio = extension.MaxSpeedRatio,
                        Splitter      = new FilterSource
                        {
                            Name          = extension.Splitter.Name,
                            SourceType    = extension.Splitter.SourceType,
                            ExternalCLSID = extension.Splitter.ExternalCLSID,
                        },
                        VideoDecoder = new FilterSource
                        {
                            Name          = extension.VideoDecoder.Name,
                            SourceType    = extension.VideoDecoder.SourceType,
                            ExternalCLSID = extension.VideoDecoder.ExternalCLSID,
                        },
                        AudioDecoder = new FilterSource
                        {
                            Name          = extension.AudioDecoder.Name,
                            SourceType    = extension.AudioDecoder.SourceType,
                            ExternalCLSID = extension.AudioDecoder.ExternalCLSID,
                        }
                    };

                    conf[ext.Extension] = ext;
                }

                // Filtres par défaut, minimum requis
                if (conf[".wmv"] == null)
                {
                    conf[".wmv"] = new ExtensionFiltersSource
                    {
                        Extension = ".wmv",
                        Splitter  = new FilterSource
                        {
                            Name          = "GDCL WMV Splitter",
                            SourceType    = FilterSourceTypeEnum.External,
                            ExternalCLSID = CLSID_WMV_SPLITTER,
                        },
                        VideoDecoder = new FilterSource
                        {
                            Name          = "LAV Video Decoder",
                            SourceType    = FilterSourceTypeEnum.External,
                            ExternalCLSID = CLSID_LAV_VIDEO_DECODER,
                        },
                        AudioDecoder = new FilterSource
                        {
                            Name       = "Auto Audio Decoder",
                            SourceType = FilterSourceTypeEnum.Auto,
                        }
                    };
                }

                // Vérification de l'exactitude des valeurs
                if (conf.Select(e => e.Extension).GroupBy(e => e).Any(g => g.Count() > 2))
                {
                    throw new ConfigurationErrorsException("Les extensions configurées doivent être uniques.");
                }

                foreach (var e in conf)
                {
                    if (e.Splitter.SourceType == FilterSourceTypeEnum.Auto)
                    {
                        throw new ConfigurationErrorsException("Le splitter ne peut pas être Auto");
                    }

                    if ((e.MinSpeedRatio.HasValue && !e.MaxSpeedRatio.HasValue) ||
                        (!e.MinSpeedRatio.HasValue && e.MaxSpeedRatio.HasValue))
                    {
                        throw new ConfigurationErrorsException("Les vitesses de lecture doivent être toutes les deux définies");
                    }

                    if (e.MinSpeedRatio.HasValue && e.MaxSpeedRatio.HasValue && e.MinSpeedRatio.Value > e.MaxSpeedRatio.Value)
                    {
                        throw new ConfigurationErrorsException("Les vitesses de lecture sont incorrectes");
                    }

                    var sources = new FilterSource[]
                    {
                        e.Splitter,
                        e.AudioDecoder,
                        e.VideoDecoder
                    };

                    foreach (var source in sources)
                    {
                        if (source.SourceType == FilterSourceTypeEnum.External && string.IsNullOrEmpty(source.ExternalCLSID))
                        {
                            throw new ConfigurationErrorsException("Une source externe doit être accompagnée d'un CLSID externe");
                        }

                        if (source.SourceType == FilterSourceTypeEnum.Auto && !string.IsNullOrEmpty(source.ExternalCLSID))
                        {
                            throw new ConfigurationErrorsException("Une source auto ne doit pas être accompagnée d'un CLSID externe");
                        }
                    }
                }

                return(conf);
            }
            catch (ConfigurationErrorsException ex)
            {
                TraceManager.TraceError(ex, "Erreur de configuration");
                MessageBox.Show(Resources.LocalizationResources.Error_Configuration_Filters, Resources.LocalizationResources.Error, MessageBoxButton.OK, MessageBoxImage.Error);
                return(null);
            }
            catch (Exception e)
            {
                TraceManager.TraceError(e, "Erreur lors de l'initialisation de la configuration des filtres");
                MessageBox.Show(Resources.LocalizationResources.Exception_GenericMessage, Resources.LocalizationResources.Error, MessageBoxButton.OK, MessageBoxImage.Error);
                return(null);
            }
        }