diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 462ff3e47a..72c0690733 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -131,6 +131,10 @@ namespace Emby.Server.Implementations.Data { queries.Add("PRAGMA temp_store = memory"); } + else + { + queries.Add("PRAGMA temp_store = file"); + } ////foreach (var query in queries) ////{ diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 4fde66d1ac..d157f1b652 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -779,7 +779,7 @@ namespace MediaBrowser.Api.Playback if (string.IsNullOrEmpty(container)) { container = request.Static ? - state.InputContainer : + StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, null, DlnaProfileType.Audio) : GetOutputFileExtension(state); } diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 536236f5fe..9d23591024 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -117,7 +117,7 @@ namespace MediaBrowser.Api.Playback var authInfo = _authContext.GetAuthorizationInfo(Request); var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); - + var profile = request.DeviceProfile; if (profile == null) { @@ -144,6 +144,11 @@ namespace MediaBrowser.Api.Playback } } + if (result.MediaSource != null) + { + NormalizeMediaSourceContainer(result.MediaSource, profile, DlnaProfileType.Video); + } + return result; } @@ -207,9 +212,22 @@ namespace MediaBrowser.Api.Playback } } + if (info.MediaSources != null) + { + foreach (var mediaSource in info.MediaSources) + { + NormalizeMediaSourceContainer(mediaSource, profile, DlnaProfileType.Video); + } + } + return info; } + private void NormalizeMediaSourceContainer(MediaSourceInfo mediaSource, DeviceProfile profile, DlnaProfileType type) + { + mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, profile, type); + } + public async Task Post(GetPostedPlaybackInfo request) { var result = await GetPlaybackInfo(request).ConfigureAwait(false); diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index db5c78a2f2..95b8c33296 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -167,7 +167,7 @@ namespace MediaBrowser.Api.Playback.Progressive // Static stream if (request.Static) { - var contentType = state.GetMimeType(state.MediaPath); + var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath); using (state) { diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index eecc124324..6c098deea2 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -131,14 +131,14 @@ namespace MediaBrowser.Api.Playback public long? EncodingDurationTicks { get; set; } - public string GetMimeType(string outputPath) + public string GetMimeType(string outputPath, bool enableStreamDefault = true) { if (!string.IsNullOrEmpty(MimeType)) { return MimeType; } - return MimeTypes.GetMimeType(outputPath); + return MimeTypes.GetMimeType(outputPath, enableStreamDefault); } public bool EnableDlnaHeaders { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 9f55a9ff23..3efbc41f1d 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -48,22 +48,19 @@ namespace MediaBrowser.Controller.LiveTv return list; } + private static string EmbyServiceName = "Emby"; public override double? GetDefaultPrimaryImageAspectRatio() { - if (IsMovie) + var serviceName = ServiceName; + if (!IsMovie && !string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || !string.IsNullOrWhiteSpace(serviceName)) { - double value = 2; - value /= 3; - - return value; + return null; } - else - { - double value = 2; - value /= 3; - return value; - } + double value = 2; + value /= 3; + + return value; } [IgnoreDataMember] @@ -227,7 +224,7 @@ namespace MediaBrowser.Controller.LiveTv public LiveTvProgramLookupInfo GetLookupInfo() { var info = GetItemLookupInfo(); - info.IsMovie = IsMovie; + info.IsMovie = IsMovie; return info; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 4b3e340c99..afbb99d397 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.MediaEncoding { @@ -148,10 +149,13 @@ namespace MediaBrowser.Controller.MediaEncoding public string GetInputFormat(string container) { - if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrWhiteSpace(container)) { - return "matroska"; + return null; } + + container = container.Replace("mkv", "matroska", StringComparison.OrdinalIgnoreCase); + if (string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase)) { return "mpegts"; @@ -1694,7 +1698,8 @@ namespace MediaBrowser.Controller.MediaEncoding state.InputAudioSync = "1"; } - if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase) || + string.Equals(mediaSource.Container, "asf", StringComparison.OrdinalIgnoreCase)) { // Seeing some stuttering when transcoding wma to audio-only HLS state.InputAudioSync = "1"; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 1e91a8198b..023100f449 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (data.format != null) { - info.Container = data.format.format_name; + info.Container = NormalizeFormat(data.format.format_name); if (!string.IsNullOrEmpty(data.format.bit_rate)) { @@ -195,6 +195,23 @@ namespace MediaBrowser.MediaEncoding.Probing return info; } + private string NormalizeFormat(string format) + { + if (string.IsNullOrWhiteSpace(format)) + { + return null; + } + + if (string.Equals(format, "mpegvideo", StringComparison.OrdinalIgnoreCase)) + { + return "mpeg"; + } + + format = format.Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase); + + return format; + } + private int? GetEstimatedAudioBitrate(string codec, int? channels) { if (!channels.HasValue) diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index e04e04d218..979cd343fa 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -42,16 +42,9 @@ namespace MediaBrowser.Model.Dlna return SplitValue(Codec); } - public List GetContainers() - { - return SplitValue(Container); - } - private bool ContainsContainer(string container) { - List containers = GetContainers(); - - return containers.Count == 0 || ListHelper.ContainsIgnoreCase(containers, container ?? string.Empty); + return ContainerProfile.ContainsContainer(Container, container); } public bool ContainsCodec(string codec, string container) diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index 35d7ada6b9..2004cfc1fe 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Xml.Serialization; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Extensions; @@ -20,11 +21,16 @@ namespace MediaBrowser.Model.Dlna } public List GetContainers() + { + return SplitValue(Container); + } + + public static List SplitValue(string value) { List list = new List(); - foreach (string i in (Container ?? string.Empty).Split(',')) + foreach (string i in (value ?? string.Empty).Split(',')) { - if (!string.IsNullOrEmpty(i)) list.Add(i); + if (!string.IsNullOrWhiteSpace(i)) list.Add(i); } return list; } @@ -33,7 +39,32 @@ namespace MediaBrowser.Model.Dlna { List containers = GetContainers(); - return containers.Count == 0 || ListHelper.ContainsIgnoreCase(containers, container ?? string.Empty); + return ContainsContainer(containers, container); + } + + public static bool ContainsContainer(string profileContainers, string inputContainer) + { + return ContainsContainer(SplitValue(profileContainers), inputContainer); + } + + public static bool ContainsContainer(List profileContainers, string inputContainer) + { + if (profileContainers.Count == 0) + { + return true; + } + + var allInputContainers = SplitValue(inputContainer); + + foreach (var container in allInputContainers) + { + if (ListHelper.ContainsIgnoreCase(profileContainers, container)) + { + return true; + } + } + + return false; } } } diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index cd7ff08d6a..5f9bd772cc 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -187,17 +187,14 @@ namespace MediaBrowser.Model.Dlna public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth) { - container = StringHelper.TrimStart(container ?? string.Empty, '.'); - foreach (var i in ResponseProfiles) { - if (i.Type != MediaBrowser.Model.Dlna.DlnaProfileType.Audio) + if (i.Type != DlnaProfileType.Audio) { continue; } - List containers = i.GetContainers(); - if (containers.Count > 0 && !ListHelper.ContainsIgnoreCase(containers, container)) + if (!ContainerProfile.ContainsContainer(i.GetContainers(), container)) { continue; } @@ -208,7 +205,7 @@ namespace MediaBrowser.Model.Dlna continue; } - var conditionProcessor = new MediaBrowser.Model.Dlna.ConditionProcessor(); + var conditionProcessor = new ConditionProcessor(); var anyOff = false; foreach (ProfileCondition c in i.Conditions) @@ -230,9 +227,9 @@ namespace MediaBrowser.Model.Dlna return null; } - private MediaBrowser.Model.Dlna.ProfileCondition GetModelProfileCondition(ProfileCondition c) + private ProfileCondition GetModelProfileCondition(ProfileCondition c) { - return new MediaBrowser.Model.Dlna.ProfileCondition + return new ProfileCondition { Condition = c.Condition, IsRequired = c.IsRequired, @@ -243,22 +240,19 @@ namespace MediaBrowser.Model.Dlna public ResponseProfile GetImageMediaProfile(string container, int? width, int? height) { - container = StringHelper.TrimStart(container ?? string.Empty, '.'); - foreach (var i in ResponseProfiles) { - if (i.Type != MediaBrowser.Model.Dlna.DlnaProfileType.Photo) + if (i.Type != DlnaProfileType.Photo) { continue; } - List containers = i.GetContainers(); - if (containers.Count > 0 && !ListHelper.ContainsIgnoreCase(containers, container)) + if (!ContainerProfile.ContainsContainer(i.GetContainers(), container)) { continue; } - var conditionProcessor = new MediaBrowser.Model.Dlna.ConditionProcessor(); + var conditionProcessor = new ConditionProcessor(); var anyOff = false; foreach (ProfileCondition c in i.Conditions) @@ -300,17 +294,14 @@ namespace MediaBrowser.Model.Dlna string videoCodecTag, bool? isAvc) { - container = StringHelper.TrimStart(container ?? string.Empty, '.'); - foreach (var i in ResponseProfiles) { - if (i.Type != MediaBrowser.Model.Dlna.DlnaProfileType.Video) + if (i.Type != DlnaProfileType.Video) { continue; } - List containers = i.GetContainers(); - if (containers.Count > 0 && !ListHelper.ContainsIgnoreCase(containers, container ?? string.Empty)) + if (!ContainerProfile.ContainsContainer(i.GetContainers(), container)) { continue; } @@ -327,7 +318,7 @@ namespace MediaBrowser.Model.Dlna continue; } - var conditionProcessor = new MediaBrowser.Model.Dlna.ConditionProcessor(); + var conditionProcessor = new ConditionProcessor(); var anyOff = false; foreach (ProfileCondition c in i.Conditions) diff --git a/MediaBrowser.Model/Dlna/DirectPlayProfile.cs b/MediaBrowser.Model/Dlna/DirectPlayProfile.cs index df511b0da0..d99501875d 100644 --- a/MediaBrowser.Model/Dlna/DirectPlayProfile.cs +++ b/MediaBrowser.Model/Dlna/DirectPlayProfile.cs @@ -19,27 +19,9 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("type")] public DlnaProfileType Type { get; set; } - public List GetContainers() - { - List list = new List(); - foreach (string i in (Container ?? string.Empty).Split(',')) - { - if (!string.IsNullOrEmpty(i)) list.Add(i); - } - return list; - } - public bool SupportsContainer(string container) { - var all = GetContainers(); - - // Only allow unknown container if the profile is all inclusive - if (string.IsNullOrWhiteSpace(container)) - { - return all.Count == 0; - } - - return all.Count == 0 || all.Contains(container, StringComparer.OrdinalIgnoreCase); + return ContainerProfile.ContainsContainer(Container, container); } public List GetAudioCodecs() diff --git a/MediaBrowser.Model/Dlna/ResponseProfile.cs b/MediaBrowser.Model/Dlna/ResponseProfile.cs index 1d4791b5c9..f1a001bbab 100644 --- a/MediaBrowser.Model/Dlna/ResponseProfile.cs +++ b/MediaBrowser.Model/Dlna/ResponseProfile.cs @@ -33,12 +33,7 @@ namespace MediaBrowser.Model.Dlna public List GetContainers() { - List list = new List(); - foreach (string i in (Container ?? string.Empty).Split(',')) - { - if (!string.IsNullOrEmpty(i)) list.Add(i); - } - return list; + return ContainerProfile.SplitValue(Container); } public List GetAudioCodecs() diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index b483d527c3..189ed27e46 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -197,6 +197,40 @@ namespace MediaBrowser.Model.Dlna } } + public static string NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, DeviceProfile profile, DlnaProfileType type) + { + if (string.IsNullOrWhiteSpace(inputContainer)) + { + return null; + } + + var formats = ContainerProfile.SplitValue(inputContainer); + + if (formats.Count == 1) + { + return formats[0]; + } + + if (profile != null) + { + foreach (var format in formats) + { + foreach (var directPlayProfile in profile.DirectPlayProfiles) + { + if (directPlayProfile.Type == type) + { + if (directPlayProfile.SupportsContainer(format)) + { + return format; + } + } + } + } + } + + return formats[0]; + } + private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options) { List transcodeReasons = new List(); @@ -214,14 +248,14 @@ namespace MediaBrowser.Model.Dlna if (options.ForceDirectPlay) { playlistItem.PlayMethod = PlayMethod.DirectPlay; - playlistItem.Container = item.Container; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } if (options.ForceDirectStream) { playlistItem.PlayMethod = PlayMethod.DirectStream; - playlistItem.Container = item.Container; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } @@ -295,7 +329,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.PlayMethod = PlayMethod.DirectStream; } - playlistItem.Container = item.Container; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } @@ -648,7 +682,7 @@ namespace MediaBrowser.Model.Dlna if (directPlay != null) { playlistItem.PlayMethod = directPlay.Value; - playlistItem.Container = item.Container; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Video); if (subtitleStream != null) { @@ -1231,21 +1265,27 @@ namespace MediaBrowser.Model.Dlna private static bool IsSubtitleEmbedSupported(MediaStream subtitleStream, SubtitleProfile subtitleProfile, string transcodingSubProtocol, string transcodingContainer) { - if (string.Equals(transcodingContainer, "ts", StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrWhiteSpace(transcodingContainer)) { - return false; - } - if (string.Equals(transcodingContainer, "mpegts", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (string.Equals(transcodingContainer, "mp4", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (string.Equals(transcodingContainer, "mkv", StringComparison.OrdinalIgnoreCase)) - { - return true; + var normalizedContainers = ContainerProfile.SplitValue(transcodingContainer); + + if (ContainerProfile.ContainsContainer(normalizedContainers, "ts")) + { + return false; + } + if (ContainerProfile.ContainsContainer(normalizedContainers, "mpegts")) + { + return false; + } + if (ContainerProfile.ContainsContainer(normalizedContainers, "mp4")) + { + return false; + } + if (ContainerProfile.ContainsContainer(normalizedContainers, "mkv") || + ContainerProfile.ContainsContainer(normalizedContainers, "matroska")) + { + return true; + } } return false; @@ -1572,14 +1612,17 @@ namespace MediaBrowser.Model.Dlna } // Check audio codec - List audioCodecs = profile.GetAudioCodecs(); - if (audioCodecs.Count > 0) + if (audioStream != null) { - // Check audio codecs - string audioCodec = audioStream == null ? null : audioStream.Codec; - if (string.IsNullOrEmpty(audioCodec) || !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec)) + List audioCodecs = profile.GetAudioCodecs(); + if (audioCodecs.Count > 0) { - return false; + // Check audio codecs + string audioCodec = audioStream == null ? null : audioStream.Codec; + if (string.IsNullOrEmpty(audioCodec) || !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec)) + { + return false; + } } } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 2f132cb373..7a2e1f2159 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -106,14 +106,15 @@ namespace MediaBrowser.Model.Net return dict; } + public static string GetMimeType(string path) + { + return GetMimeType(path, true); + } + /// /// Gets the type of the MIME. /// - /// The path. - /// System.String. - /// path - /// Argument not supported: + path - public static string GetMimeType(string path) + public static string GetMimeType(string path, bool enableStreamDefault) { if (string.IsNullOrEmpty(path)) { @@ -329,7 +330,12 @@ namespace MediaBrowser.Model.Net return "application/ttml+xml"; } - return "application/octet-stream"; + if (enableStreamDefault) + { + return "application/octet-stream"; + } + + return null; } public static string ToExtension(string mimeType) diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 04e549526c..12d1d3468b 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -95,14 +95,14 @@ namespace MediaBrowser.Providers.MediaInfo { var mediaStreams = mediaInfo.MediaStreams; - //audio.FormatName = mediaInfo.Container; + audio.Container = mediaInfo.Container; audio.TotalBitrate = mediaInfo.Bitrate; audio.RunTimeTicks = mediaInfo.RunTimeTicks; audio.Size = mediaInfo.Size; var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.'); - audio.Container = extension; + //audio.Container = extension; await FetchDataFromTags(audio, mediaInfo).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index eaf3505d1a..06267f33a9 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -187,6 +187,7 @@ namespace MediaBrowser.Providers.MediaInfo { video.Container = null; } + video.Container = mediaInfo.Container; var chapters = mediaInfo.Chapters ?? new List(); if (blurayInfo != null) diff --git a/SharedVersion.cs b/SharedVersion.cs index bbaac5d907..a6247b61c9 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.26.13")] +[assembly: AssemblyVersion("3.2.26.14")]