mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-30 10:12:44 -04:00 
			
		
		
		
	Refactor ProbeResultNormalizer
Improve code structure and readability
This commit is contained in:
		
							parent
							
								
									40c73e96a9
								
							
						
					
					
						commit
						11a5551218
					
				| @ -1,5 +1,3 @@ | ||||
| #nullable disable | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Globalization; | ||||
| @ -22,7 +20,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 throw new ArgumentNullException(nameof(result)); | ||||
|             } | ||||
| 
 | ||||
|             if (result.Format != null && result.Format.Tags != null) | ||||
|             if (result.Format?.Tags != null) | ||||
|             { | ||||
|                 result.Format.Tags = ConvertDictionaryToCaseInsensitive(result.Format.Tags); | ||||
|             } | ||||
| @ -40,40 +38,18 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a string from an FFProbeResult tags dictionary. | ||||
|         /// </summary> | ||||
|         /// <param name="tags">The tags.</param> | ||||
|         /// <param name="key">The key.</param> | ||||
|         /// <returns>System.String.</returns> | ||||
|         public static string GetDictionaryValue(IReadOnlyDictionary<string, string> tags, string key) | ||||
|         { | ||||
|             if (tags == null) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             tags.TryGetValue(key, out var val); | ||||
|             return val; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets an int from an FFProbeResult tags dictionary. | ||||
|         /// </summary> | ||||
|         /// <param name="tags">The tags.</param> | ||||
|         /// <param name="key">The key.</param> | ||||
|         /// <returns>System.Nullable{System.Int32}.</returns> | ||||
|         public static int? GetDictionaryNumericValue(Dictionary<string, string> tags, string key) | ||||
|         public static int? GetDictionaryNumericValue(IReadOnlyDictionary<string, string> tags, string key) | ||||
|         { | ||||
|             var val = GetDictionaryValue(tags, key); | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(val)) | ||||
|             { | ||||
|                 if (int.TryParse(val, out var i)) | ||||
|             if (tags.TryGetValue(key, out var val) && int.TryParse(val, out var i)) | ||||
|             { | ||||
|                 return i; | ||||
|             } | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| @ -84,18 +60,12 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|         /// <param name="tags">The tags.</param> | ||||
|         /// <param name="key">The key.</param> | ||||
|         /// <returns>System.Nullable{DateTime}.</returns> | ||||
|         public static DateTime? GetDictionaryDateTime(Dictionary<string, string> tags, string key) | ||||
|         public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary<string, string> tags, string key) | ||||
|         { | ||||
|             var val = GetDictionaryValue(tags, key); | ||||
| 
 | ||||
|             if (string.IsNullOrEmpty(val)) | ||||
|             if (tags.TryGetValue(key, out var val) | ||||
|                 && DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime)) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             if (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var i)) | ||||
|             { | ||||
|                 return i.ToUniversalTime(); | ||||
|                 return dateTime.ToUniversalTime(); | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|  | ||||
| @ -8,6 +8,7 @@ using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Xml; | ||||
| using Jellyfin.Extensions; | ||||
| using MediaBrowser.Controller.Library; | ||||
| using MediaBrowser.Model.Dto; | ||||
| using MediaBrowser.Model.Entities; | ||||
| @ -80,68 +81,33 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             var tags = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); | ||||
|             var tagStreamType = isAudio ? "audio" : "video"; | ||||
| 
 | ||||
|             if (data.Streams != null) | ||||
|             { | ||||
|                 var tagStream = data.Streams.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); | ||||
|             var tagStream = data.Streams?.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); | ||||
| 
 | ||||
