/// <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); }
/// <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); }