aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2017-10-01 23:35:45 -0400
committerGitHub <noreply@github.com>2017-10-01 23:35:45 -0400
commita73da532d52ae68ad01965dbf368bacc7d56a218 (patch)
treea6f05e95515f822dfc129c36554f74f1da4d4c23 /MediaBrowser.Controller
parentf651fd6ffba80a6f8e54fca7d014622692cc08f7 (diff)
parent796f374359d75e22d2095b3f3a8f9b220cacde27 (diff)
Merge pull request #2931 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs8
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/ImageHelper.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs2
-rw-r--r--MediaBrowser.Controller/Entities/BasePluginFolder.cs8
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs8
-rw-r--r--MediaBrowser.Controller/Entities/GameGenre.cs5
-rw-r--r--MediaBrowser.Controller/Entities/GameSystem.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Photo.cs29
-rw-r--r--MediaBrowser.Controller/Entities/PhotoAlbum.cs5
-rw-r--r--MediaBrowser.Controller/Entities/User.cs5
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs8
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs15
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs8
-rw-r--r--MediaBrowser.Controller/IO/StreamHelper.cs5
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs2
-rw-r--r--MediaBrowser.Controller/LiveTv/ITunerHost.cs15
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveStream.cs87
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs91
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs159
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs46
-rw-r--r--MediaBrowser.Controller/TV/ITVSeriesManager.cs2
25 files changed, 350 insertions, 187 deletions
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 54faa1443..f74c01994 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -32,6 +32,14 @@ namespace MediaBrowser.Controller.Channels
return base.IsVisible(user);
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ double value = 16;
+ value /= 9;
+
+ return value;
+ }
+
[IgnoreDataMember]
public override bool SupportsInheritedParentImages
{
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index d7b68d1e7..542fa5e08 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -117,8 +117,6 @@ namespace MediaBrowser.Controller.Drawing
IImageEncoder ImageEncoder { get; set; }
- void SaveImageSize(string path, DateTime imageDateModified, ImageSize size);
-
bool SupportsTransparency(string path);
}
}
diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs
index 9452446a1..9936b1036 100644
--- a/MediaBrowser.Controller/Drawing/ImageHelper.cs
+++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs
@@ -21,11 +21,6 @@ namespace MediaBrowser.Controller.Drawing
public static IImageProcessor ImageProcessor { get; set; }
- public static void SaveImageSize(string path, DateTime dateModified, ImageSize size)
- {
- ImageProcessor.SaveImageSize(path, dateModified, size);
- }
-
private static ImageSize GetSizeEstimate(ImageProcessingOptions options)
{
if (options.Width.HasValue && options.Height.HasValue)
diff --git a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
index cdb6f3f61..d2b4569ba 100644
--- a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
+++ b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
@@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public override double? GetDefaultPrimaryImageAspectRatio()
{
- return null;
+ return 1;
}
}
}
diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
index a61862f28..c06f1cef4 100644
--- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs
+++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
@@ -42,5 +42,13 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ //public override double? GetDefaultPrimaryImageAspectRatio()
+ //{
+ // double value = 16;
+ // value /= 9;
+
+ // return value;
+ //}
}
}
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index a83e084db..5fb9e517c 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -31,6 +31,14 @@ namespace MediaBrowser.Controller.Entities
PhysicalFolderIds = EmptyGuidArray;
}
+ //public override double? GetDefaultPrimaryImageAspectRatio()
+ //{
+ // double value = 16;
+ // value /= 9;
+
+ // return value;
+ //}
+
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs
index 4e78a7fa5..6dc85f3e5 100644
--- a/MediaBrowser.Controller/Entities/GameGenre.cs
+++ b/MediaBrowser.Controller/Entities/GameGenre.cs
@@ -22,6 +22,11 @@ namespace MediaBrowser.Controller.Entities
return GetUserDataKeys()[0];
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ return 1;
+ }
+
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs
index bbaec14a1..c940b5953 100644
--- a/MediaBrowser.Controller/Entities/GameSystem.cs
+++ b/MediaBrowser.Controller/Entities/GameSystem.cs
@@ -44,6 +44,14 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ double value = 16;
+ value /= 9;
+
+ return value;
+ }
+
/// <summary>
/// Gets or sets the game system.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index 790f8938e..569a0dfb8 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -25,6 +25,11 @@ namespace MediaBrowser.Controller.Entities
return GetUserDataKeys()[0];
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ return 1;
+ }
+
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 8e9eac50c..11db633ba 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -62,6 +62,35 @@ namespace MediaBrowser.Controller.Entities
return true;
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ if (Width.HasValue && Height.HasValue)
+ {
+ double width = Width.Value;
+ double height = Height.Value;
+
+ if (Orientation.HasValue)
+ {
+ switch (Orientation.Value)
+ {
+ case ImageOrientation.LeftBottom:
+ case ImageOrientation.LeftTop:
+ case ImageOrientation.RightBottom:
+ case ImageOrientation.RightTop:
+ var temp = height;
+ height = width;
+ width = temp;
+ break;
+ }
+ }
+
+ width /= Height.Value;
+ return width;
+ }
+
+ return base.GetDefaultPrimaryImageAspectRatio();
+ }
+
public int? Width { get; set; }
public int? Height { get; set; }
public string CameraMake { get; set; }
diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
index af9d8c801..52d743e36 100644
--- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs
+++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
@@ -30,5 +30,10 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ return 1;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index e9a794e79..36bbf6886 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -254,6 +254,11 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ return 1;
+ }
+
/// <summary>
/// Gets the configuration directory path.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 66174034d..2152e65cf 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -58,6 +58,14 @@ namespace MediaBrowser.Controller.Entities
}
}
+ //public override double? GetDefaultPrimaryImageAspectRatio()
+ //{
+ // double value = 16;
+ // value /= 9;
+
+ // return value;
+ //}
+
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count;
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 3ab82a103..43adc4af6 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -238,12 +238,9 @@ namespace MediaBrowser.Controller.Entities
{
if (queryParent is UserView)
{
- return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), queryParent, query);
- }
- else
- {
- return GetResult(queryParent.GetChildren(user, true), queryParent, query);
+ return GetResult(GetMediaFolders(user).OfType<Folder>().SelectMany(i => i.GetChildren(user, true)), queryParent, query);
}
+ return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
}
}
@@ -1681,7 +1678,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- private IEnumerable<Folder> GetMediaFolders(User user)
+ private IEnumerable<BaseItem> GetMediaFolders(User user)
{
if (user == null)
{
@@ -1696,7 +1693,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
}
- private List<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
+ private List<BaseItem> GetMediaFolders(User user, IEnumerable<string> viewTypes)
{
if (user == null)
{
@@ -1717,14 +1714,14 @@ namespace MediaBrowser.Controller.Entities
}).ToList();
}
- private List<Folder> GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
+ private List<BaseItem> GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
{
if (parent == null || parent is UserView)
{
return GetMediaFolders(user, viewTypes);
}
- return new List<Folder> { parent };
+ return new List<BaseItem> { parent };
}
private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index ffb601dc4..8693d867c 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -78,6 +78,14 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ double value = 16;
+ value /= 9;
+
+ return value;
+ }
+
public override string CreatePresentationUniqueKey()
{
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index 7d820b007..49b967104 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -32,6 +32,14 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public override double? GetDefaultPrimaryImageAspectRatio()
+ {
+ double value = 2;
+ value /= 3;
+
+ return value;
+ }
+
[IgnoreDataMember]
public override bool SupportsAncestors
{
diff --git a/MediaBrowser.Controller/IO/StreamHelper.cs b/MediaBrowser.Controller/IO/StreamHelper.cs
index af97a0233..106fec41f 100644
--- a/MediaBrowser.Controller/IO/StreamHelper.cs
+++ b/MediaBrowser.Controller/IO/StreamHelper.cs
@@ -6,11 +6,6 @@ namespace MediaBrowser.Controller.IO
{
public static class StreamHelper
{
- public static void CopyTo(Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken)
- {
- CopyTo(source, destination, bufferSize, null, cancellationToken);
- }
-
public static void CopyTo(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken)
{
byte[] buffer = new byte[bufferSize];
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 42c31c629..be85e115c 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -383,7 +383,7 @@ namespace MediaBrowser.Controller.LiveTv
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
string GetEmbyTvActiveRecordingPath(string id);
- Task<LiveStream> GetEmbyTvLiveStream(string id);
+ Task<ILiveStream> GetEmbyTvLiveStream(string id);
ActiveRecordingInfo GetActiveRecordingInfo(string path);
diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
index fc344298b..2019259c5 100644
--- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs
+++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="streamId">The stream identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
- Task<LiveStream> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
+ Task<ILiveStream> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel stream media sources.
/// </summary>
@@ -56,4 +56,17 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task.</returns>
Task Validate(TunerHostInfo info);
}
+
+ public interface ILiveStream
+ {
+ Task Open(CancellationToken cancellationToken);
+ Task Close();
+ int ConsumerCount { get; }
+ string OriginalStreamId { get; set; }
+ bool EnableStreamSharing { get; set; }
+ ITunerHost TunerHost { get; set; }
+ MediaSourceInfo OpenedMediaSource { get; set; }
+ string UniqueId { get; }
+ List<string> SharedStreamIds { get; }
+ }
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveStream.cs b/MediaBrowser.Controller/LiveTv/LiveStream.cs
deleted file mode 100644
index 20947462e..000000000
--- a/MediaBrowser.Controller/LiveTv/LiveStream.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.System;
-
-namespace MediaBrowser.Controller.LiveTv
-{
- public class LiveStream
- {
- public MediaSourceInfo OriginalMediaSource { get; set; }
- public MediaSourceInfo OpenedMediaSource { get; set; }
- public int ConsumerCount
- {
- get { return SharedStreamIds.Count; }
- }
- public ITunerHost TunerHost { get; set; }
- public string OriginalStreamId { get; set; }
- public bool EnableStreamSharing { get; set; }
- public string UniqueId = Guid.NewGuid().ToString("N");
-
- public List<string> SharedStreamIds = new List<string>();
- protected readonly IEnvironmentInfo Environment;
- protected readonly IFileSystem FileSystem;
- const int StreamCopyToBufferSize = 81920;
-
- public LiveStream(MediaSourceInfo mediaSource, IEnvironmentInfo environment, IFileSystem fileSystem)
- {
- OriginalMediaSource = mediaSource;
- Environment = environment;
- FileSystem = fileSystem;
- OpenedMediaSource = mediaSource;
- EnableStreamSharing = true;
- }
-
- public Task Open(CancellationToken cancellationToken)
- {
- return OpenInternal(cancellationToken);
- }
-
- protected virtual Task OpenInternal(CancellationToken cancellationToken)
- {
- return Task.FromResult(true);
- }
-
- public virtual Task Close()
- {
- return Task.FromResult(true);
- }
-
- protected Stream GetInputStream(string path, bool allowAsyncFileRead)
- {
- var fileOpenOptions = FileOpenOptions.SequentialScan;
-
- if (allowAsyncFileRead)
- {
- fileOpenOptions |= FileOpenOptions.Asynchronous;
- }
-
- return FileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, fileOpenOptions);
- }
-
- protected async Task DeleteTempFile(string path, int retryCount = 0)
- {
- try
- {
- FileSystem.DeleteFile(path);
- return;
- }
- catch
- {
-
- }
-
- if (retryCount > 20)
- {
- return;
- }
-
- await Task.Delay(500).ConfigureAwait(false);
- await DeleteTempFile(path, retryCount + 1).ConfigureAwait(false);
- }
- }
-}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 5ef763b62..b33993859 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -145,7 +145,6 @@
<Compile Include="Library\UserDataSaveEventArgs.cs" />
<Compile Include="LiveTv\IListingsProvider.cs" />
<Compile Include="LiveTv\ITunerHost.cs" />
- <Compile Include="LiveTv\LiveStream.cs" />
<Compile Include="LiveTv\RecordingGroup.cs" />
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
<Compile Include="LiveTv\ILiveTvRecording.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 657b9c959..8b612f809 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -346,7 +346,8 @@ namespace MediaBrowser.Controller.MediaEncoding
"Constrained High"
};
- return Array.FindIndex(list.ToArray(), t => string.Equals(t, profile, StringComparison.OrdinalIgnoreCase));
+ // strip spaces because they may be stripped out on the query string
+ return Array.FindIndex(list.ToArray(), t => string.Equals(t.Replace(" ", ""), profile.Replace(" ", ""), StringComparison.OrdinalIgnoreCase));
}
public string GetInputPathArgument(EncodingJobInfo state)
@@ -529,7 +530,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var seconds = Math.Round(TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds);
- var setPtsParam = state.CopyTimestamps
+ // hls always copies timestamps
+ var setPtsParam = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive
? string.Empty
: string.Format(",setpts=PTS -{0}/TB", seconds.ToString(_usCulture));
@@ -691,22 +693,26 @@ namespace MediaBrowser.Controller.MediaEncoding
param += string.Format(" -r {0}", framerate.Value.ToString(_usCulture));
}
- var request = state.BaseRequest;
+ var targetVideoCodec = state.ActualOutputVideoCodec;
- if (!string.IsNullOrEmpty(request.Profile))
+ var request = state.BaseRequest;
+ var profile = state.GetRequestedProfiles(targetVideoCodec).FirstOrDefault();
+ if (!string.IsNullOrEmpty(profile))
{
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
{
// not supported by h264_omx
- param += " -profile:v " + request.Profile;
+ param += " -profile:v " + profile;
}
}
- if (!string.IsNullOrEmpty(request.Level))
+ var level = state.GetRequestedLevel(targetVideoCodec);
+
+ if (!string.IsNullOrEmpty(level))
{
- var level = NormalizeTranscodingLevel(state.OutputVideoCodec, request.Level);
+ level = NormalizeTranscodingLevel(state.OutputVideoCodec, level);
// h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
// also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307
@@ -756,7 +762,6 @@ namespace MediaBrowser.Controller.MediaEncoding
{
param += " -level " + level;
}
-
}
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
@@ -796,7 +801,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (videoStream.IsInterlaced)
{
- if (request.DeInterlace)
+ if (state.DeInterlace(videoStream.Codec, false))
{
return false;
}
@@ -828,23 +833,27 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Source and target codecs must match
- if (string.IsNullOrEmpty(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase))
+ if (string.IsNullOrWhiteSpace(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase))
{
return false;
}
+ var requestedProfiles = state.GetRequestedProfiles(videoStream.Codec);
+
// If client is requesting a specific video profile, it must match the source
- if (!string.IsNullOrEmpty(request.Profile))
+ if (requestedProfiles.Length > 0)
{
- if (string.IsNullOrEmpty(videoStream.Profile))
+ if (string.IsNullOrWhiteSpace(videoStream.Profile))
{
//return false;
}
- if (!string.IsNullOrEmpty(videoStream.Profile) && !string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase))
+ var requestedProfile = requestedProfiles[0];
+ // strip spaces because they may be stripped out on the query string as well
+ if (!string.IsNullOrWhiteSpace(videoStream.Profile) && !requestedProfiles.Contains(videoStream.Profile.Replace(" ", ""), StringComparer.OrdinalIgnoreCase))
{
var currentScore = GetVideoProfileScore(videoStream.Profile);
- var requestedScore = GetVideoProfileScore(request.Profile);
+ var requestedScore = GetVideoProfileScore(requestedProfile);
if (currentScore == -1 || currentScore > requestedScore)
{
@@ -909,11 +918,12 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// If a specific level was requested, the source must match or be less than
- if (!string.IsNullOrEmpty(request.Level))
+ var level = state.GetRequestedLevel(videoStream.Codec);
+ if (!string.IsNullOrEmpty(level))
{
double requestLevel;
- if (double.TryParse(request.Level, NumberStyles.Any, _usCulture, out requestLevel))
+ if (double.TryParse(level, NumberStyles.Any, _usCulture, out requestLevel))
{
if (!videoStream.Level.HasValue)
{
@@ -1074,7 +1084,8 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && !state.CopyTimestamps)
+ var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive;
+ if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && !isCopyingTimestamps)
{
var seconds = TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds;
@@ -1357,9 +1368,10 @@ namespace MediaBrowser.Controller.MediaEncoding
filters.Add("hwupload");
}
- if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+ if (state.DeInterlace("h264", true) && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
- if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase))
+ // If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle
+ if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase) && (state.VideoStream.RealFrameRate ?? 60) <= 30)
{
filters.Add("yadif=1:-1:0");
}
@@ -1523,11 +1535,18 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <returns>System.Int32.</returns>
public int GetNumberOfThreads(EncodingJobInfo state, EncodingOptions encodingOptions, bool isWebm)
{
- var threads = GetNumberOfThreadsInternal(state, encodingOptions, isWebm);
+ if (isWebm)
+ {
+ // Recommended per docs
+ return Math.Max(Environment.ProcessorCount - 1, 2);
+ }
+
+ var threads = state.BaseRequest.CpuCoreLimit ?? encodingOptions.EncodingThreadCount;
- if (state.BaseRequest.CpuCoreLimit.HasValue && state.BaseRequest.CpuCoreLimit.Value > 0)
+ // Automatic
+ if (threads <= 0 || threads >= Environment.ProcessorCount)
{
- threads = Math.Min(threads, state.BaseRequest.CpuCoreLimit.Value);
+ return 0;
}
return threads;
@@ -1799,11 +1818,6 @@ namespace MediaBrowser.Controller.MediaEncoding
state.InternalSubtitleStreamOffset = mediaStreams.Where(i => i.Type == MediaStreamType.Subtitle && !i.IsExternal).ToList().IndexOf(state.SubtitleStream);
}
- if (state.VideoStream != null && state.VideoStream.IsInterlaced)
- {
- state.DeInterlace = true;
- }
-
EnforceResolutionLimit(state);
NormalizeSubtitleEmbed(state);
@@ -1954,29 +1968,6 @@ namespace MediaBrowser.Controller.MediaEncoding
return null;
}
- /// <summary>
- /// Gets the number of threads.
- /// </summary>
- /// <returns>System.Int32.</returns>
- private int GetNumberOfThreadsInternal(EncodingJobInfo state, EncodingOptions encodingOptions, bool isWebm)
- {
- var threads = encodingOptions.EncodingThreadCount;
-
- if (isWebm)
- {
- // Recommended per docs
- return Math.Max(Environment.ProcessorCount - 1, 2);
- }
-
- // Automatic
- if (threads == -1)
- {
- return 0;
- }
-
- return threads;
- }
-
public string GetSubtitleEmbedArguments(EncodingJobInfo state)
{
if (state.SubtitleStream == null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Embed)
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index e76217fda..506fce3ca 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -160,7 +160,97 @@ namespace MediaBrowser.Controller.MediaEncoding
public int? OutputAudioBitrate;
public int? OutputAudioChannels;
- public bool DeInterlace { get; set; }
+
+ public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
+ {
+ var videoStream = VideoStream;
+ var isInputInterlaced = videoStream != null && videoStream.IsInterlaced;
+
+ if (!isInputInterlaced)
+ {
+ return false;
+ }
+
+ // Support general param
+ if (BaseRequest.DeInterlace)
+ {
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(videoCodec))
+ {
+ if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ if (forceDeinterlaceIfSourceIsInterlaced)
+ {
+ if (isInputInterlaced)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public string[] GetRequestedProfiles(string codec)
+ {
+ if (!string.IsNullOrWhiteSpace(BaseRequest.Profile))
+ {
+ return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ if (!string.IsNullOrWhiteSpace(codec))
+ {
+ var profile = BaseRequest.GetOption(codec, "profile");
+
+ if (!string.IsNullOrWhiteSpace(profile))
+ {
+ return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ }
+
+ return new string[] { };
+ }
+
+ public string GetRequestedLevel(string codec)
+ {
+ if (!string.IsNullOrWhiteSpace(BaseRequest.Level))
+ {
+ return BaseRequest.Level;
+ }
+
+ if (!string.IsNullOrWhiteSpace(codec))
+ {
+ return BaseRequest.GetOption(codec, "level");
+ }
+
+ return null;
+ }
+
+ public int? GetRequestedMaxRefFrames(string codec)
+ {
+ if (!string.IsNullOrWhiteSpace(BaseRequest.Level))
+ {
+ return BaseRequest.MaxRefFrames;
+ }
+
+ if (!string.IsNullOrWhiteSpace(codec))
+ {
+ var value = BaseRequest.GetOption(codec, "maxrefframes");
+ int result;
+ if (!string.IsNullOrWhiteSpace(value) && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result))
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
public bool IsVideoRequest { get; set; }
public TranscodingJobType TranscodingType { get; set; }
@@ -169,7 +259,7 @@ namespace MediaBrowser.Controller.MediaEncoding
_logger = logger;
TranscodingType = jobType;
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- PlayableStreamFileNames = new string[]{};
+ PlayableStreamFileNames = new string[] { };
SupportedAudioCodecs = new List<string>();
SupportedVideoCodecs = new List<string>();
SupportedSubtitleCodecs = new List<string>();
@@ -319,12 +409,19 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
- var stream = VideoStream;
- var request = BaseRequest;
+ if (BaseRequest.Static)
+ {
+ return VideoStream == null ? null : VideoStream.Level;
+ }
- return !string.IsNullOrEmpty(request.Level) && !request.Static
- ? double.Parse(request.Level, CultureInfo.InvariantCulture)
- : stream == null ? null : stream.Level;
+ var level = GetRequestedLevel(ActualOutputVideoCodec);
+ double result;
+ if (!string.IsNullOrWhiteSpace(level) && double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out result))
+ {
+ return result;
+ }
+
+ return null;
}
}
@@ -348,8 +445,12 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
- var stream = VideoStream;
- return stream == null || !BaseRequest.Static ? null : stream.RefFrames;
+ if (BaseRequest.Static)
+ {
+ return VideoStream == null ? null : VideoStream.RefFrames;
+ }
+
+ return null;
}
}
@@ -404,10 +505,18 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
- var stream = VideoStream;
- return !string.IsNullOrEmpty(BaseRequest.Profile) && !BaseRequest.Static
- ? BaseRequest.Profile
- : stream == null ? null : stream.Profile;
+ if (BaseRequest.Static)
+ {
+ return VideoStream == null ? null : VideoStream.Profile;
+ }
+
+ var requestedProfile = GetRequestedProfiles(ActualOutputVideoCodec).FirstOrDefault();
+ if (!string.IsNullOrWhiteSpace(requestedProfile))
+ {
+ return requestedProfile;
+ }
+
+ return null;
}
}
@@ -435,6 +544,28 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
+ public string ActualOutputVideoCodec
+ {
+ get
+ {
+ var codec = OutputVideoCodec;
+
+ if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
+ {
+ var stream = VideoStream;
+
+ if (stream != null)
+ {
+ return stream.Codec;
+ }
+
+ return null;
+ }
+
+ return codec;
+ }
+ }
+
public bool? IsTargetInterlaced
{
get
@@ -444,7 +575,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
}
- if (DeInterlace)
+ if (DeInterlace(ActualOutputVideoCodec, true))
{
return false;
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
index 5fc93bf38..bac2a6e65 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
@@ -1,4 +1,7 @@
-using System.Globalization;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Services;
@@ -37,18 +40,16 @@ namespace MediaBrowser.Controller.MediaEncoding
MaxWidth = info.MaxWidth;
MaxHeight = info.MaxHeight;
MaxFramerate = info.MaxFramerate;
- Profile = info.VideoProfile;
ItemId = info.ItemId;
MediaSourceId = info.MediaSourceId;
- AudioCodec = info.TargetAudioCodec;
+ AudioCodec = info.TargetAudioCodec.FirstOrDefault();
MaxAudioChannels = info.MaxAudioChannels;
AudioBitRate = info.AudioBitrate;
AudioSampleRate = info.TargetAudioSampleRate;
DeviceProfile = deviceProfile;
- VideoCodec = info.TargetVideoCodec;
+ VideoCodec = info.TargetVideoCodec.FirstOrDefault();
VideoBitRate = info.VideoBitrate;
AudioStreamIndex = info.AudioStreamIndex;
- MaxRefFrames = info.MaxRefFrames;
MaxVideoBitDepth = info.MaxVideoBitDepth;
SubtitleMethod = info.SubtitleDeliveryMethod;
Context = info.Context;
@@ -58,11 +59,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
SubtitleStreamIndex = info.SubtitleStreamIndex;
}
-
- if (info.VideoLevel.HasValue)
- {
- Level = info.VideoLevel.Value.ToString(_usCulture);
- }
+ StreamOptions = info.StreamOptions;
}
}
@@ -224,12 +221,41 @@ namespace MediaBrowser.Controller.MediaEncoding
public EncodingContext Context { get; set; }
+ public void SetOption(string qualifier, string name, string value)
+ {
+ SetOption(qualifier + "-" + name, value);
+ }
+
+ public Dictionary<string, string> StreamOptions { get; set; }
+
+ public void SetOption(string name, string value)
+ {
+ StreamOptions[name] = value;
+ }
+
+ public string GetOption(string qualifier, string name)
+ {
+ return GetOption(qualifier + "-" + name);
+ }
+
+ public string GetOption(string name)
+ {
+ string value;
+ if (StreamOptions.TryGetValue(name, out value))
+ {
+ return value;
+ }
+
+ return null;
+ }
+
public BaseEncodingJobOptions()
{
EnableAutoStreamCopy = true;
AllowVideoStreamCopy = true;
AllowAudioStreamCopy = true;
Context = EncodingContext.Streaming;
+ StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
}
diff --git a/MediaBrowser.Controller/TV/ITVSeriesManager.cs b/MediaBrowser.Controller/TV/ITVSeriesManager.cs
index 0bcb9ae5b..fd41094ee 100644
--- a/MediaBrowser.Controller/TV/ITVSeriesManager.cs
+++ b/MediaBrowser.Controller/TV/ITVSeriesManager.cs
@@ -15,6 +15,6 @@ namespace MediaBrowser.Controller.TV
/// <summary>
/// Gets the next up.
/// </summary>
- QueryResult<BaseItem> GetNextUp(NextUpQuery request, List<Folder> parentsFolders, DtoOptions options);
+ QueryResult<BaseItem> GetNextUp(NextUpQuery request, List<BaseItem> parentsFolders, DtoOptions options);
}
}