private void SetPreferredSubtitle_intern(ref BaseStreamInfoHandler subtitleStreams) { if (subtitleStreams == null) { return; } VideoSettings settings = ServiceRegistration.Get <ISettingsManager>().Load <VideoSettings>() ?? new VideoSettings(); // first try to find a stream by it's exact LCID. StreamInfo streamInfo = subtitleStreams.FindStream(settings.PreferredSubtitleLanguage) ?? subtitleStreams.FindSimilarStream(settings.PreferredSubtitleStreamName); if (streamInfo == null || !settings.EnableMpcSubtitlesEngine) { // auto-activate forced subtitles StreamInfo forced = subtitleStreams.FindForcedStream(); if (forced != null) { subtitleStreams.EnableStream(forced.Name); } else { StreamInfo noSubtitleStream = subtitleStreams.FindSimilarStream(GetNoSubsName()); if (noSubtitleStream != null) { subtitleStreams.EnableStream(noSubtitleStream.Name); } } } else { subtitleStreams.EnableStream(streamInfo.Name); } }
/// <summary> /// Release all COM object references to IAMStreamSelect instances. /// </summary> protected virtual void ReleaseStreamSelectors() { // Release all existing stream selector references if (_streamSelectors != null) { foreach (IAMStreamSelect streamSelector in _streamSelectors) { FilterGraphTools.TryReleaseComObject(streamSelector); } } _streamSelectors = null; _streamInfoAudio = null; _streamInfoSubtitles = null; _streamInfoTitles = null; }
/// <summary> /// Release all COM object references to IAMStreamSelect instances. /// </summary> protected virtual void ReleaseStreamSelectors() { // Release all existing stream selector references if (_streamSelectors != null) { foreach (IAMStreamSelect streamSelector in _streamSelectors) { if (Marshal.IsComObject(streamSelector)) { Marshal.ReleaseComObject(streamSelector); } } } _streamSelectors = null; _streamInfoAudio = null; _streamInfoSubtitles = null; _streamInfoTitles = null; }
/// <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); } BaseStreamInfoHandler audioStreams; BaseStreamInfoHandler titleStreams; lock (SyncObj) { audioStreams = _streamInfoAudio; titleStreams = _streamInfoTitles; } if (forceRefresh || audioStreams == null || titleStreams == null) { audioStreams = new StreamInfoHandler(); titleStreams = new StreamInfoHandler(); // Release stream selectors ReleaseStreamSelectors(); _streamSelectors = FilterGraphTools.FindFiltersByInterface <IAMStreamSelect>(_graphBuilder); _hasEdition = false; // To decide for stream enumerations in SetTitle 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.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.Video: // Used for multiple video streams inside a single MKV, i.e. to have both 2D and 3D video in same file titleStreams.AddUnique(currentStream, true); break; case StreamGroup.MatroskaEdition: // This is a MKV Edition handled by Haali splitter titleStreams.AddUnique(currentStream, true); _hasEdition = true; // To decide for stream enumerations in SetTitle 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); } } // MPC engine uses it's own way to enumerate subs. BaseStreamInfoHandler subtitleStreams = new MpcStreamInfoHandler(); SetPreferredSubtitle_intern(ref subtitleStreams); SetPreferedAudio_intern(ref audioStreams, false); lock (SyncObj) { _streamInfoAudio = audioStreams; _streamInfoSubtitles = subtitleStreams; _streamInfoTitles = titleStreams; } return(true); } return(false); }
private void SetPreferedAudio_intern(ref BaseStreamInfoHandler audioStreams, bool useFirstAsDefault) { if (audioStreams == null || audioStreams.Count == 0) { return; } VideoSettings settings = ServiceRegistration.Get <ISettingsManager>().Load <VideoSettings>(); // When multiple streams are available, we select the stream by channel count preference (PreferMultiChannelAudio). Predicate <StreamInfo> channelCountPreference; if (settings.PreferMultiChannelAudio) { channelCountPreference = (a => a.ChannelCount > 2); // Prefer more then stereo (usually 6ch) } else { channelCountPreference = (a => a.ChannelCount <= 2); // Stereo or even mono } // Check if there are multiple audio streams for the PreferredAudioLanguage. int preferredAudioLCID = settings.PreferredAudioLanguage; List <StreamInfo> streamsForLCID = audioStreams.ToList().FindAll(a => a.LCID == preferredAudioLCID && a.LCID != 0); int count = streamsForLCID.Count; if (count > 0) { // If we have only one choice, select this stream. if (count == 1) { audioStreams.EnableStream(streamsForLCID[0].Name); return; } StreamInfo bestChannelStream = streamsForLCID.Find(channelCountPreference); if (bestChannelStream != null) { audioStreams.EnableStream(bestChannelStream.Name); return; } } // If we did not find matching languages by LCID no try to find them by name. StreamInfo streamInfo = null; if (preferredAudioLCID != 0) { try { CultureInfo ci = new CultureInfo(preferredAudioLCID); string languagePart = ci.EnglishName.Substring(0, ci.EnglishName.IndexOf("(") - 1); streamInfo = audioStreams.FindSimilarStream(languagePart); } catch { } } // Still no matching languages? Then select the first that matches channelCountPreference. if (streamInfo == null) { streamInfo = audioStreams.ToList().Find(channelCountPreference); } if (streamInfo != null) { audioStreams.EnableStream(streamInfo.Name); } else if (useFirstAsDefault) { audioStreams.EnableStream(audioStreams[0].Name); } }