Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <summary>
        /// Enumerates streams from video (audio, subtitles).
        /// </summary>
        /// <param name="forceRefresh">Force refresh</param>
        /// <returns><c>true</c> if information has been changed.</returns>
        protected virtual bool EnumerateStreams(bool forceRefresh)
        {
            if (_graphBuilder == null || !_initialized)
            {
                return(false);
            }

            StreamInfoHandler audioStreams;
            StreamInfoHandler subtitleStreams;
            StreamInfoHandler titleStreams;

            lock (SyncObj)
            {
                audioStreams    = _streamInfoAudio;
                subtitleStreams = _streamInfoSubtitles;
                titleStreams    = _streamInfoTitles;
            }
            if (forceRefresh || audioStreams == null || subtitleStreams == null || titleStreams == null)
            {
                audioStreams    = new StreamInfoHandler();
                subtitleStreams = new StreamInfoHandler();
                titleStreams    = new StreamInfoHandler();

                // Release stream selectors
                ReleaseStreamSelectors();
                _streamSelectors = FilterGraphTools.FindFiltersByInterface <IAMStreamSelect>(_graphBuilder);
                foreach (IAMStreamSelect streamSelector in _streamSelectors)
                {
                    FilterInfo fi = FilterGraphTools.QueryFilterInfoAndFree(((IBaseFilter)streamSelector));
                    int        streamCount;
                    streamSelector.Count(out streamCount);

                    for (int i = 0; i < streamCount; ++i)
                    {
                        IntPtr pp_punk            = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        IntPtr pp_object          = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        IntPtr pp_name            = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        IntPtr pp_groupNumber     = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        IntPtr pp_lcid            = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        IntPtr pp_selectInfoFlags = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        IntPtr pp_mediaType       = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
                        int    hr = streamSelector.Info(i, pp_mediaType, pp_selectInfoFlags, pp_lcid, pp_groupNumber, pp_name, pp_punk, pp_object);
                        new HRESULT(hr).Throw();

                        // We get a pointer to pointer for a structure.
                        AMMediaType mediaType   = (AMMediaType)Marshal.PtrToStructure(Marshal.ReadIntPtr(pp_mediaType), typeof(AMMediaType));
                        int         groupNumber = Marshal.ReadInt32(pp_groupNumber);
                        int         lcid        = Marshal.ReadInt32(pp_lcid);
                        string      name        = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(pp_name));

                        // If stream does not contain a LCID, try a lookup from stream name.
                        if (lcid == 0)
                        {
                            lcid = LookupLcidFromName(name);
                        }

                        ServiceRegistration.Get <ILogger>().Debug("Stream {4}|{0}: MajorType {1}; Name {2}; PWDGroup: {3}; LCID: {5}",
                                                                  i, mediaType.majorType, name, groupNumber, fi.achName, lcid);

                        StreamInfo currentStream = new StreamInfo(streamSelector, i, name, lcid);
                        switch ((StreamGroup)groupNumber)
                        {
                        case StreamGroup.Video:
                            break;

                        case StreamGroup.Audio:
                            if (mediaType.majorType == MediaType.AnalogAudio || mediaType.majorType == MediaType.Audio)
                            {
                                String streamName = name.Trim();
                                String streamAppendix;
                                if (!CodecHandler.MediaSubTypes.TryGetValue(mediaType.subType, out streamAppendix))
                                {
                                    streamAppendix = string.Empty;
                                }

                                // if audio information is available via WaveEx format, query the channel count
                                if (mediaType.formatType == FormatType.WaveEx && mediaType.formatPtr != IntPtr.Zero)
                                {
                                    WaveFormatEx waveFormatEx = (WaveFormatEx)Marshal.PtrToStructure(mediaType.formatPtr, typeof(WaveFormatEx));
                                    currentStream.ChannelCount = waveFormatEx.nChannels;
                                    streamAppendix             = String.Format("{0} {1}ch", streamAppendix, currentStream.ChannelCount);
                                }

                                if (!string.IsNullOrEmpty(streamAppendix))
                                {
                                    currentStream.Name = String.Format("{0} ({1})", streamName, streamAppendix);
                                }

                                audioStreams.AddUnique(currentStream);
                            }
                            break;

                        case StreamGroup.Subtitle:
                        {
                            currentStream.IsAutoSubtitle = currentStream.Name.ToLowerInvariant().Contains(FORCED_SUBTITLES);
                            subtitleStreams.AddUnique(currentStream, true);
                        }
                        break;

                        case StreamGroup.VsFilterSubtitle:
                        case StreamGroup.VsFilterSubtitleOptions:
                        case StreamGroup.DirectVobSubtitle:
                            subtitleStreams.AddUnique(currentStream, true);
                            break;

                        case StreamGroup.MatroskaEdition: // This is a MKV Edition handled by Haali splitter
                            titleStreams.AddUnique(currentStream, true);
                            break;
                        }
                        // Free MediaType and references
                        DsUtils.FreeAMMediaType(mediaType);
                        Marshal.FreeHGlobal(pp_punk);
                        Marshal.FreeHGlobal(pp_object);
                        Marshal.FreeHGlobal(pp_name);
                        Marshal.FreeHGlobal(pp_groupNumber);
                        Marshal.FreeHGlobal(pp_lcid);
                        Marshal.FreeHGlobal(pp_selectInfoFlags);
                        Marshal.FreeHGlobal(pp_mediaType);
                    }
                }

                SetPreferedAudio_intern(ref audioStreams, false);
                SetPreferredSubtitle_intern(ref subtitleStreams);
                lock (SyncObj)
                {
                    _streamInfoAudio     = audioStreams;
                    _streamInfoSubtitles = subtitleStreams;
                    _streamInfoTitles    = titleStreams;
                }
                return(true);
            }
            return(false);
        }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
        /// <summary>
        /// Enumerates streams from video (audio, subtitles).
        /// </summary>
        /// <param name="forceRefresh">Force refresh</param>
        /// <returns><c>true</c> if information has been changed.</returns>
        protected virtual bool EnumerateStreams(bool forceRefresh)
        {
            if (_graphBuilder == null || !_initialized)
            {
                return(false);
            }

            StreamInfoHandler audioStreams;
            StreamInfoHandler subtitleStreams;
            StreamInfoHandler titleStreams;

            lock (SyncObj)
            {
                audioStreams    = _streamInfoAudio;
                subtitleStreams = _streamInfoSubtitles;
                titleStreams    = _streamInfoTitles;
            }
            if (forceRefresh || audioStreams == null || subtitleStreams == null || titleStreams == null)
            {
                audioStreams    = new StreamInfoHandler();
                subtitleStreams = new StreamInfoHandler();
                titleStreams    = new StreamInfoHandler();

                // Release stream selectors
                ReleaseStreamSelectors();
                _streamSelectors = FilterGraphTools.FindFiltersByInterface <IAMStreamSelect>(_graphBuilder);
                foreach (IAMStreamSelect streamSelector in _streamSelectors)
                {
                    FilterInfo fi = FilterGraphTools.QueryFilterInfoAndFree(((IBaseFilter)streamSelector));
                    int        streamCount;
                    streamSelector.Count(out streamCount);

                    for (int i = 0; i < streamCount; ++i)
                    {
                        AMMediaType             mediaType;
                        AMStreamSelectInfoFlags selectInfoFlags;
                        int    groupNumber, lcid;
                        string name;
                        object pppunk, ppobject;

                        streamSelector.Info(i, out mediaType, out selectInfoFlags, out lcid, out groupNumber, out name, out pppunk, out ppobject);

                        // If stream does not contain a LCID, try a lookup from stream name.
                        if (lcid == 0)
                        {
                            lcid = LookupLcidFromName(name);
                        }

                        ServiceRegistration.Get <ILogger>().Debug("Stream {4}|{0}: MajorType {1}; Name {2}; PWDGroup: {3}; LCID: {5}",
                                                                  i, mediaType.majorType, name, groupNumber, fi.achName, lcid);

                        StreamInfo currentStream = new StreamInfo(streamSelector, i, name, lcid);
                        switch ((StreamGroup)groupNumber)
                        {
                        case StreamGroup.Video:
                            break;

                        case StreamGroup.Audio:
                            if (mediaType.majorType == MediaType.AnalogAudio || mediaType.majorType == MediaType.Audio)
                            {
                                String streamName = name.Trim();
                                String streamAppendix;
                                if (!CodecHandler.MediaSubTypes.TryGetValue(mediaType.subType, out streamAppendix))
                                {
                                    streamAppendix = string.Empty;
                                }

                                // if audio information is available via WaveEx format, query the channel count
                                if (mediaType.formatType == FormatType.WaveEx && mediaType.formatPtr != IntPtr.Zero)
                                {
                                    WaveFormatEx waveFormatEx = (WaveFormatEx)Marshal.PtrToStructure(mediaType.formatPtr, typeof(WaveFormatEx));
                                    currentStream.ChannelCount = waveFormatEx.nChannels;
                                    streamAppendix             = String.Format("{0} {1}ch", streamAppendix, currentStream.ChannelCount);
                                }

                                if (!string.IsNullOrEmpty(streamAppendix))
                                {
                                    currentStream.Name = String.Format("{0} ({1})", streamName, streamAppendix);
                                }

                                audioStreams.AddUnique(currentStream);
                            }
                            break;

                        case StreamGroup.Subtitle:
                        case StreamGroup.DirectVobSubtitle:
                            subtitleStreams.AddUnique(currentStream, true);
                            break;

                        case StreamGroup.MatroskaEdition: // This is a MKV Edition handled by Haali splitter
                            titleStreams.AddUnique(currentStream, true);
                            break;
                        }
                        // Free MediaType and references
                        FilterGraphTools.FreeAMMediaType(mediaType);
                    }
                }

                lock (SyncObj)
                {
                    _streamInfoAudio     = audioStreams;
                    _streamInfoSubtitles = subtitleStreams;
                    _streamInfoTitles    = titleStreams;
                }
                return(true);
            }
            return(false);
        }