|                 if (tagStream != null && tagStream.Tags != null) | ||||
|             if (tagStream?.Tags != null) | ||||
|             { | ||||
|                     foreach (var pair in tagStream.Tags) | ||||
|                 foreach (var (key, value) in tagStream.Tags) | ||||
|                 { | ||||
|                         tags[pair.Key] = pair.Value; | ||||
|                     } | ||||
|                     tags[key] = value; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (data.Format != null && data.Format.Tags != null) | ||||
|             if (data.Format?.Tags != null) | ||||
|             { | ||||
|                 foreach (var pair in data.Format.Tags) | ||||
|                 foreach (var (key, value) in data.Format.Tags) | ||||
|                 { | ||||
|                     tags[pair.Key] = pair.Value; | ||||
|                     tags[key] = value; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             FetchGenres(info, tags); | ||||
|             var overview = FFProbeHelpers.GetDictionaryValue(tags, "synopsis"); | ||||
| 
 | ||||
|             if (string.IsNullOrWhiteSpace(overview)) | ||||
|             { | ||||
|                 overview = FFProbeHelpers.GetDictionaryValue(tags, "description"); | ||||
|             } | ||||
| 
 | ||||
|             if (string.IsNullOrWhiteSpace(overview)) | ||||
|             { | ||||
|                 overview = FFProbeHelpers.GetDictionaryValue(tags, "desc"); | ||||
|             } | ||||
| 
 | ||||
|             if (!string.IsNullOrWhiteSpace(overview)) | ||||
|             { | ||||
|                 info.Overview = overview; | ||||
|             } | ||||
| 
 | ||||
|             var title = FFProbeHelpers.GetDictionaryValue(tags, "title"); | ||||
|             if (!string.IsNullOrWhiteSpace(title)) | ||||
|             { | ||||
|                 info.Name = title; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 title = FFProbeHelpers.GetDictionaryValue(tags, "title-eng"); | ||||
|                 if (!string.IsNullOrWhiteSpace(title)) | ||||
|                 { | ||||
|                     info.Name = title; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             var titleSort = FFProbeHelpers.GetDictionaryValue(tags, "titlesort"); | ||||
|             if (!string.IsNullOrWhiteSpace(titleSort)) | ||||
|             { | ||||
|                 info.ForcedSortName = titleSort; | ||||
|             } | ||||
|             info.Name = tags.GetFirstNotNullNorWhiteSpaceValue("title", "title-eng"); | ||||
|             info.ForcedSortName = tags.GetFirstNotNullNorWhiteSpaceValue("sort_name", "title-sort", "titlesort"); | ||||
|             info.Overview = tags.GetFirstNotNullNorWhiteSpaceValue("synopsis", "description", "desc"); | ||||
| 
 | ||||
|             info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort"); | ||||
|             info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number"); | ||||
|             info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name"); | ||||
|             info.ShowName = tags.GetValueOrDefault("show_name"); | ||||
|             info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date"); | ||||
| 
 | ||||
|             // Several different forms of retail/premiere date | ||||
| @ -153,32 +119,21 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 FFProbeHelpers.GetDictionaryDateTime(tags, "date"); | ||||
| 
 | ||||
|             // Set common metadata for music (audio) and music videos (video) | ||||
|             info.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); | ||||
|             info.Album = tags.GetValueOrDefault("album"); | ||||
| 
 | ||||
|             var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); | ||||
| 
 | ||||
|             if (!string.IsNullOrWhiteSpace(artists)) | ||||
|             if (tags.TryGetValue("artists", out var artists) && !string.IsNullOrWhiteSpace(artists)) | ||||
|             { | ||||
|                 info.Artists = SplitArtists(artists, new[] { '/', ';' }, false) | ||||
|                     .DistinctNames() | ||||
|                     .ToArray(); | ||||
|                 info.Artists = SplitDistinctArtists(artists, new[] { '/', ';' }, false).ToArray(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); | ||||
|                 if (string.IsNullOrWhiteSpace(artist)) | ||||
|                 { | ||||
|                     info.Artists = Array.Empty<string>(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     info.Artists = SplitArtists(artist, _nameDelimiters, true) | ||||
|                         .DistinctNames() | ||||
|                         .ToArray(); | ||||
|                 } | ||||
|                 var artist = tags.GetFirstNotNullNorWhiteSpaceValue("artist"); | ||||
|                 info.Artists = artist == null | ||||
|                     ? Array.Empty<string>() | ||||
|                     : SplitDistinctArtists(artist, _nameDelimiters, true).ToArray(); | ||||
|             } | ||||
| 
 | ||||
|             // If we don't have a ProductionYear try and get it from PremiereDate | ||||
|             // Guess ProductionYear from PremiereDate if missing | ||||
|             if (!info.ProductionYear.HasValue && info.PremiereDate.HasValue) | ||||
|             { | ||||
|                 info.ProductionYear = info.PremiereDate.Value.Year; | ||||
| @ -198,10 +153,10 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             { | ||||
|                 FetchStudios(info, tags, "copyright"); | ||||
| 
 | ||||
|                 var iTunEXTC = FFProbeHelpers.GetDictionaryValue(tags, "iTunEXTC"); | ||||
|                 if (!string.IsNullOrWhiteSpace(iTunEXTC)) | ||||
|                 var iTunExtc = tags.GetFirstNotNullNorWhiteSpaceValue("iTunEXTC"); | ||||
|                 if (iTunExtc != null) | ||||
|                 { | ||||
|                     var parts = iTunEXTC.Split('|', StringSplitOptions.RemoveEmptyEntries); | ||||
|                     var parts = iTunExtc.Split('|', StringSplitOptions.RemoveEmptyEntries); | ||||
|                     // Example | ||||
|                     // mpaa|G|100|For crude humor | ||||
|                     if (parts.Length > 1) | ||||
| @ -215,10 +170,10 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 var itunesXml = FFProbeHelpers.GetDictionaryValue(tags, "iTunMOVI"); | ||||
|                 if (!string.IsNullOrWhiteSpace(itunesXml)) | ||||
|                 var iTunXml = tags.GetFirstNotNullNorWhiteSpaceValue("iTunMOVI"); | ||||
|                 if (iTunXml != null) | ||||
|                 { | ||||
|                     FetchFromItunesInfo(itunesXml, info); | ||||
|                     FetchFromItunesInfo(iTunXml, info); | ||||
|                 } | ||||
| 
 | ||||
|                 if (data.Format != null && !string.IsNullOrEmpty(data.Format.Duration)) | ||||
| @ -235,8 +190,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
| 
 | ||||
|                 ExtractTimestamp(info); | ||||
| 
 | ||||
|                 var stereoMode = GetDictionaryValue(tags, "stereo_mode"); | ||||
|                 if (string.Equals(stereoMode, "left_right", StringComparison.OrdinalIgnoreCase)) | ||||
|                 if (tags.TryGetValue("stereo_mode", out var stereoMode) && string.Equals(stereoMode, "left_right", StringComparison.OrdinalIgnoreCase)) | ||||
|                 { | ||||
|                     info.Video3DFormat = Video3DFormat.FullSideBySide; | ||||
|                 } | ||||
| @ -289,13 +243,11 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) | ||||
|                 || string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
|                 if (channelsValue <= 2) | ||||
|                 switch (channelsValue) | ||||
|                 { | ||||
|                     case <= 2: | ||||
|                         return 192000; | ||||
|                 } | ||||
| 
 | ||||
|                 if (channelsValue >= 5) | ||||
|                 { | ||||
|                     case >= 5: | ||||
|                         return 320000; | ||||
|                 } | ||||
|             } | ||||
| @ -303,13 +255,11 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             if (string.Equals(codec, "ac3", StringComparison.OrdinalIgnoreCase) | ||||
|                 || string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
|                 if (channelsValue <= 2) | ||||
|                 switch (channelsValue) | ||||
|                 { | ||||
|                     case <= 2: | ||||
|                         return 192000; | ||||
|                 } | ||||
| 
 | ||||
|                 if (channelsValue >= 5) | ||||
|                 { | ||||
|                     case >= 5: | ||||
|                         return 640000; | ||||
|                 } | ||||
|             } | ||||
| @ -317,13 +267,11 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             if (string.Equals(codec, "flac", StringComparison.OrdinalIgnoreCase) | ||||
|                 || string.Equals(codec, "alac", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
|                 if (channelsValue <= 2) | ||||
|                 switch (channelsValue) | ||||
|                 { | ||||
|                     case <= 2: | ||||
|                         return 960000; | ||||
|                 } | ||||
| 
 | ||||
|                 if (channelsValue >= 5) | ||||
|                 { | ||||
|                     case >= 5: | ||||
|                         return 2880000; | ||||
|                 } | ||||
|             } | ||||
| @ -854,7 +802,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                     || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) | ||||
|             { | ||||
|                 var bps = GetBPSFromTags(streamInfo); | ||||
|                 if (bps != null && bps > 0) | ||||
|                 if (bps > 0) | ||||
|                 { | ||||
|                     stream.BitRate = bps; | ||||
|                 } | ||||
| @ -923,6 +871,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             } | ||||
| 
 | ||||
|             tags.TryGetValue(key, out var val); | ||||
| 
 | ||||
|             return val; | ||||
|         } | ||||
| 
 | ||||
| @ -930,7 +879,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(input)) | ||||
|             { | ||||
|                 return input; | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             return input.Split('(').FirstOrDefault(); | ||||
| @ -1018,8 +967,11 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|         /// <returns>System.Nullable{System.Single}.</returns> | ||||
|         private float? GetFrameRate(string value) | ||||
|         { | ||||
|             if (!string.IsNullOrEmpty(value)) | ||||
|             if (string.IsNullOrEmpty(value)) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             var parts = value.Split('/'); | ||||
| 
 | ||||
|             float result; | ||||
| @ -1033,21 +985,18 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 result = float.Parse(parts[0], _usCulture); | ||||
|             } | ||||
| 
 | ||||
|                 return float.IsNaN(result) ? (float?)null : result; | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|             return float.IsNaN(result) ? null : result; | ||||
|         } | ||||
| 
 | ||||
|         private void SetAudioRuntimeTicks(InternalMediaInfoResult result, MediaInfo data) | ||||
|         { | ||||
|             if (result.Streams != null) | ||||
|         { | ||||
|             // Get the first info stream | ||||
|                 var stream = result.Streams.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); | ||||
| 
 | ||||
|                 if (stream != null) | ||||
|             var stream = result.Streams?.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); | ||||
|             if (stream == null) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // Get duration from stream properties | ||||
|             var duration = stream.Duration; | ||||
| 
 | ||||
| @ -1063,73 +1012,72 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; | ||||
|             } | ||||
|         } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private int? GetBPSFromTags(MediaStreamInfo streamInfo) | ||||
|         { | ||||
|             if (streamInfo != null && streamInfo.Tags != null) | ||||
|             if (streamInfo?.Tags == null) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); | ||||
|             if (!string.IsNullOrEmpty(bps) | ||||
|                 && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) | ||||
|             { | ||||
|                 return parsedBps; | ||||
|             } | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         private double? GetRuntimeSecondsFromTags(MediaStreamInfo streamInfo) | ||||
|         { | ||||
|             if (streamInfo != null && streamInfo.Tags != null) | ||||
|             if (streamInfo?.Tags == null) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); | ||||
|             if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) | ||||
|             { | ||||
|                 return parsedDuration.TotalSeconds; | ||||
|             } | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         private long? GetNumberOfBytesFromTags(MediaStreamInfo streamInfo) | ||||
|         { | ||||
|             if (streamInfo != null && streamInfo.Tags != null) | ||||
|             if (streamInfo?.Tags == null) | ||||
|             { | ||||
|                 var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") | ||||
|                                 ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); | ||||
|             if (!string.IsNullOrEmpty(numberOfBytes) | ||||
|                 && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) | ||||
|             { | ||||
|                 return parsedBytes; | ||||
|             } | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         private void SetSize(InternalMediaInfoResult data, MediaInfo info) | ||||
|         { | ||||
|             if (data.Format != null) | ||||
|             if (data.Format == null) | ||||
|             { | ||||
|                 if (!string.IsNullOrEmpty(data.Format.Size)) | ||||
|                 { | ||||
|                     info.Size = long.Parse(data.Format.Size, _usCulture); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     info.Size = null; | ||||
|                 } | ||||
|             } | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|         private void SetAudioInfoFromTags(MediaInfo audio, Dictionary<string, string> tags) | ||||
|             info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, _usCulture); | ||||
|         } | ||||
| 
 | ||||
