From ceed0241fd1db8b417e4148f2599368779ba8b14 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 12 Jun 2017 02:11:19 -0400 Subject: fixes #2578 - [VAAPI Bug] HEVC Decoding not possible on Intel hardware without this ability --- .../MediaEncoding/EncodingHelper.cs | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index c348ffda7..c14b1f416 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -42,6 +42,11 @@ namespace MediaBrowser.Controller.MediaEncoding { var hwType = encodingOptions.HardwareAccelerationType; + if (!encodingOptions.EnableHardwareEncoding) + { + hwType = null; + } + if (string.Equals(hwType, "qsv", StringComparison.OrdinalIgnoreCase) || string.Equals(hwType, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { @@ -1761,14 +1766,11 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) + if (state.VideoStream != null && + !string.IsNullOrWhiteSpace(state.VideoStream.Codec) && + !string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType) && + encodingOptions.EnableHardwareDecoding) { - if (!string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType)) - { - // causing unpredictable results - //return "-hwaccel auto"; - } - if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { switch (state.MediaSource.VideoStream.Codec.ToLower()) @@ -1818,6 +1820,13 @@ namespace MediaBrowser.Controller.MediaEncoding return "-c:v h264_cuvid "; } break; + case "hevc": + case "h265": + if (_mediaEncoder.SupportsDecoder("hevc_cuvid")) + { + return "-c:v hevc_cuvid "; + } + break; } } } -- cgit v1.2.3 From 1663b258a71a164046007831e09ddd5f389b28a4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 13 Jun 2017 02:33:29 -0400 Subject: update home sections --- .../Data/SqliteItemRepository.cs | 9 -- .../Emby.Server.Implementations.csproj | 1 - .../LiveTv/LiveTvManager.cs | 12 --- .../LiveTv/ProgramImageProvider.cs | 103 --------------------- MediaBrowser.Api/BaseApiService.cs | 84 ++++++++--------- .../Entities/InternalItemsQuery.cs | 1 - MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 6 -- .../MediaEncoding/EncodingHelper.cs | 7 +- .../Encoder/EncoderValidator.cs | 8 +- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 3 - MediaBrowser.Model/Users/UserPolicy.cs | 2 + 11 files changed, 57 insertions(+), 179 deletions(-) delete mode 100644 Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index df3cecbf9..e999f5753 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -3929,15 +3929,6 @@ namespace Emby.Server.Implementations.Data } } - if (!string.IsNullOrWhiteSpace(query.SlugName)) - { - whereClauses.Add("CleanName=@SlugName"); - if (statement != null) - { - statement.TryBind("@SlugName", GetCleanValue(query.SlugName)); - } - } - if (!string.IsNullOrWhiteSpace(query.MinSortName)) { whereClauses.Add("SortName>=@MinSortName"); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index df70680f1..4482bb13b 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -167,7 +167,6 @@ - diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1a5e6bddd..8f62670e4 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1422,18 +1422,6 @@ namespace Emby.Server.Implementations.LiveTv await _libraryManager.UpdateItem(program, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } - if (!(service is EmbyTV.EmbyTV)) - { - foreach (var program in newPrograms) - { - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low); - } - foreach (var program in updatedPrograms) - { - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low); - } - } - currentChannel.IsMovie = isMovie; currentChannel.IsNews = isNews; currentChannel.IsSports = isSports; diff --git a/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs b/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs deleted file mode 100644 index 5cff88a67..000000000 --- a/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ /dev/null @@ -1,103 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Emby.Server.Implementations.LiveTv -{ - public class ProgramImageProvider : IDynamicImageProvider, IHasItemChangeMonitor, IHasOrder - { - private readonly ILiveTvManager _liveTvManager; - - public ProgramImageProvider(ILiveTvManager liveTvManager) - { - _liveTvManager = liveTvManager; - } - - public IEnumerable GetSupportedImages(IHasImages item) - { - return new[] { ImageType.Primary }; - } - - private string GetItemExternalId(BaseItem item) - { - var externalId = item.ExternalId; - - if (string.IsNullOrWhiteSpace(externalId)) - { - externalId = item.GetProviderId("ProviderExternalId"); - } - - return externalId; - } - - public async Task GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) - { - var liveTvItem = (LiveTvProgram)item; - - var imageResponse = new DynamicImageResponse(); - - var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase)); - - if (service != null) - { - try - { - var channel = _liveTvManager.GetInternalChannel(liveTvItem.ChannelId); - - if (channel != null) - { - var response = await service.GetProgramImageAsync(GetItemExternalId(liveTvItem), GetItemExternalId(channel), cancellationToken).ConfigureAwait(false); - - if (response != null) - { - imageResponse.HasImage = true; - imageResponse.Stream = response.Stream; - imageResponse.Format = response.Format; - } - } - } - catch (NotImplementedException) - { - } - } - - return imageResponse; - } - - public string Name - { - get { return "Live TV Service Provider"; } - } - - public bool Supports(IHasImages item) - { - return item is LiveTvProgram; - } - - public int Order - { - get - { - // Let the better providers run first - return 100; - } - } - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) - { - var liveTvItem = item as LiveTvProgram; - - if (liveTvItem != null) - { - return !liveTvItem.HasImage(ImageType.Primary); - } - return false; - } - } -} diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 0f1d240d0..d3cc18d4b 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -178,13 +178,7 @@ namespace MediaBrowser.Api { if (name.IndexOf(BaseItem.SlugChar) != -1) { - var result = libraryManager.GetItemList(new InternalItemsQuery - { - SlugName = name, - IncludeItemTypes = new[] { typeof(MusicArtist).Name }, - DtoOptions = dtoOptions - - }).OfType().FirstOrDefault(); + var result = GetItemFromSlugName(libraryManager, name, dtoOptions); if (result != null) { @@ -199,13 +193,7 @@ namespace MediaBrowser.Api { if (name.IndexOf(BaseItem.SlugChar) != -1) { - var result = libraryManager.GetItemList(new InternalItemsQuery - { - SlugName = name, - IncludeItemTypes = new[] { typeof(Studio).Name }, - DtoOptions = dtoOptions - - }).OfType().FirstOrDefault(); + var result = GetItemFromSlugName(libraryManager, name, dtoOptions); if (result != null) { @@ -220,13 +208,7 @@ namespace MediaBrowser.Api { if (name.IndexOf(BaseItem.SlugChar) != -1) { - var result = libraryManager.GetItemList(new InternalItemsQuery - { - SlugName = name, - IncludeItemTypes = new[] { typeof(Genre).Name }, - DtoOptions = dtoOptions - - }).OfType().FirstOrDefault(); + var result = GetItemFromSlugName(libraryManager, name, dtoOptions); if (result != null) { @@ -241,13 +223,7 @@ namespace MediaBrowser.Api { if (name.IndexOf(BaseItem.SlugChar) != -1) { - var result = libraryManager.GetItemList(new InternalItemsQuery - { - SlugName = name, - IncludeItemTypes = new[] { typeof(MusicGenre).Name }, - DtoOptions = dtoOptions - - }).OfType().FirstOrDefault(); + var result = GetItemFromSlugName(libraryManager, name, dtoOptions); if (result != null) { @@ -262,13 +238,7 @@ namespace MediaBrowser.Api { if (name.IndexOf(BaseItem.SlugChar) != -1) { - var result = libraryManager.GetItemList(new InternalItemsQuery - { - SlugName = name, - IncludeItemTypes = new[] { typeof(GameGenre).Name }, - DtoOptions = dtoOptions - - }).OfType().FirstOrDefault(); + var result = GetItemFromSlugName(libraryManager, name, dtoOptions); if (result != null) { @@ -283,13 +253,7 @@ namespace MediaBrowser.Api { if (name.IndexOf(BaseItem.SlugChar) != -1) { - var result = libraryManager.GetItemList(new InternalItemsQuery - { - SlugName = name, - IncludeItemTypes = new[] { typeof(Person).Name }, - DtoOptions = dtoOptions - - }).OfType().FirstOrDefault(); + var result = GetItemFromSlugName(libraryManager, name, dtoOptions); if (result != null) { @@ -300,6 +264,42 @@ namespace MediaBrowser.Api return libraryManager.GetPerson(name); } + private T GetItemFromSlugName(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) + where T : BaseItem, new() + { + var result = libraryManager.GetItemList(new InternalItemsQuery + { + Name = name.Replace(BaseItem.SlugChar, '&'), + IncludeItemTypes = new[] { typeof(T).Name }, + DtoOptions = dtoOptions + + }).OfType().FirstOrDefault(); + + if (result == null) + { + result = libraryManager.GetItemList(new InternalItemsQuery + { + Name = name.Replace(BaseItem.SlugChar, '/'), + IncludeItemTypes = new[] { typeof(T).Name }, + DtoOptions = dtoOptions + + }).OfType().FirstOrDefault(); + } + + if (result == null) + { + result = libraryManager.GetItemList(new InternalItemsQuery + { + Name = name.Replace(BaseItem.SlugChar, '?'), + IncludeItemTypes = new[] { typeof(T).Name }, + DtoOptions = dtoOptions + + }).OfType().FirstOrDefault(); + } + + return result as T; + } + protected string GetPathValue(int index) { var pathInfo = Parse(Request.PathInfo); diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 4d96c082f..608e3f56c 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -56,7 +56,6 @@ namespace MediaBrowser.Controller.Entities public string Path { get; set; } public string PathNotStartsWith { get; set; } public string Name { get; set; } - public string SlugName { get; set; } public string Person { get; set; } public string[] PersonIds { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 87fc58130..9f55a9ff2 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -221,12 +221,6 @@ namespace MediaBrowser.Controller.LiveTv public override bool IsInternetMetadataEnabled() { - if (IsMovie) - { - var options = (LiveTvOptions)ConfigurationManager.GetConfiguration("livetv"); - return options.EnableMovieProviders; - } - return false; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index c14b1f416..60583b95b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -233,7 +233,12 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - return codec; + if (_mediaEncoder.SupportsDecoder(codec)) + { + return codec; + } + + return null; } /// diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 338f58c16..59f3576ec 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -92,7 +92,13 @@ namespace MediaBrowser.MediaEncoding.Encoder "mpeg2_qsv", "vc1_qsv", "h264_cuvid", - "hevc_cuvid" + "hevc_cuvid", + "dts", + "ac3", + "aac", + "mp3", + "h264", + "hevc" }; foreach (var codec in required) diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 91ea977f7..32153a11c 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -1,13 +1,11 @@ using System.Collections.Generic; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.LiveTv { public class LiveTvOptions { public int? GuideDays { get; set; } - public bool EnableMovieProviders { get; set; } public string RecordingPath { get; set; } public string MovieRecordingPath { get; set; } public string SeriesRecordingPath { get; set; } @@ -30,7 +28,6 @@ namespace MediaBrowser.Model.LiveTv public LiveTvOptions() { - EnableMovieProviders = true; TunerHosts = new List(); ListingProviders = new List(); MediaLocationsCreated = new string[] { }; diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 2a987ceb1..e2a75c56b 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -70,6 +70,8 @@ namespace MediaBrowser.Model.Users public UserPolicy() { + EnableContentDeletion = true; + EnableSyncTranscoding = true; EnableMediaPlayback = true; -- cgit v1.2.3 From a107ff0369e5cade3dc2848f190a95b5be302a0b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 24 Jun 2017 14:33:19 -0400 Subject: capture more transcoding info --- MediaBrowser.Api/ApiEntryPoint.cs | 3 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 + MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 5 + MediaBrowser.Api/Playback/MediaInfoService.cs | 2 + MediaBrowser.Api/Playback/UniversalAudioService.cs | 7 +- MediaBrowser.Controller/Entities/Folder.cs | 8 +- .../MediaEncoding/EncodingJobInfo.cs | 22 +- .../MediaEncoding/EncodingJobOptions.cs | 2 + .../Configuration/UserConfiguration.cs | 1 - MediaBrowser.Model/Dlna/ProfileCondition.cs | 1 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 271 +++++++++++++++++++-- MediaBrowser.Model/Dlna/StreamInfo.cs | 20 +- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 4 + MediaBrowser.Model/Session/TranscodingInfo.cs | 33 +++ 14 files changed, 338 insertions(+), 45 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index e4abe96f3..34d0bd413 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -265,7 +265,8 @@ namespace MediaBrowser.Api Height = state.OutputHeight, AudioChannels = state.OutputAudioChannels, IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase), - IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) + IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase), + TranscodeReasons = state.TranscodeReasons }); } } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index bbee36199..e4ef294d1 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -583,6 +583,10 @@ namespace MediaBrowser.Api.Playback videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } } + else if (i == 33) + { + request.TranscodeReasons = val; + } } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index ddd2d8cd2..c6282bbad 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -541,6 +541,11 @@ namespace MediaBrowser.Api.Playback.Hls { queryString += "&SegmentContainer=" + state.Request.SegmentContainer; } + // from universal audio service + if (!string.IsNullOrWhiteSpace(state.Request.TranscodeReasons) && queryString.IndexOf("TranscodeReasons=", StringComparison.OrdinalIgnoreCase) == -1) + { + queryString += "&TranscodeReasons=" + state.Request.TranscodeReasons; + } // Main stream var playlistUrl = isLiveStream ? "live.m3u8" : "main.m3u8"; diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index bba8094b6..6853ddbeb 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -513,6 +513,8 @@ namespace MediaBrowser.Api.Playback var profiles = info.GetSubtitleProfiles(false, "-", accessToken); mediaSource.DefaultSubtitleStreamIndex = info.SubtitleStreamIndex; + mediaSource.TranscodeReasons = info.TranscodeReasons; + foreach (var profile in profiles) { foreach (var stream in mediaSource.MediaStreams) diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index fffec6948..b9bcd106e 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Threading.Tasks; using MediaBrowser.Api.Playback.Hls; using MediaBrowser.Api.Playback.Progressive; @@ -265,7 +266,8 @@ namespace MediaBrowser.Api.Playback Static = isStatic, SegmentContainer = request.TranscodingContainer, AudioSampleRate = request.MaxAudioSampleRate, - BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames + BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames, + TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()) }; if (isHeadRequest) @@ -307,7 +309,8 @@ namespace MediaBrowser.Api.Playback PlaySessionId = playbackInfoResult.PlaySessionId, StartTimeTicks = request.StartTimeTicks, Static = isStatic, - AudioSampleRate = request.MaxAudioSampleRate + AudioSampleRate = request.MaxAudioSampleRate, + TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()) }; if (isHeadRequest) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 34b33fde0..ea442ba1e 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -487,7 +487,7 @@ namespace MediaBrowser.Controller.Entities var folder = this; innerProgress.RegisterAction(p => { - double newPct = .70 * p + 10; + double newPct = .80 * p + 10; progress.Report(newPct); ProviderManager.OnRefreshProgress(folder, newPct); }); @@ -498,11 +498,11 @@ namespace MediaBrowser.Controller.Entities if (refreshChildMetadata) { - progress.Report(80); + progress.Report(90); if (recursive) { - ProviderManager.OnRefreshProgress(this, 80); + ProviderManager.OnRefreshProgress(this, 90); } var container = this as IMetadataContainer; @@ -512,7 +512,7 @@ namespace MediaBrowser.Controller.Entities var folder = this; innerProgress.RegisterAction(p => { - double newPct = .20 * p + 80; + double newPct = .10 * p + 90; progress.Report(newPct); if (recursive) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 57c81ddf7..a83a6a15e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; @@ -9,6 +10,7 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Session; namespace MediaBrowser.Controller.MediaEncoding { @@ -40,6 +42,24 @@ namespace MediaBrowser.Controller.MediaEncoding public bool ReadInputAtNativeFramerate { get; set; } + private List _transcodeReasons = null; + public List TranscodeReasons + { + get + { + if (_transcodeReasons == null) + { + _transcodeReasons = (BaseRequest.TranscodeReasons ?? string.Empty) + .Split(',') + .Where(i => !string.IsNullOrWhiteSpace(i)) + .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true)) + .ToList(); + } + + return _transcodeReasons; + } + } + public bool IgnoreInputDts { get @@ -251,7 +271,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return AudioStream.SampleRate; } - } + } else if (BaseRequest.AudioSampleRate.HasValue) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 632c350ad..28ef66566 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -204,6 +204,8 @@ namespace MediaBrowser.Controller.MediaEncoding public string SubtitleCodec { get; set; } + public string TranscodeReasons { get; set; } + /// /// Gets or sets the index of the audio stream. /// diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 5567063fe..30b5f384f 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -55,7 +55,6 @@ namespace MediaBrowser.Model.Configuration HidePlayedInLatest = true; PlayDefaultAudioTrack = true; - DisplayMissingEpisodes = true; LatestItemsExcludes = new string[] { }; OrderedViews = new string[] { }; diff --git a/MediaBrowser.Model/Dlna/ProfileCondition.cs b/MediaBrowser.Model/Dlna/ProfileCondition.cs index 3d104f9c4..9234a2713 100644 --- a/MediaBrowser.Model/Dlna/ProfileCondition.cs +++ b/MediaBrowser.Model/Dlna/ProfileCondition.cs @@ -1,5 +1,4 @@ using System.Xml.Serialization; -using MediaBrowser.Model.Dlna; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 0ecc413f2..b758d5ed5 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -105,8 +105,99 @@ namespace MediaBrowser.Model.Dlna return null; } + private TranscodeReason? GetTranscodeReasonForFailedCondition(ProfileCondition condition) + { + switch (condition.Property) + { + case ProfileConditionValue.AudioBitrate: + if (condition.Condition == ProfileConditionType.LessThanEqual) + { + return TranscodeReason.AudioBitrateNotSupported; + } + return TranscodeReason.AudioBitrateNotSupported; + + case ProfileConditionValue.AudioChannels: + if (condition.Condition == ProfileConditionType.LessThanEqual) + { + return TranscodeReason.AudioChannelsNotSupported; + } + return TranscodeReason.AudioChannelsNotSupported; + + case ProfileConditionValue.AudioProfile: + return TranscodeReason.AudioProfileNotSupported; + + case ProfileConditionValue.AudioSampleRate: + return TranscodeReason.AudioSampleRateNotSupported; + + case ProfileConditionValue.Has64BitOffsets: + // TODO + return null; + + case ProfileConditionValue.Height: + return TranscodeReason.VideoResolutionNotSupported; + + case ProfileConditionValue.IsAnamorphic: + return TranscodeReason.AnamorphicVideoNotSupported; + + case ProfileConditionValue.IsAvc: + // TODO + return null; + + case ProfileConditionValue.IsInterlaced: + return TranscodeReason.InterlacedVideoNotSupported; + + case ProfileConditionValue.IsSecondaryAudio: + return TranscodeReason.SecondaryAudioNotSupported; + + case ProfileConditionValue.NumAudioStreams: + // TODO + return null; + + case ProfileConditionValue.NumVideoStreams: + // TODO + return null; + + case ProfileConditionValue.PacketLength: + // TODO + return null; + + case ProfileConditionValue.RefFrames: + return TranscodeReason.RefFramesNotSupported; + + case ProfileConditionValue.VideoBitDepth: + return TranscodeReason.VideoBitDepthNotSupported; + + case ProfileConditionValue.VideoBitrate: + return TranscodeReason.VideoBitrateNotSupported; + + case ProfileConditionValue.VideoCodecTag: + return TranscodeReason.VideoCodecNotSupported; + + case ProfileConditionValue.VideoFramerate: + return TranscodeReason.VideoFramerateNotSupported; + + case ProfileConditionValue.VideoLevel: + return TranscodeReason.VideoLevelNotSupported; + + case ProfileConditionValue.VideoProfile: + return TranscodeReason.VideoProfileNotSupported; + + case ProfileConditionValue.VideoTimestamp: + // TODO + return null; + + case ProfileConditionValue.Width: + return TranscodeReason.VideoResolutionNotSupported; + + default: + return null; + } + } + private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options) { + List transcodeReasons = new List(); + StreamInfo playlistItem = new StreamInfo { ItemId = options.ItemId, @@ -133,7 +224,10 @@ namespace MediaBrowser.Model.Dlna MediaStream audioStream = item.GetDefaultAudioStream(null); - List directPlayMethods = GetAudioDirectPlayMethods(item, audioStream, options); + var directPlayInfo = GetAudioDirectPlayMethods(item, audioStream, options); + + List directPlayMethods = directPlayInfo.Item1; + transcodeReasons.AddRange(directPlayInfo.Item2); ConditionProcessor conditionProcessor = new ConditionProcessor(); @@ -180,6 +274,11 @@ namespace MediaBrowser.Model.Dlna if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate)) { LogConditionFailure(options.Profile, "AudioCodecProfile", c, item); + var transcodeReason = GetTranscodeReasonForFailedCondition(c); + if (transcodeReason.HasValue) + { + transcodeReasons.Add(transcodeReason.Value); + } all = false; break; } @@ -292,9 +391,9 @@ namespace MediaBrowser.Model.Dlna var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate); playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate); - } + playlistItem.TranscodeReasons = transcodeReasons; return playlistItem; } @@ -308,8 +407,10 @@ namespace MediaBrowser.Model.Dlna return options.GetMaxBitrate(isAudio); } - private List GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options) + private Tuple, List> GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options) { + List transcodeReasons = new List(); + DirectPlayProfile directPlayProfile = null; foreach (DirectPlayProfile i in options.Profile.DirectPlayProfiles) { @@ -325,27 +426,134 @@ namespace MediaBrowser.Model.Dlna if (directPlayProfile != null) { // While options takes the network and other factors into account. Only applies to direct stream - if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream) && options.EnableDirectStream) + if (item.SupportsDirectStream) { - playMethods.Add(PlayMethod.DirectStream); + if (IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream)) + { + if (options.EnableDirectStream) + { + playMethods.Add(PlayMethod.DirectStream); + } + } + else + { + transcodeReasons.Add(TranscodeReason.ContainerBitrateExceedsLimit); + } } // The profile describes what the device supports // If device requirements are satisfied then allow both direct stream and direct play - if (item.SupportsDirectPlay && - IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay) && options.EnableDirectPlay) + if (item.SupportsDirectPlay) { - playMethods.Add(PlayMethod.DirectPlay); + if (IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay)) + { + if (options.EnableDirectPlay) + { + playMethods.Add(PlayMethod.DirectPlay); + } + } + else + { + transcodeReasons.Add(TranscodeReason.ContainerBitrateExceedsLimit); + } } } else { + transcodeReasons.InsertRange(0, GetTranscodeReasonsFromDirectPlayProfile(item, null, audioStream, options.Profile.DirectPlayProfiles)); + _logger.Info("Profile: {0}, No direct play profiles found for Path: {1}", options.Profile.Name ?? "Unknown Profile", item.Path ?? "Unknown path"); } - return playMethods; + if (playMethods.Count > 0) + { + transcodeReasons.Clear(); + } + else + { + transcodeReasons = transcodeReasons.Distinct().ToList(); + } + + return new Tuple, List>(playMethods, transcodeReasons); + } + + private List GetTranscodeReasonsFromDirectPlayProfile(MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream, IEnumerable directPlayProfiles) + { + var list = new List(); + var containerSupported = false; + var audioSupported = false; + var videoSupported = false; + + foreach (var profile in directPlayProfiles) + { + if (profile.Container.Length > 0) + { + // Check container type + string mediaContainer = item.Container ?? string.Empty; + foreach (string i in profile.GetContainers()) + { + if (StringHelper.EqualsIgnoreCase(i, mediaContainer)) + { + containerSupported = true; + + if (videoStream != null) + { + // Check video codec + List videoCodecs = profile.GetVideoCodecs(); + if (videoCodecs.Count > 0) + { + string videoCodec = videoStream.Codec; + if (!string.IsNullOrEmpty(videoCodec) && ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec)) + { + videoSupported = true; + } + } + else + { + videoSupported = true; + } + } + + if (audioStream != null) + { + // Check audio codec + List audioCodecs = profile.GetAudioCodecs(); + if (audioCodecs.Count > 0) + { + string audioCodec = audioStream.Codec; + if (!string.IsNullOrEmpty(audioCodec) && ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec)) + { + audioSupported = true; + } + } + else + { + audioSupported = true; + } + } + } + } + } + } + + if (!containerSupported) + { + list.Add(TranscodeReason.ContainerNotSupported); + } + + if (videoStream != null && !videoSupported) + { + list.Add(TranscodeReason.VideoCodecNotSupported); + } + + if (audioStream != null && !audioSupported) + { + list.Add(TranscodeReason.VideoCodecNotSupported); + } + + return list; } private int? GetDefaultSubtitleStreamIndex(MediaSourceInfo item, SubtitleProfile[] subtitleProfiles) @@ -393,6 +601,8 @@ namespace MediaBrowser.Model.Dlna private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options) { + List transcodeReasons = new List(); + StreamInfo playlistItem = new StreamInfo { ItemId = options.ItemId, @@ -428,7 +638,8 @@ namespace MediaBrowser.Model.Dlna if (isEligibleForDirectPlay || isEligibleForDirectStream) { // See if it can be direct played - PlayMethod? directPlay = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); + var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); + var directPlay = directPlayInfo.Item1; if (directPlay != null) { @@ -445,6 +656,8 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } + + transcodeReasons.AddRange(directPlayInfo.Item2); } // Can't direct play, find the transcoding profile @@ -618,6 +831,8 @@ namespace MediaBrowser.Model.Dlna } } + playlistItem.TranscodeReasons = transcodeReasons; + return playlistItem; } @@ -677,7 +892,7 @@ namespace MediaBrowser.Model.Dlna return Math.Min(defaultBitrate, encoderAudioBitrateLimit); } - private PlayMethod? GetVideoDirectPlayProfile(VideoOptions options, + private Tuple> GetVideoDirectPlayProfile(VideoOptions options, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream, @@ -688,11 +903,11 @@ namespace MediaBrowser.Model.Dlna if (options.ForceDirectPlay) { - return PlayMethod.DirectPlay; + return new Tuple>(PlayMethod.DirectPlay, new List()); } if (options.ForceDirectStream) { - return PlayMethod.DirectStream; + return new Tuple>(PlayMethod.DirectStream, new List()); } if (videoStream == null) @@ -701,7 +916,7 @@ namespace MediaBrowser.Model.Dlna profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); - return null; + return new Tuple>(null, new List { TranscodeReason.UnknownVideoStreamInfo }); } // See if it can be direct played @@ -721,7 +936,7 @@ namespace MediaBrowser.Model.Dlna profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); - return null; + return new Tuple>(null, GetTranscodeReasonsFromDirectPlayProfile(mediaSource, videoStream, audioStream, profile.DirectPlayProfiles)); } string container = mediaSource.Container; @@ -784,7 +999,7 @@ namespace MediaBrowser.Model.Dlna profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); - return null; + return new Tuple>(null, new List { TranscodeReason.UnknownVideoStreamInfo }); } conditions = new List(); @@ -819,7 +1034,12 @@ namespace MediaBrowser.Model.Dlna { LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); - return null; + var transcodeReason = GetTranscodeReasonForFailedCondition(i); + var transcodeReasons = transcodeReason.HasValue + ? new List { transcodeReason.Value } + : new List { }; + + return new Tuple>(null, transcodeReasons); } } @@ -833,7 +1053,7 @@ namespace MediaBrowser.Model.Dlna profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); - return null; + return new Tuple>(null, new List { TranscodeReason.UnknownAudioStreamInfo }); } conditions = new List(); @@ -870,17 +1090,22 @@ namespace MediaBrowser.Model.Dlna { LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource); - return null; + var transcodeReason = GetTranscodeReasonForFailedCondition(i); + var transcodeReasons = transcodeReason.HasValue + ? new List { transcodeReason.Value } + : new List { }; + + return new Tuple>(null, transcodeReasons); } } } if (isEligibleForDirectStream && mediaSource.SupportsDirectStream) { - return PlayMethod.DirectStream; + return new Tuple>(PlayMethod.DirectStream, new List()); } - return null; + return new Tuple>(null, new List { TranscodeReason.ContainerBitrateExceedsLimit }); } private void LogConditionFailure(DeviceProfile profile, string type, ProfileCondition condition, MediaSourceInfo mediaSource) @@ -1047,12 +1272,12 @@ namespace MediaBrowser.Model.Dlna // Don't restrict by bitrate if coming from an external domain if (item.IsRemote) { - return true; + return true; } if (!maxBitrate.HasValue) { - _logger.Info("Cannot "+ playMethod + " due to unknown supported bitrate"); + _logger.Info("Cannot " + playMethod + " due to unknown supported bitrate"); return false; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index ba5251e8c..d70d89cf7 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -21,6 +21,7 @@ namespace MediaBrowser.Model.Dlna AudioCodecs = new string[] { }; VideoCodecs = new string[] { }; SubtitleCodecs = new string[] { }; + TranscodeReasons = new List(); } public string ItemId { get; set; } @@ -89,6 +90,7 @@ namespace MediaBrowser.Model.Dlna public string PlaySessionId { get; set; } public List AllMediaSources { get; set; } + public List TranscodeReasons { get; set; } public string MediaSourceId { @@ -231,22 +233,11 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); - var forceStartPosition = false; long startPositionTicks = item.StartPositionTicks; - //if (item.MediaSource.DateLiveStreamOpened.HasValue && startPositionTicks == 0) - //{ - // var elapsed = DateTime.UtcNow - item.MediaSource.DateLiveStreamOpened.Value; - // elapsed -= TimeSpan.FromSeconds(20); - // if (elapsed.TotalSeconds >= 0) - // { - // startPositionTicks = elapsed.Ticks + startPositionTicks; - // forceStartPosition = true; - // } - //} var isHls = StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls"); - if (isHls && !forceStartPosition) + if (isHls) { list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } @@ -310,6 +301,11 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString())); } + if (isDlna || !item.IsDirectStream) + { + list.Add(new NameValuePair("TranscodeReasons", string.Join(",", item.TranscodeReasons.Distinct().Select(i => i.ToString()).ToArray()))); + } + return list; } diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index c93eca0e7..08824913f 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -4,6 +4,7 @@ using MediaBrowser.Model.MediaInfo; using System.Collections.Generic; using System.Linq; using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Session; namespace MediaBrowser.Model.Dto { @@ -110,6 +111,9 @@ namespace MediaBrowser.Model.Dto } } + [IgnoreDataMember] + public List TranscodeReasons { get; set; } + public int? DefaultAudioStreamIndex { get; set; } public int? DefaultSubtitleStreamIndex { get; set; } diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index e646d80d3..67eac6fd5 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace MediaBrowser.Model.Session { public class TranscodingInfo @@ -15,5 +17,36 @@ namespace MediaBrowser.Model.Session public int? Width { get; set; } public int? Height { get; set; } public int? AudioChannels { get; set; } + + public List TranscodeReasons { get; set; } + + public TranscodingInfo() + { + TranscodeReasons = new List(); + } + } + + public enum TranscodeReason + { + ContainerNotSupported = 0, + VideoCodecNotSupported = 1, + AudioCodecNotSupported = 2, + ContainerBitrateExceedsLimit = 3, + AudioBitrateNotSupported = 4, + AudioChannelsNotSupported = 5, + VideoResolutionNotSupported = 6, + UnknownVideoStreamInfo = 7, + UnknownAudioStreamInfo = 8, + AudioProfileNotSupported = 9, + AudioSampleRateNotSupported = 10, + AnamorphicVideoNotSupported = 11, + InterlacedVideoNotSupported = 12, + SecondaryAudioNotSupported = 13, + RefFramesNotSupported = 14, + VideoBitDepthNotSupported = 15, + VideoBitrateNotSupported = 16, + VideoFramerateNotSupported = 17, + VideoLevelNotSupported = 18, + VideoProfileNotSupported = 19 } } \ No newline at end of file -- cgit v1.2.3 From a759b0957722d5971944f89f2184600b8147d217 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 26 Jun 2017 11:10:52 -0400 Subject: support max audio bit depth --- Emby.Dlna/Didl/DidlBuilder.cs | 5 ++++- Emby.Dlna/PlayTo/PlayToController.cs | 1 + MediaBrowser.Api/Playback/BaseStreamingService.cs | 3 ++- MediaBrowser.Api/Playback/UniversalAudioService.cs | 15 ++++++++++++++ .../MediaEncoding/EncodingJobInfo.cs | 23 ++++++++++++++++++++++ .../MediaEncoding/EncodingJobOptions.cs | 2 ++ .../Encoder/EncodingJobFactory.cs | 2 +- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 13 ++++++++---- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 4 +++- MediaBrowser.Model/Dlna/DeviceProfile.cs | 4 ++-- MediaBrowser.Model/Dlna/ProfileConditionValue.cs | 3 ++- MediaBrowser.Model/Dlna/StreamBuilder.cs | 18 +++++++++++------ MediaBrowser.Model/Dlna/StreamInfo.cs | 12 +++++++++++ MediaBrowser.Model/Session/TranscodingInfo.cs | 3 ++- 14 files changed, 90 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 4d003ca7c..3344bfcfe 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -472,6 +472,7 @@ namespace Emby.Dlna.Didl var targetAudioBitrate = streamInfo.TargetAudioBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; + var targetAudioBitDepth = streamInfo.TargetAudioBitDepth; if (targetChannels.HasValue) { @@ -492,7 +493,8 @@ namespace Emby.Dlna.Didl streamInfo.TargetAudioCodec, targetChannels, targetAudioBitrate, - targetSampleRate); + targetSampleRate, + targetAudioBitDepth); var filename = url.Substring(0, url.IndexOf('?')); @@ -505,6 +507,7 @@ namespace Emby.Dlna.Didl targetAudioBitrate, targetSampleRate, targetChannels, + targetAudioBitDepth, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TranscodeSeekInfo); diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 8c168dc23..15d73e824 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -532,6 +532,7 @@ namespace Emby.Dlna.PlayTo streamInfo.TargetAudioBitrate, streamInfo.TargetAudioSampleRate, streamInfo.TargetAudioChannels, + streamInfo.TargetAudioBitDepth, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TranscodeSeekInfo); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index e4ef294d1..8d01e4021 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -869,7 +869,7 @@ namespace MediaBrowser.Api.Playback var videoCodec = state.ActualOutputVideoCodec; var mediaProfile = state.VideoRequest == null ? - profile.GetAudioMediaProfile(state.OutputContainer, audioCodec, state.OutputAudioChannels, state.OutputAudioBitrate, state.OutputAudioSampleRate) : + profile.GetAudioMediaProfile(state.OutputContainer, audioCodec, state.OutputAudioChannels, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioBitDepth) : profile.GetVideoMediaProfile(state.OutputContainer, audioCodec, videoCodec, @@ -966,6 +966,7 @@ namespace MediaBrowser.Api.Playback state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioChannels, + state.OutputAudioBitDepth, isStaticallyStreamed, state.RunTimeTicks, state.TranscodeSeekInfo diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index b9bcd106e..118bf5246 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -52,6 +52,7 @@ namespace MediaBrowser.Api.Playback public string TranscodingContainer { get; set; } public string TranscodingProtocol { get; set; } public int? MaxAudioSampleRate { get; set; } + public int? MaxAudioBitDepth { get; set; } public bool EnableRedirection { get; set; } public bool EnableRemoteMedia { get; set; } @@ -164,6 +165,18 @@ namespace MediaBrowser.Api.Playback }); } + if (request.MaxAudioBitDepth.HasValue) + { + // codec profile + conditions.Add(new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + IsRequired = false, + Property = ProfileConditionValue.AudioBitDepth, + Value = request.MaxAudioBitDepth.Value.ToString(CultureInfo.InvariantCulture) + }); + } + if (request.MaxAudioChannels.HasValue) { // codec profile @@ -266,6 +279,7 @@ namespace MediaBrowser.Api.Playback Static = isStatic, SegmentContainer = request.TranscodingContainer, AudioSampleRate = request.MaxAudioSampleRate, + MaxAudioBitDepth = request.MaxAudioBitDepth, BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames, TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()) }; @@ -310,6 +324,7 @@ namespace MediaBrowser.Api.Playback StartTimeTicks = request.StartTimeTicks, Static = isStatic, AudioSampleRate = request.MaxAudioSampleRate, + MaxAudioBitDepth = request.MaxAudioBitDepth, TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()) }; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index a83a6a15e..b552579a8 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -284,6 +284,29 @@ namespace MediaBrowser.Controller.MediaEncoding } } + public int? OutputAudioBitDepth + { + get + { + if (BaseRequest.Static || string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + if (AudioStream != null) + { + return AudioStream.BitDepth; + } + } + + //else if (BaseRequest.AudioSampleRate.HasValue) + //{ + // // Don't exceed what the encoder supports + // // Seeing issues of attempting to encode to 88200 + // return Math.Min(44100, BaseRequest.AudioSampleRate.Value); + //} + + return null; + } + } + /// /// Predicts the audio sample rate that will be in the output stream /// diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 28ef66566..5fc93bf38 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -83,6 +83,8 @@ namespace MediaBrowser.Controller.MediaEncoding [ApiMember(Name = "AudioSampleRate", Description = "Optional. Specify a specific audio sample rate, e.g. 44100", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? AudioSampleRate { get; set; } + public int? MaxAudioBitDepth { get; set; } + /// /// Gets or sets the audio bit rate. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index ba5f625f5..50d3d254a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -262,7 +262,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var outputContainer = state.Options.OutputContainer; var mediaProfile = state.IsVideoRequest ? - profile.GetAudioMediaProfile(outputContainer, audioCodec, state.OutputAudioChannels, state.OutputAudioBitrate, state.OutputAudioSampleRate) : + profile.GetAudioMediaProfile(outputContainer, audioCodec, state.OutputAudioChannels, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioBitDepth) : profile.GetVideoMediaProfile(outputContainer, audioCodec, videoCodec, diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index a388bf98b..291096f75 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Dlna public bool IsVideoConditionSatisfied(ProfileCondition condition, int? width, int? height, - int? bitDepth, + int? videoBitDepth, int? videoBitrate, string videoProfile, double? videoLevel, @@ -46,7 +46,7 @@ namespace MediaBrowser.Model.Dlna case ProfileConditionValue.PacketLength: return IsConditionSatisfied(condition, packetLength); case ProfileConditionValue.VideoBitDepth: - return IsConditionSatisfied(condition, bitDepth); + return IsConditionSatisfied(condition, videoBitDepth); case ProfileConditionValue.VideoBitrate: return IsConditionSatisfied(condition, videoBitrate); case ProfileConditionValue.Height: @@ -79,7 +79,7 @@ namespace MediaBrowser.Model.Dlna } } - public bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, int? audioSampleRate) + public bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth) { switch (condition.Property) { @@ -89,6 +89,8 @@ namespace MediaBrowser.Model.Dlna return IsConditionSatisfied(condition, audioChannels); case ProfileConditionValue.AudioSampleRate: return IsConditionSatisfied(condition, audioSampleRate); + case ProfileConditionValue.AudioBitDepth: + return IsConditionSatisfied(condition, audioBitDepth); default: throw new ArgumentException("Unexpected condition on audio file: " + condition.Property); } @@ -97,7 +99,8 @@ namespace MediaBrowser.Model.Dlna public bool IsVideoAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, - int? audioSampleRate, + int? audioSampleRate, + int? audioBitDepth, string audioProfile, bool? isSecondaryTrack) { @@ -113,6 +116,8 @@ namespace MediaBrowser.Model.Dlna return IsConditionSatisfied(condition, isSecondaryTrack); case ProfileConditionValue.AudioSampleRate: return IsConditionSatisfied(condition, audioSampleRate); + case ProfileConditionValue.AudioBitDepth: + return IsConditionSatisfied(condition, audioBitDepth); default: throw new ArgumentException("Unexpected condition on audio file: " + condition.Property); } diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 6f6994a7e..8a9dc1dd1 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -55,6 +55,7 @@ namespace MediaBrowser.Model.Dlna int? audioBitrate, int? audioSampleRate, int? audioChannels, + int? audioBitDepth, bool isDirectStream, long? runtimeTicks, TranscodeSeekInfo transcodeSeekInfo) @@ -86,7 +87,8 @@ namespace MediaBrowser.Model.Dlna audioCodec, audioChannels, audioBitrate, - audioSampleRate); + audioSampleRate, + audioBitDepth); string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn; diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 33d73e3bb..cd7ff08d6 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -185,7 +185,7 @@ namespace MediaBrowser.Model.Dlna return null; } - public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate) + public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth) { container = StringHelper.TrimStart(container ?? string.Empty, '.'); @@ -213,7 +213,7 @@ namespace MediaBrowser.Model.Dlna var anyOff = false; foreach (ProfileCondition c in i.Conditions) { - if (!conditionProcessor.IsAudioConditionSatisfied(GetModelProfileCondition(c), audioChannels, audioBitrate, audioSampleRate)) + if (!conditionProcessor.IsAudioConditionSatisfied(GetModelProfileCondition(c), audioChannels, audioBitrate, audioSampleRate, audioBitDepth)) { anyOff = true; break; diff --git a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs index 208a7df7e..a96e9ac36 100644 --- a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs +++ b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs @@ -23,6 +23,7 @@ VideoCodecTag = 19, IsAvc = 20, IsInterlaced = 21, - AudioSampleRate = 22 + AudioSampleRate = 22, + AudioBitDepth = 23 } } \ No newline at end of file diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index ebfeb358e..342796a10 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -167,6 +167,9 @@ namespace MediaBrowser.Model.Dlna case ProfileConditionValue.VideoBitDepth: return TranscodeReason.VideoBitDepthNotSupported; + case ProfileConditionValue.AudioBitDepth: + return TranscodeReason.AudioBitDepthNotSupported; + case ProfileConditionValue.VideoBitrate: return TranscodeReason.VideoBitrateNotSupported; @@ -234,6 +237,7 @@ namespace MediaBrowser.Model.Dlna int? inputAudioChannels = audioStream == null ? null : audioStream.Channels; int? inputAudioBitrate = audioStream == null ? null : audioStream.BitDepth; int? inputAudioSampleRate = audioStream == null ? null : audioStream.SampleRate; + int? inputAudioBitDepth = audioStream == null ? null : audioStream.BitDepth; if (directPlayMethods.Count > 0) { @@ -250,7 +254,7 @@ namespace MediaBrowser.Model.Dlna bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { - if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate)) + if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth)) { LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item); applyConditions = false; @@ -271,7 +275,7 @@ namespace MediaBrowser.Model.Dlna bool all = true; foreach (ProfileCondition c in conditions) { - if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate)) + if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth)) { LogConditionFailure(options.Profile, "AudioCodecProfile", c, item); var transcodeReason = GetTranscodeReasonForFailedCondition(c); @@ -351,7 +355,7 @@ namespace MediaBrowser.Model.Dlna bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { - if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate)) + if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth)) { LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item); applyConditions = false; @@ -734,8 +738,9 @@ namespace MediaBrowser.Model.Dlna int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; int? inputAudioSampleRate = audioStream == null ? null : audioStream.SampleRate; + int? inputAudioBitDepth = audioStream == null ? null : audioStream.BitDepth; - if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, audioProfile, isSecondaryAudio)) + if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio)) { LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item); applyConditions = false; @@ -972,6 +977,7 @@ namespace MediaBrowser.Model.Dlna int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; int? audioSampleRate = audioStream == null ? null : audioStream.SampleRate; + int? audioBitDepth = audioStream == null ? null : audioStream.BitDepth; TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; int? packetLength = videoStream == null ? null : videoStream.PacketLength; @@ -1066,7 +1072,7 @@ namespace MediaBrowser.Model.Dlna bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { - if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, audioBitrate, audioSampleRate, audioProfile, isSecondaryAudio)) + if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, audioBitrate, audioSampleRate, audioBitDepth, audioProfile, isSecondaryAudio)) { LogConditionFailure(profile, "VideoAudioCodecProfile", applyCondition, mediaSource); applyConditions = false; @@ -1086,7 +1092,7 @@ namespace MediaBrowser.Model.Dlna foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioSampleRate, audioProfile, isSecondaryAudio)) + if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioSampleRate, audioBitDepth, audioProfile, isSecondaryAudio)) { LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource); diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index d70d89cf7..9c8e8b030 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -477,6 +477,18 @@ namespace MediaBrowser.Model.Dlna } } + /// + /// Predicts the audio sample rate that will be in the output stream + /// + public int? TargetAudioBitDepth + { + get + { + MediaStream stream = TargetAudioStream; + return stream == null ? null : stream.BitDepth; + } + } + /// /// Predicts the audio sample rate that will be in the output stream /// diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index 67eac6fd5..f1cbacd90 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -47,6 +47,7 @@ namespace MediaBrowser.Model.Session VideoBitrateNotSupported = 16, VideoFramerateNotSupported = 17, VideoLevelNotSupported = 18, - VideoProfileNotSupported = 19 + VideoProfileNotSupported = 19, + AudioBitDepthNotSupported = 20 } } \ No newline at end of file -- cgit v1.2.3 From 71308b5c29da6506bc294a6b4eb1f4a5b86ce0bd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 27 Jun 2017 16:56:47 -0400 Subject: fix -tp format command line --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 4 ++++ SharedVersion.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 60583b95b..44bdafc5b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -201,6 +201,10 @@ namespace MediaBrowser.Controller.MediaEncoding { return null; } + if (string.Equals(container, "tp", StringComparison.OrdinalIgnoreCase)) + { + return null; + } // Seeing reported failures here, not sure yet if this is related to specfying input format if (string.Equals(container, "m4v", StringComparison.OrdinalIgnoreCase)) diff --git a/SharedVersion.cs b/SharedVersion.cs index 54c495e32..a7aafdb10 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.20.14")] +[assembly: AssemblyVersion("3.2.20.15")] -- cgit v1.2.3