protected override bool EnumerateStreams(bool forceRefresh) { //FIXME: TSReader only offers Audio in IAMStreamSelect, it would be cleaner to expose subs as well. bool refreshed = base.EnumerateStreams(forceRefresh); if (refreshed) { // If base class has refreshed the stream infos, then update the subtitle streams. ISubtitleStream subtitleStream = _sourceFilter as ISubtitleStream; int count = 0; if (subtitleStream != null) { _streamInfoSubtitles = new StreamInfoHandler(); subtitleStream.GetSubtitleStreamCount(ref count); if (count > 0) { StreamInfo subStream = new StreamInfo(null, NO_STREAM_INDEX, NO_SUBTITLES, 0); _streamInfoSubtitles.AddUnique(subStream); } for (int i = 0; i < count; ++i) { //FIXME: language should be passed back also as LCID SubtitleLanguage language = new SubtitleLanguage(); int type = 0; subtitleStream.GetSubtitleStreamLanguage(i, ref language); subtitleStream.GetSubtitleStreamType(i, ref type); int lcid = LookupLcidFromName(language.lang); string name = type == 0 ? String.Format("{0} (DVB)", language.lang) : String.Format("{0} (Teletext)", language.lang); StreamInfo subStream = new StreamInfo(null, i, name, lcid); _streamInfoSubtitles.AddUnique(subStream); } } } return refreshed; }
protected override bool EnumerateStreams(bool forceRefresh) { //FIXME: TSReader only offers Audio in IAMStreamSelect, it would be cleaner to expose subs as well. bool refreshed = base.EnumerateStreams(forceRefresh); if (refreshed) { // If base class has refreshed the stream infos, then update the subtitle streams. ISubtitleStream subtitleStream = _sourceFilter as ISubtitleStream; int count = 0; if (subtitleStream != null) { _streamInfoSubtitles = new StreamInfoHandler(); subtitleStream.GetSubtitleStreamCount(ref count); if (count > 0) { StreamInfo subStream = new StreamInfo(null, NO_STREAM_INDEX, NO_SUBTITLES, 0); _streamInfoSubtitles.AddUnique(subStream); } for (int i = 0; i < count; ++i) { //FIXME: language should be passed back also as LCID SubtitleLanguage language = new SubtitleLanguage(); subtitleStream.GetSubtitleStreamLanguage(i, ref language); int lcid = LookupLcidFromName(language.lang); // Note: the "type" is no longer considered in MP1 code as well, so I guess DVBSub3 only supports Bitmap subs at all. string name = language.lang; StreamInfo subStream = new StreamInfo(null, i, name, lcid); _streamInfoSubtitles.AddUnique(subStream); } } } return refreshed; }
/// <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)); if (mediaType == null) { ServiceRegistration.Get<ILogger>().Warn("Stream {0}: Could not determine MediaType!", i); continue; } 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; }