|         private void SetAudioInfoFromTags(MediaInfo audio, IReadOnlyDictionary<string, string> tags) | ||||
|         { | ||||
|             var people = new List<BaseItemPerson>(); | ||||
|             var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); | ||||
|             if (!string.IsNullOrWhiteSpace(composer)) | ||||
|             if (tags.TryGetValue("composer", out var composer) && !string.IsNullOrWhiteSpace(composer)) | ||||
|             { | ||||
|                 foreach (var person in Split(composer, false)) | ||||
|                 { | ||||
| @ -1137,8 +1085,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); | ||||
|             if (!string.IsNullOrWhiteSpace(conductor)) | ||||
|             if (tags.TryGetValue("conductor", out var conductor) && !string.IsNullOrWhiteSpace(conductor)) | ||||
|             { | ||||
|                 foreach (var person in Split(conductor, false)) | ||||
|                 { | ||||
| @ -1146,8 +1093,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); | ||||
|             if (!string.IsNullOrWhiteSpace(lyricist)) | ||||
|             if (tags.TryGetValue("lyricist", out var lyricist) && !string.IsNullOrWhiteSpace(lyricist)) | ||||
|             { | ||||
|                 foreach (var person in Split(lyricist, false)) | ||||
|                 { | ||||
| @ -1156,8 +1102,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             } | ||||
| 
 | ||||
|             // Check for writer some music is tagged that way as alternative to composer/lyricist | ||||
|             var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer"); | ||||
|             if (!string.IsNullOrWhiteSpace(writer)) | ||||
|             if (tags.TryGetValue("writer", out var writer) && !string.IsNullOrWhiteSpace(writer)) | ||||
|             { | ||||
|                 foreach (var person in Split(writer, false)) | ||||
|                 { | ||||
| @ -1167,38 +1112,23 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
| 
 | ||||
|             audio.People = people.ToArray(); | ||||
| 
 | ||||
|             var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist"); | ||||
|             if (string.IsNullOrWhiteSpace(albumArtist)) | ||||
|             { | ||||
|                 albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist"); | ||||
|             } | ||||
| 
 | ||||
|             if (string.IsNullOrWhiteSpace(albumArtist)) | ||||
|             { | ||||
|                 albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist"); | ||||
|             } | ||||
| 
 | ||||
|             if (string.IsNullOrWhiteSpace(albumArtist)) | ||||
|             { | ||||
|                 audio.AlbumArtists = Array.Empty<string>(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 audio.AlbumArtists = SplitArtists(albumArtist, _nameDelimiters, true) | ||||
|                     .DistinctNames() | ||||
|                     .ToArray(); | ||||
|             } | ||||
|             // Set album artist | ||||
|             var albumArtist = tags.GetFirstNotNullNorWhiteSpaceValue("albumartist", "album artist", "album_artist"); | ||||
|             audio.AlbumArtists = albumArtist != null | ||||
|                 ? SplitDistinctArtists(albumArtist, _nameDelimiters, true).ToArray() | ||||
|                 : Array.Empty<string>(); | ||||
| 
 | ||||
|             // Set album artist to artist if empty | ||||
|             if (audio.AlbumArtists.Length == 0) | ||||
|             { | ||||
|                 audio.AlbumArtists = audio.Artists; | ||||
|             } | ||||
| 
 | ||||
|             // Track number | ||||
|             audio.IndexNumber = GetDictionaryDiscValue(tags, "track"); | ||||
|             audio.IndexNumber = GetDictionaryTrackOrDiscNumber(tags, "track"); | ||||
| 
 | ||||
|             // Disc number | ||||
|             audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc"); | ||||
|             audio.ParentIndexNumber = GetDictionaryTrackOrDiscNumber(tags, "disc"); | ||||
| 
 | ||||
|             // There's several values in tags may or may not be present | ||||
|             FetchStudios(audio, tags, "organization"); | ||||
| @ -1206,30 +1136,25 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             FetchStudios(audio, tags, "publisher"); | ||||
|             FetchStudios(audio, tags, "label"); | ||||
| 
 | ||||
|             // These support mulitple values, but for now we only store the first. | ||||
|             var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); | ||||
| 
 | ||||
|             // These support multiple values, but for now we only store the first. | ||||
|             var mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Album Artist Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ALBUMARTISTID")); | ||||
|             audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Artist Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ARTISTID")); | ||||
|             audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Album Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ALBUMID")); | ||||
|             audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Release Group Id")) | ||||
|                  ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_RELEASEGROUPID")); | ||||
|             audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")) | ||||
|                 ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); | ||||
| 
 | ||||
|             mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Release Track Id")) | ||||
|                  ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_RELEASETRACKID")); | ||||
|             audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); | ||||
|         } | ||||
| 
 | ||||
| @ -1253,18 +1178,18 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|         /// <returns>System.String[][].</returns> | ||||
|         private IEnumerable<string> Split(string val, bool allowCommaDelimiter) | ||||
|         { | ||||
|             // Only use the comma as a delimeter if there are no slashes or pipes. | ||||
|             // Only use the comma as a delimiter if there are no slashes or pipes. | ||||
|             // We want to be careful not to split names that have commas in them | ||||
|             var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? | ||||
|             var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? | ||||
|                 _nameDelimiters : | ||||
|                 new[] { ',' }; | ||||
| 
 | ||||
|             return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries) | ||||
|             return val.Split(delimiter, StringSplitOptions.RemoveEmptyEntries) | ||||
|                 .Where(i => !string.IsNullOrWhiteSpace(i)) | ||||
|                 .Select(i => i.Trim()); | ||||
|         } | ||||
| 
 | ||||
|         private IEnumerable<string> SplitArtists(string val, char[] delimiters, bool splitFeaturing) | ||||
|         private IEnumerable<string> SplitDistinctArtists(string val, char[] delimiters, bool splitFeaturing) | ||||
|         { | ||||
|             if (splitFeaturing) | ||||
|             { | ||||
| @ -1290,7 +1215,7 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 .Select(i => i.Trim()); | ||||
| 
 | ||||
|             artistsFound.AddRange(artists); | ||||
|             return artistsFound; | ||||
|             return artistsFound.DistinctNames(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
| @ -1299,24 +1224,28 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|         /// <param name="info">The info.</param> | ||||
|         /// <param name="tags">The tags.</param> | ||||
|         /// <param name="tagName">Name of the tag.</param> | ||||
|         private void FetchStudios(MediaInfo info, Dictionary<string, string> tags, string tagName) | ||||
|         private void FetchStudios(MediaInfo info, IReadOnlyDictionary<string, string> tags, string tagName) | ||||
|         { | ||||
|             var val = FFProbeHelpers.GetDictionaryValue(tags, tagName); | ||||
|             var val = tags.GetValueOrDefault(tagName); | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(val)) | ||||
|             if (string.IsNullOrEmpty(val)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             var studios = Split(val, true); | ||||
|             var studioList = new List<string>(); | ||||
| 
 | ||||
|             foreach (var studio in studios) | ||||
|             { | ||||
|                     // Sometimes the artist name is listed here, account for that | ||||
|                     if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase)) | ||||
|                 if (string.IsNullOrWhiteSpace(studio)) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                     if (info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) | ||||
|                 // Don't add artist/album artist name to studios, even if it's listed there | ||||
|                 if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase) | ||||
|                     || info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
| @ -1325,70 +1254,65 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             } | ||||
| 
 | ||||
|             info.Studios = studioList | ||||
|                     .Where(i => !string.IsNullOrWhiteSpace(i)) | ||||
|                 .Distinct(StringComparer.OrdinalIgnoreCase) | ||||
|                 .ToArray(); | ||||
|         } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets the genres from the tags collection. | ||||
|         /// </summary> | ||||
|         /// <param name="info">The information.</param> | ||||
|         /// <param name="tags">The tags.</param> | ||||
|         private void FetchGenres(MediaInfo info, Dictionary<string, string> tags) | ||||
|         private void FetchGenres(MediaInfo info, IReadOnlyDictionary<string, string> tags) | ||||
|         { | ||||
|             var val = FFProbeHelpers.GetDictionaryValue(tags, "genre"); | ||||
|             var genreVal = tags.GetValueOrDefault("genre"); | ||||
|             if (string.IsNullOrEmpty(genreVal)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(val)) | ||||
|             { | ||||
|             var genres = new List<string>(info.Genres); | ||||
|                 foreach (var genre in Split(val, true)) | ||||
|             foreach (var genre in Split(genreVal, true)) | ||||
|             { | ||||
|                 if (string.IsNullOrWhiteSpace(genre)) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 genres.Add(genre); | ||||
|             } | ||||
| 
 | ||||
|             info.Genres = genres | ||||
|                     .Where(i => !string.IsNullOrWhiteSpace(i)) | ||||
|                 .Distinct(StringComparer.OrdinalIgnoreCase) | ||||
|                 .ToArray(); | ||||
|         } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'. | ||||
|         /// Gets the track or disc number, which can be in the form of '1', or '1/3'. | ||||
|         /// </summary> | ||||
|         /// <param name="tags">The tags.</param> | ||||
|         /// <param name="tagName">Name of the tag.</param> | ||||
|         /// <returns>System.Nullable{System.Int32}.</returns> | ||||
|         private int? GetDictionaryDiscValue(Dictionary<string, string> tags, string tagName) | ||||
|         /// <returns>The track or disc number, or null, if missing or not parseable.</returns> | ||||
|         private static int? GetDictionaryTrackOrDiscNumber(IReadOnlyDictionary<string, string> tags, string tagName) | ||||
|         { | ||||
|             var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName); | ||||
|             var disc = tags.GetValueOrDefault(tagName); | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(disc)) | ||||
|             if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.Split('/')[0], out var discNum)) | ||||
|             { | ||||
|                 disc = disc.Split('/')[0]; | ||||
| 
 | ||||
|                 if (int.TryParse(disc, out var num)) | ||||
|                 { | ||||
|                     return num; | ||||
|                 } | ||||
|                 return discNum; | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         private ChapterInfo GetChapterInfo(MediaChapter chapter) | ||||
|         private static ChapterInfo GetChapterInfo(MediaChapter chapter) | ||||
|         { | ||||
|             var info = new ChapterInfo(); | ||||
| 
 | ||||
|             if (chapter.Tags != null) | ||||
|             { | ||||
|                 if (chapter.Tags.TryGetValue("title", out string name)) | ||||
|             if (chapter.Tags != null && chapter.Tags.TryGetValue("title", out string name)) | ||||
|             { | ||||
|                 info.Name = name; | ||||
|             } | ||||
|             } | ||||
| 
 | ||||
|             // Limit accuracy to milliseconds to match xml saving | ||||
|             var secondsString = chapter.StartTime; | ||||
| @ -1404,14 +1328,14 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
| 
 | ||||
|         private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data) | ||||
|         { | ||||
|             if (data.Format == null || data.Format.Tags == null) | ||||
|             var tags = data.Format?.Tags; | ||||
| 
 | ||||
|             if (tags == null) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             var genres = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/Genre"); | ||||
| 
 | ||||
|             if (!string.IsNullOrWhiteSpace(genres)) | ||||
|             if (tags.TryGetValue("WM/Genre", out var genres) && !string.IsNullOrWhiteSpace(genres)) | ||||
|             { | ||||
|                 var genreList = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries) | ||||
|                     .Where(i => !string.IsNullOrWhiteSpace(i)) | ||||
| @ -1425,16 +1349,12 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             var officialRating = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/ParentalRating"); | ||||
| 
 | ||||
|             if (!string.IsNullOrWhiteSpace(officialRating)) | ||||
|             if (tags.TryGetValue("WM/ParentalRating", out var officialRating) && !string.IsNullOrWhiteSpace(officialRating)) | ||||
|             { | ||||
|                 video.OfficialRating = officialRating; | ||||
|             } | ||||
| 
 | ||||
|             var people = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaCredits"); | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(people)) | ||||
|             if (tags.TryGetValue("WM/MediaCredits", out var people) && !string.IsNullOrEmpty(people)) | ||||
|             { | ||||
|                 video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) | ||||
|                     .Where(i => !string.IsNullOrWhiteSpace(i)) | ||||
| @ -1442,29 +1362,21 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                     .ToArray(); | ||||
|             } | ||||
| 
 | ||||
|             var year = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/OriginalReleaseTime"); | ||||
|             if (!string.IsNullOrWhiteSpace(year)) | ||||
|             if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, _usCulture, out var parsedYear)) | ||||
|             { | ||||
|                 if (int.TryParse(year, NumberStyles.Integer, _usCulture, out var val)) | ||||
|                 { | ||||
|                     video.ProductionYear = val; | ||||
|                 } | ||||
|                 video.ProductionYear = parsedYear; | ||||
|             } | ||||
| 
 | ||||
