< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Library.MediaStreamSelector
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Library/MediaStreamSelector.cs
Line coverage
27%
Covered lines: 17
Uncovered lines: 45
Coverable lines: 62
Total lines: 159
Line coverage: 27.4%
Branch coverage
31%
Covered branches: 17
Total branches: 54
Branch coverage: 31.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetDefaultAudioStreamIndex(...)100%66100%
GetDefaultSubtitleStreamIndex(...)0%342180%
GetSortedStreams(...)100%11100%
SetSubtitleStreamScores(...)0%342180%
GetStreamScore(...)91.66%1212100%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Library/MediaStreamSelector.cs

#LineLine coverage
 1#pragma warning disable CS1591
 2
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using Jellyfin.Data.Enums;
 7using Jellyfin.Extensions;
 8using MediaBrowser.Model.Entities;
 9
 10namespace Emby.Server.Implementations.Library
 11{
 12    public static class MediaStreamSelector
 13    {
 14        public static int? GetDefaultAudioStreamIndex(IReadOnlyList<MediaStream> streams, IReadOnlyList<string> preferre
 15        {
 916            var sortedStreams = GetSortedStreams(streams, MediaStreamType.Audio, preferredLanguages).ToList();
 17
 918            if (preferDefaultTrack)
 19            {
 420                var defaultStream = sortedStreams.FirstOrDefault(i => i.IsDefault);
 21
 422                if (defaultStream is not null)
 23                {
 324                    return defaultStream.Index;
 25                }
 26            }
 27
 628            return sortedStreams.FirstOrDefault()?.Index;
 29        }
 30
 31        public static int? GetDefaultSubtitleStreamIndex(
 32            IEnumerable<MediaStream> streams,
 33            IReadOnlyList<string> preferredLanguages,
 34            SubtitlePlaybackMode mode,
 35            string audioTrackLanguage)
 36        {
 037            if (mode == SubtitlePlaybackMode.None)
 38            {
 039                return null;
 40            }
 41
 042            var sortedStreams = streams
 043                .Where(i => i.Type == MediaStreamType.Subtitle)
 044                .OrderByDescending(x => x.IsExternal)
 045                .ThenByDescending(x => x.IsForced && string.Equals(x.Language, audioTrackLanguage, StringComparison.Ordi
 046                .ThenByDescending(x => x.IsForced)
 047                .ThenByDescending(x => x.IsDefault)
 048                .ThenByDescending(x => preferredLanguages.Contains(x.Language, StringComparison.OrdinalIgnoreCase))
 049                .ToList();
 50
 051            MediaStream? stream = null;
 052            if (mode == SubtitlePlaybackMode.Default)
 53            {
 54                // Load subtitles according to external, forced and default flags.
 055                stream = sortedStreams.FirstOrDefault(x => x.IsExternal || x.IsForced || x.IsDefault);
 56            }
 057            else if (mode == SubtitlePlaybackMode.Smart)
 58            {
 59                // Only attempt to load subtitles if the audio language is not one of the user's preferred subtitle lang
 60                // If no subtitles of preferred language available, use default behaviour.
 061                if (!preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
 62                {
 063                    stream = sortedStreams.FirstOrDefault(x => preferredLanguages.Contains(x.Language, StringComparison.
 064                        sortedStreams.FirstOrDefault(x => x.IsExternal || x.IsForced || x.IsDefault);
 65                }
 66                else
 67                {
 68                    // Respect forced flag.
 069                    stream = sortedStreams.FirstOrDefault(x => x.IsForced);
 70                }
 71            }
 072            else if (mode == SubtitlePlaybackMode.Always)
 73            {
 74                // Always load (full/non-forced) subtitles of the user's preferred subtitle language if possible, otherw
 075                stream = sortedStreams.FirstOrDefault(x => !x.IsForced && preferredLanguages.Contains(x.Language, String
 076                    sortedStreams.FirstOrDefault(x => x.IsExternal || x.IsForced || x.IsDefault);
 77            }
 078            else if (mode == SubtitlePlaybackMode.OnlyForced)
 79            {
 80                // Only load subtitles that are flagged forced.
 081                stream = sortedStreams.FirstOrDefault(x => x.IsForced);
 82            }
 83
 084            return stream?.Index;
 85        }
 86
 87        private static IEnumerable<MediaStream> GetSortedStreams(IEnumerable<MediaStream> streams, MediaStreamType type,
 88        {
 89            // Give some preference to external text subs for better performance
 990            return streams
 991                .Where(i => i.Type == type)
 992                .OrderByDescending(i => GetStreamScore(i, languagePreferences));
 93        }
 94
 95        public static void SetSubtitleStreamScores(
 96            IReadOnlyList<MediaStream> streams,
 97            IReadOnlyList<string> preferredLanguages,
 98            SubtitlePlaybackMode mode,
 99            string audioTrackLanguage)
 100        {
 0101            if (mode == SubtitlePlaybackMode.None)
 102            {
 0103                return;
 104            }
 105
 0106            var sortedStreams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages).ToList();
 107
 0108            List<MediaStream>? filteredStreams = null;
 109
 0110            if (mode == SubtitlePlaybackMode.Default)
 111            {
 112                // Prefer embedded metadata over smart logic
 0113                filteredStreams = sortedStreams.Where(s => s.IsForced || s.IsDefault)
 0114                    .ToList();
 115            }
 0116            else if (mode == SubtitlePlaybackMode.Smart)
 117            {
 118                // Prefer smart logic over embedded metadata
 0119                if (!preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
 120                {
 0121                    filteredStreams = sortedStreams.Where(s => !s.IsForced && preferredLanguages.Contains(s.Language, St
 0122                        .ToList();
 123                }
 124            }
 0125            else if (mode == SubtitlePlaybackMode.Always)
 126            {
 127                // Always load the most suitable full subtitles
 0128                filteredStreams = sortedStreams.Where(s => !s.IsForced).ToList();
 129            }
 0130            else if (mode == SubtitlePlaybackMode.OnlyForced)
 131            {
 132                // Always load the most suitable full subtitles
 0133                filteredStreams = sortedStreams.Where(s => s.IsForced).ToList();
 134            }
 135
 136            // Load forced subs if we have found no suitable full subtitles
 0137            var iterStreams = filteredStreams is null || filteredStreams.Count == 0
 0138                ? sortedStreams.Where(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.
 0139                : filteredStreams;
 140
 0141            foreach (var stream in iterStreams)
 142            {
 0143                stream.Score = GetStreamScore(stream, preferredLanguages);
 144            }
 0145        }
 146
 147        internal static int GetStreamScore(MediaStream stream, IReadOnlyList<string> languagePreferences)
 148        {
 22149            var index = languagePreferences.FindIndex(x => string.Equals(x, stream.Language, StringComparison.OrdinalIgn
 22150            var score = index == -1 ? 1 : 101 - index;
 22151            score = (score * 10) + (stream.IsForced ? 2 : 1);
 22152            score = (score * 10) + (stream.IsDefault ? 2 : 1);
 22153            score = (score * 10) + (stream.SupportsExternalStream ? 2 : 1);
 22154            score = (score * 10) + (stream.IsTextSubtitleStream ? 2 : 1);
 22155            score = (score * 10) + (stream.IsExternal ? 2 : 1);
 22156            return score;
 157        }
 158    }
 159}