diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index fc48e9a3a..503f9927c 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -135,6 +135,7 @@ + diff --git a/MediaBrowser.Model/Sync/SyncHelper.cs b/MediaBrowser.Api/Sync/SyncHelper.cs similarity index 97% rename from MediaBrowser.Model/Sync/SyncHelper.cs rename to MediaBrowser.Api/Sync/SyncHelper.cs index 34a5ba995..d0a866c02 100644 --- a/MediaBrowser.Model/Sync/SyncHelper.cs +++ b/MediaBrowser.Api/Sync/SyncHelper.cs @@ -1,7 +1,8 @@ using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Sync; using System.Collections.Generic; -namespace MediaBrowser.Model.Sync +namespace MediaBrowser.Api.Sync { public static class SyncHelper { diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 06f18729b..beb64b373 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -397,6 +397,7 @@ + diff --git a/MediaBrowser.Controller/Sync/SyncJobOptions.cs b/MediaBrowser.Controller/Sync/SyncJobOptions.cs new file mode 100644 index 000000000..abd6d2553 --- /dev/null +++ b/MediaBrowser.Controller/Sync/SyncJobOptions.cs @@ -0,0 +1,19 @@ +using MediaBrowser.Model.Dlna; + +namespace MediaBrowser.Controller.Sync +{ + public class SyncJobOptions + where T : AudioOptions, new () + { + /// + /// Gets or sets the conversion options. + /// + /// The conversion options. + public T ConversionOptions { get; set; } + /// + /// Gets or sets a value indicating whether this instance is converting. + /// + /// true if this instance is converting; otherwise, false. + public bool IsConverting { get; set; } + } +} diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index f60f227d7..c2d46b9b3 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -1100,9 +1100,6 @@ Sync\SyncedItem.cs - - Sync\SyncHelper.cs - Sync\SyncJob.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 1685d5f7b..129c667a0 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -1059,9 +1059,6 @@ Sync\SyncedItem.cs - - Sync\SyncHelper.cs - Sync\SyncJob.cs diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c546958aa..3a6eda620 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -387,7 +387,6 @@ - diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index c4ef3e9de..1915814e1 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -231,6 +231,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs index ff43816b0..016ad19eb 100644 --- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Devices; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Sync; -using System; using System.Collections.Generic; using System.Linq; @@ -37,21 +36,7 @@ namespace MediaBrowser.Server.Implementations.Sync var caps = _deviceManager.GetCapabilities(target.Id); var deviceProfile = caps == null || caps.DeviceProfile == null ? new DeviceProfile() : caps.DeviceProfile; - var maxBitrate = deviceProfile.MaxStaticBitrate; - - if (maxBitrate.HasValue) - { - if (string.Equals(quality, "medium", StringComparison.OrdinalIgnoreCase)) - { - maxBitrate = Convert.ToInt32(maxBitrate.Value * .75); - } - else if (string.Equals(quality, "low", StringComparison.OrdinalIgnoreCase)) - { - maxBitrate = Convert.ToInt32(maxBitrate.Value * .5); - } - - deviceProfile.MaxStaticBitrate = maxBitrate; - } + deviceProfile.MaxStaticBitrate = SyncHelper.AdjustBitrate(deviceProfile.MaxStaticBitrate, quality); return deviceProfile; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs b/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs new file mode 100644 index 000000000..6bcb27328 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs @@ -0,0 +1,33 @@ +using System; +using System.Globalization; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class SyncHelper + { + public static int? AdjustBitrate(int? profileBitrate, string quality) + { + if (profileBitrate.HasValue) + { + if (string.Equals(quality, "medium", StringComparison.OrdinalIgnoreCase)) + { + profileBitrate = Convert.ToInt32(profileBitrate.Value * .75); + } + else if (string.Equals(quality, "low", StringComparison.OrdinalIgnoreCase)) + { + profileBitrate = Convert.ToInt32(profileBitrate.Value*.5); + } + else + { + int value; + if (int.TryParse(quality, NumberStyles.Any, CultureInfo.InvariantCulture, out value)) + { + profileBitrate = value; + } + } + } + + return profileBitrate; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 8fb4b5a3a..aecd9280d 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -476,22 +476,17 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private bool IsOriginalQuality(SyncJob job) - { - return string.IsNullOrWhiteSpace(job.Quality) || - string.Equals(job.Quality, "original", StringComparison.OrdinalIgnoreCase); - } - private async Task Sync(SyncJobItem jobItem, SyncJob job, Video item, User user, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { - var options = _syncManager.GetVideoOptions(jobItem, job); + var jobOptions = _syncManager.GetVideoOptions(jobItem, job); + var conversionOptions = jobOptions.ConversionOptions; - options.DeviceId = jobItem.TargetId; - options.Context = EncodingContext.Static; - options.ItemId = item.Id.ToString("N"); - options.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); + conversionOptions.DeviceId = jobItem.TargetId; + conversionOptions.Context = EncodingContext.Static; + conversionOptions.ItemId = item.Id.ToString("N"); + conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - var streamInfo = new StreamBuilder().BuildVideoItem(options); + var streamInfo = new StreamBuilder().BuildVideoItem(conversionOptions); var mediaSource = streamInfo.MediaSource; // No sense creating external subs if we're already burning one into the video @@ -500,7 +495,7 @@ namespace MediaBrowser.Server.Implementations.Sync streamInfo.GetExternalSubtitles(false); // Mark as requiring conversion if transcoding the video, or if any subtitles need to be extracted - var requiresVideoTranscoding = streamInfo.PlayMethod == PlayMethod.Transcode && IsOriginalQuality(job); + var requiresVideoTranscoding = streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting; var requiresConversion = requiresVideoTranscoding || externalSubs.Any(i => RequiresExtraction(i, mediaSource)); if (requiresConversion && !enableConversion) @@ -538,7 +533,7 @@ namespace MediaBrowser.Server.Implementations.Sync } }); - jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, options.Profile) + jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, conversionOptions.Profile) { OutputDirectory = jobItem.TemporaryPath @@ -676,20 +671,21 @@ namespace MediaBrowser.Server.Implementations.Sync private async Task Sync(SyncJobItem jobItem, SyncJob job, Audio item, User user, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { - var options = _syncManager.GetAudioOptions(jobItem, job); + var jobOptions = _syncManager.GetAudioOptions(jobItem, job); + var conversionOptions = jobOptions.ConversionOptions; - options.DeviceId = jobItem.TargetId; - options.Context = EncodingContext.Static; - options.ItemId = item.Id.ToString("N"); - options.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); + conversionOptions.DeviceId = jobItem.TargetId; + conversionOptions.Context = EncodingContext.Static; + conversionOptions.ItemId = item.Id.ToString("N"); + conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - var streamInfo = new StreamBuilder().BuildAudioItem(options); + var streamInfo = new StreamBuilder().BuildAudioItem(conversionOptions); var mediaSource = streamInfo.MediaSource; jobItem.MediaSourceId = streamInfo.MediaSourceId; jobItem.TemporaryPath = GetTemporaryPath(jobItem); - if (streamInfo.PlayMethod == PlayMethod.Transcode && !IsOriginalQuality(job)) + if (streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting) { if (!enableConversion) { @@ -716,7 +712,7 @@ namespace MediaBrowser.Server.Implementations.Sync } }); - jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, options.Profile) + jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, conversionOptions.Profile) { OutputDirectory = jobItem.TemporaryPath diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 19e3841d1..0ec05a0aa 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -982,23 +982,34 @@ namespace MediaBrowser.Server.Implementations.Sync return _repo.GetLibraryItemIds(query); } - public AudioOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) + private bool IsOriginalQuality(SyncJob job) { - var profile = GetDeviceProfile(jobItem.TargetId, null, null); - - return new AudioOptions + return string.IsNullOrWhiteSpace(job.Quality) || + string.Equals(job.Quality, "original", StringComparison.OrdinalIgnoreCase) || + string.Equals(job.Profile, "original", StringComparison.OrdinalIgnoreCase); + } + + public SyncJobOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) + { + return new SyncJobOptions { - Profile = profile + ConversionOptions = new AudioOptions + { + Profile = GetDeviceProfile(jobItem.TargetId, null, null) + }, + IsConverting = !IsOriginalQuality(job) }; } - public VideoOptions GetVideoOptions(SyncJobItem jobItem, SyncJob job) + public SyncJobOptions GetVideoOptions(SyncJobItem jobItem, SyncJob job) { - var profile = GetDeviceProfile(jobItem.TargetId, job.Profile, job.Quality); - - return new VideoOptions + return new SyncJobOptions { - Profile = profile + ConversionOptions = new VideoOptions + { + Profile = GetDeviceProfile(jobItem.TargetId, job.Profile, job.Quality) + }, + IsConverting = !IsOriginalQuality(job) }; } @@ -1033,21 +1044,7 @@ namespace MediaBrowser.Server.Implementations.Sync private DeviceProfile GetDeviceProfile(string profile, string quality) { var deviceProfile = new CloudSyncProfile(true, false); - var maxBitrate = deviceProfile.MaxStaticBitrate; - - if (maxBitrate.HasValue) - { - if (string.Equals(quality, "medium", StringComparison.OrdinalIgnoreCase)) - { - maxBitrate = Convert.ToInt32(maxBitrate.Value * .75); - } - else if (string.Equals(quality, "low", StringComparison.OrdinalIgnoreCase)) - { - maxBitrate = Convert.ToInt32(maxBitrate.Value * .5); - } - - deviceProfile.MaxStaticBitrate = maxBitrate; - } + deviceProfile.MaxStaticBitrate = SyncHelper.AdjustBitrate(deviceProfile.MaxStaticBitrate, quality); return deviceProfile; } @@ -1139,16 +1136,16 @@ namespace MediaBrowser.Server.Implementations.Sync list.Add(new SyncProfileOption { - Name = "Web - H264/AAC, MP3", - Id = "mobile", - Description = "Designed for compatibility with all devices, including web browsers." + Name = "Baseline", + Id = "baseline", + Description = "Designed for compatibility with all devices, including web browsers. Targets H264/AAC video and MP3 audio." }); list.Add(new SyncProfileOption { - Name = "General - H264/AAC/AC3, MP3", + Name = "General", Id = "general", - Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices.", + Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices. Targets H264/AAC/AC3 video and MP3 audio.", IsDefault = true });