|             var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaOriginalBroadcastDateTime"); | ||||
|             if (!string.IsNullOrWhiteSpace(premiereDateString)) | ||||
|             { | ||||
|             // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ | ||||
|             // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None) | ||||
|                 if (DateTime.TryParse(year, null, DateTimeStyles.None, out var val)) | ||||
|             if (tags.TryGetValue("WM/MediaOriginalBroadcastDateTime", out var premiereDateString) && DateTime.TryParse(year, null, DateTimeStyles.None, out var parsedDate)) | ||||
|             { | ||||
|                     video.PremiereDate = val.ToUniversalTime(); | ||||
|                 } | ||||
|                 video.PremiereDate = parsedDate.ToUniversalTime(); | ||||
|             } | ||||
| 
 | ||||
|             var description = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitleDescription"); | ||||
|             var description = tags.GetValueOrDefault("WM/SubTitleDescription"); | ||||
| 
 | ||||
|             var subTitle = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitle"); | ||||
|             var subTitle = tags.GetValueOrDefault("WM/SubTitle"); | ||||
| 
 | ||||
|             // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ | ||||
| 
 | ||||
| @ -1475,49 +1387,48 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|             // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S] | ||||
|             if (string.IsNullOrWhiteSpace(subTitle) | ||||
|                 && !string.IsNullOrWhiteSpace(description) | ||||
|                 && description.AsSpan().Slice(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename | ||||
|                 && description.AsSpan()[0..Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)].IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename | ||||
|             { | ||||
|                 string[] parts = description.Split(':'); | ||||
|                 if (parts.Length > 0) | ||||
|                 string[] descriptionParts = description.Split(':'); | ||||
|                 if (descriptionParts.Length > 0) | ||||
|                 { | ||||
|                     string subtitle = parts[0]; | ||||
|                     string subtitle = descriptionParts[0]; | ||||
|                     try | ||||
|                     { | ||||
|                         if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number | ||||
|                         // Check if it contains a episode number and season number | ||||
|                         if (subtitle.Contains('/', StringComparison.Ordinal)) | ||||
|                         { | ||||
|                             string[] numbers = subtitle.Split(' '); | ||||
|                             video.IndexNumber = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[0], CultureInfo.InvariantCulture); | ||||
|                             int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[1], CultureInfo.InvariantCulture); | ||||
|                             string[] subtitleParts = subtitle.Split(' '); | ||||
|                             string[] numbers = subtitleParts[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/'); | ||||
|                             video.IndexNumber = int.Parse(numbers[0], CultureInfo.InvariantCulture); | ||||
|                             // int totalEpisodesInSeason = int.Parse(numbers[1], CultureInfo.InvariantCulture); | ||||
| 
 | ||||
|                             description = string.Join(' ', numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it | ||||
|                             // Skip the numbers, concatenate the rest, trim and set as new description | ||||
|                             description = string.Join(' ', subtitleParts, 1, subtitleParts.Length - 1).Trim(); | ||||
|                         } | ||||
|                         else if (subtitle.Contains('.', StringComparison.Ordinal)) | ||||
|                         { | ||||
|                             var subtitleParts = subtitle.Split('.'); | ||||
|                             description = string.Join('.', subtitleParts, 1, subtitleParts.Length - 1).Trim(); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             // Switch to default parsing | ||||
|                             if (subtitle.Contains('.', StringComparison.Ordinal)) | ||||
|                             { | ||||
|                                 // skip the comment, keep the subtitle | ||||
|                                 description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 description = subtitle.Trim(); // Clean up whitespaces and save it | ||||
|                             } | ||||
|                             description = subtitle.Trim(); | ||||
|                         } | ||||
|                     } | ||||
|                     catch (Exception ex) | ||||
|                     { | ||||
|                         _logger.LogError(ex, "Error while parsing subtitle field"); | ||||
| 
 | ||||
|                         // Default parsing | ||||
|                         // Fallback to default parsing | ||||
|                         if (subtitle.Contains('.', StringComparison.Ordinal)) | ||||
|                         { | ||||
|                             // skip the comment, keep the subtitle | ||||
|                             description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first | ||||
|                             var subtitleParts = subtitle.Split('.'); | ||||
|                             description = string.Join('.', subtitleParts, 1, subtitleParts.Length - 1).Trim(); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             description = subtitle.Trim(); // Clean up whitespaces and save it | ||||
|                             description = subtitle.Trim(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @ -1531,24 +1442,27 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
| 
 | ||||
|         private void ExtractTimestamp(MediaInfo video) | ||||
|         { | ||||
|             if (video.VideoType == VideoType.VideoFile) | ||||
|             if (video.VideoType != VideoType.VideoFile) | ||||
|             { | ||||
|                 if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) || | ||||
|                     string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) || | ||||
|                     string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (!string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) | ||||
|                 && !string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) | ||||
|                 && !string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 video.Timestamp = GetMpegTimestamp(video.Path); | ||||
| 
 | ||||
|                 _logger.LogDebug("Video has {Timestamp} timestamp", video.Timestamp); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                         _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); | ||||
|                 video.Timestamp = null; | ||||
|                     } | ||||
|                 } | ||||
|                 _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1567,8 +1481,11 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
|                 return TransportStreamTimestamp.None; | ||||
|             } | ||||
| 
 | ||||
|             if ((packetBuffer[4] == 71) && (packetBuffer[196] == 71)) | ||||
|             if ((packetBuffer[4] != 71) || (packetBuffer[196] != 71)) | ||||
|             { | ||||
|                 return TransportStreamTimestamp.None; | ||||
|             } | ||||
| 
 | ||||
|             if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) | ||||
|             { | ||||
|                 return TransportStreamTimestamp.Zero; | ||||
| @ -1576,8 +1493,5 @@ namespace MediaBrowser.MediaEncoding.Probing | ||||
| 
 | ||||
|             return TransportStreamTimestamp.Valid; | ||||
|         } | ||||
| 
 | ||||
|             return TransportStreamTimestamp.None; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										65
									
								
								src/Jellyfin.Extensions/DictionaryExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/Jellyfin.Extensions/DictionaryExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Jellyfin.Extensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Static extensions for the <see cref="IReadOnlyDictionary{TKey,TValue}"/> interface. | ||||
|     /// </summary> | ||||
|     public static class DictionaryExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets a string from a string dictionary, checking all keys sequentially, | ||||
|         /// stopping at the first key that returns a result that's neither null nor blank. | ||||
|         /// </summary> | ||||
|         /// <param name="dictionary">The dictionary.</param> | ||||
|         /// <param name="key1">The first checked key.</param> | ||||
|         /// <returns>System.String.</returns> | ||||
|         public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary<string, string> dictionary, string key1) | ||||
|         { | ||||
|             return dictionary.GetFirstNotNullNorWhiteSpaceValue(key1, string.Empty, string.Empty); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a string from a string dictionary, checking all keys sequentially, | ||||
|         /// stopping at the first key that returns a result that's neither null nor blank. | ||||
|         /// </summary> | ||||
|         /// <param name="dictionary">The dictionary.</param> | ||||
|         /// <param name="key1">The first checked key.</param> | ||||
|         /// <param name="key2">The second checked key.</param> | ||||
|         /// <returns>System.String.</returns> | ||||
|         public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary<string, string> dictionary, string key1, string key2) | ||||
|         { | ||||
|             return dictionary.GetFirstNotNullNorWhiteSpaceValue(key1, key2, string.Empty); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a string from a string dictionary, checking all keys sequentially, | ||||
|         /// stopping at the first key that returns a result that's neither null nor blank. | ||||
|         /// </summary> | ||||
|         /// <param name="dictionary">The dictionary.</param> | ||||
|         /// <param name="key1">The first checked key.</param> | ||||
|         /// <param name="key2">The second checked key.</param> | ||||
|         /// <param name="key3">The third checked key.</param> | ||||
|         /// <returns>System.String.</returns> | ||||
|         public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary<string, string> dictionary, string key1, string key2, string key3) | ||||
|         { | ||||
|             if (dictionary.TryGetValue(key1, out var val) && !string.IsNullOrWhiteSpace(val)) | ||||
|             { | ||||
|                 return val; | ||||
|             } | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(key2) && dictionary.TryGetValue(key2, out val) && !string.IsNullOrWhiteSpace(val)) | ||||
|             { | ||||
|                 return val; | ||||
|             } | ||||
| 
 | ||||
|             if (!string.IsNullOrEmpty(key3) && dictionary.TryGetValue(key3, out val) && !string.IsNullOrWhiteSpace(val)) | ||||
|             { | ||||
|                 return val; | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user