From 59ac045c6b875fd9ed8dc2ecc2ca580ba4fdab2d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 19 Mar 2017 02:10:11 -0400 Subject: increase unification of param building --- MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index f6895696a..1b26d3b2a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -109,7 +109,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } public string OutputFilePath { get; set; } - public int? OutputAudioBitrate; public string ActualOutputVideoCodec { -- cgit v1.2.3 From 38e05b11e2cef0ee15d8c6d0ee063db08dafde24 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 19 Mar 2017 14:59:05 -0400 Subject: unify encodng param creation --- .../Data/SqliteItemRepository.cs | 79 ++++++++++---- .../Emby.Server.Implementations.csproj | 2 - .../HttpServer/GetSwaggerResource.cs | 17 --- .../HttpServer/SwaggerService.cs | 47 --------- .../Playback/Progressive/VideoService.cs | 114 +-------------------- MediaBrowser.Api/Playback/StreamState.cs | 1 - .../MediaEncoding/EncodingHelper.cs | 108 +++++++++++++++++++ .../MediaEncoding/EncodingJobInfo.cs | 2 + .../MediaEncoding/EncodingJobOptions.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 1 - MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 92 +---------------- 13 files changed, 180 insertions(+), 295 deletions(-) delete mode 100644 Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs delete mode 100644 Emby.Server.Implementations/HttpServer/SwaggerService.cs (limited to 'MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index e65ebeb04..c5ba6c892 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -3204,6 +3204,40 @@ namespace Emby.Server.Implementations.Data } } + private bool IsAlphaNumeric(string str) + { + if (string.IsNullOrWhiteSpace(str)) + return false; + + for (int i = 0; i < str.Length; i++) + { + if (!(char.IsLetter(str[i])) && (!(char.IsNumber(str[i])))) + return false; + } + + return true; + } + + private bool IsValidType(string value) + { + return IsAlphaNumeric(value); + } + + private bool IsValidMediaType(string value) + { + return IsAlphaNumeric(value); + } + + private bool IsValidId(string value) + { + return IsAlphaNumeric(value); + } + + private bool IsValidPersonType(string value) + { + return IsAlphaNumeric(value); + } + private List GetWhereClauses(InternalItemsQuery query, IStatement statement, string paramSuffix = "") { if (query.IsResumable ?? false) @@ -3423,9 +3457,9 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@ChannelId", query.ChannelIds[0]); } } - if (query.ChannelIds.Length > 1) + else if (query.ChannelIds.Length > 1) { - var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i + "'").ToArray()); + var inClause = string.Join(",", query.ChannelIds.Where(IsValidId).Select(i => "'" + i + "'").ToArray()); whereClauses.Add(string.Format("ChannelId in ({0})", inClause)); } @@ -4157,17 +4191,18 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("(IsVirtualItem=0 OR PremiereDate < DATETIME('now'))"); } } - if (query.MediaTypes.Length == 1) + var queryMediaTypes = query.MediaTypes.Where(IsValidMediaType).ToArray(); + if (queryMediaTypes.Length == 1) { whereClauses.Add("MediaType=@MediaTypes"); if (statement != null) { - statement.TryBind("@MediaTypes", query.MediaTypes[0]); + statement.TryBind("@MediaTypes", queryMediaTypes[0]); } } - if (query.MediaTypes.Length > 1) + else if (queryMediaTypes.Length > 1) { - var val = string.Join(",", query.MediaTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add("MediaType in (" + val + ")"); } @@ -4273,7 +4308,9 @@ namespace Emby.Server.Implementations.Data //var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0; var enableItemsByName = query.IncludeItemsByName ?? false; - if (query.TopParentIds.Length == 1) + var queryTopParentIds = query.TopParentIds.Where(IsValidId).ToArray(); + + if (queryTopParentIds.Length == 1) { if (enableItemsByName) { @@ -4289,12 +4326,12 @@ namespace Emby.Server.Implementations.Data } if (statement != null) { - statement.TryBind("@TopParentId", query.TopParentIds[0]); + statement.TryBind("@TopParentId", queryTopParentIds[0]); } } - if (query.TopParentIds.Length > 1) + else if (queryTopParentIds.Length > 1) { - var val = string.Join(",", query.TopParentIds.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryTopParentIds.Select(i => "'" + i + "'").ToArray()); if (enableItemsByName) { @@ -4544,7 +4581,7 @@ namespace Emby.Server.Implementations.Data return result; } - return new[] { value }; + return new[] { value }.Where(IsValidType); } public async Task DeleteItem(Guid id, CancellationToken cancellationToken) @@ -4696,31 +4733,35 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@AppearsInItemId", query.AppearsInItemId.ToGuidParamValue()); } } - if (query.PersonTypes.Count == 1) + var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList(); + + if (queryPersonTypes.Count == 1) { whereClauses.Add("PersonType=@PersonType"); if (statement != null) { - statement.TryBind("@PersonType", query.PersonTypes[0]); + statement.TryBind("@PersonType", queryPersonTypes[0]); } } - if (query.PersonTypes.Count > 1) + else if (queryPersonTypes.Count > 1) { - var val = string.Join(",", query.PersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add("PersonType in (" + val + ")"); } - if (query.ExcludePersonTypes.Count == 1) + var queryExcludePersonTypes = query.ExcludePersonTypes.Where(IsValidPersonType).ToList(); + + if (queryExcludePersonTypes.Count == 1) { whereClauses.Add("PersonType<>@PersonType"); if (statement != null) { - statement.TryBind("@PersonType", query.ExcludePersonTypes[0]); + statement.TryBind("@PersonType", queryExcludePersonTypes[0]); } } - if (query.ExcludePersonTypes.Count > 1) + else if (queryExcludePersonTypes.Count > 1) { - var val = string.Join(",", query.ExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add("PersonType not in (" + val + ")"); } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index ecd86d507..afd437fe8 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -85,7 +85,6 @@ - @@ -103,7 +102,6 @@ - diff --git a/Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs b/Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs deleted file mode 100644 index 819ede1ab..000000000 --- a/Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediaBrowser.Model.Services; - -namespace Emby.Server.Implementations.HttpServer -{ - /// - /// Class GetDashboardResource - /// - [Route("/swagger-ui/{ResourceName*}", "GET")] - public class GetSwaggerResource - { - /// - /// Gets or sets the name. - /// - /// The name. - public string ResourceName { get; set; } - } -} \ No newline at end of file diff --git a/Emby.Server.Implementations/HttpServer/SwaggerService.cs b/Emby.Server.Implementations/HttpServer/SwaggerService.cs deleted file mode 100644 index d41946645..000000000 --- a/Emby.Server.Implementations/HttpServer/SwaggerService.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Net; -using System.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Services; - -namespace Emby.Server.Implementations.HttpServer -{ - public class SwaggerService : IService, IRequiresRequest - { - private readonly IServerApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public SwaggerService(IServerApplicationPaths appPaths, IFileSystem fileSystem, IHttpResultFactory resultFactory) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - _resultFactory = resultFactory; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetSwaggerResource request) - { - var swaggerDirectory = Path.Combine(_appPaths.ApplicationResourcesPath, "swagger-ui"); - - var requestedFile = Path.Combine(swaggerDirectory, request.ResourceName.Replace('/', _fileSystem.DirectorySeparatorChar)); - - return _resultFactory.GetStaticFileResult(Request, requestedFile).Result; - } - - /// - /// Gets or sets the result factory. - /// - /// The result factory. - private readonly IHttpResultFactory _resultFactory; - - /// - /// Gets or sets the request context. - /// - /// The request context. - public IRequest Request { get; set; } - } -} diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 228f50eab..8394e016c 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -6,11 +6,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using System; -using System.IO; using System.Threading.Tasks; using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; namespace MediaBrowser.Api.Playback.Progressive @@ -95,116 +92,7 @@ namespace MediaBrowser.Api.Playback.Progressive { var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - // Get the output codec name - var videoCodec = EncodingHelper.GetVideoEncoder(state, encodingOptions); - - var format = string.Empty; - var keyFrame = string.Empty; - - if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase)) - { - // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js - format = " -f mp4 -movflags frag_keyframe+empty_moov"; - } - - var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); - - var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions); - - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", - inputModifier, - EncodingHelper.GetInputArgument(state, encodingOptions), - keyFrame, - EncodingHelper.GetMapArgs(state), - GetVideoArguments(state, videoCodec), - threads, - EncodingHelper.GetProgressiveVideoAudioArguments(state, encodingOptions), - EncodingHelper.GetSubtitleEmbedArguments(state), - format, - outputPath - ).Trim(); - } - - /// - /// Gets video arguments to pass to ffmpeg - /// - /// The state. - /// The video codec. - /// System.String. - private string GetVideoArguments(StreamState state, string videoCodec) - { - var args = "-codec:v:0 " + videoCodec; - - if (state.EnableMpegtsM2TsMode) - { - args += " -mpegts_m2ts_mode 1"; - } - - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) - { - if (state.VideoStream != null && EncodingHelper.IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) - { - args += " -bsf:v h264_mp4toannexb"; - } - - if (state.RunTimeTicks.HasValue && state.VideoRequest.CopyTimestamps) - { - args += " -copyts -avoid_negative_ts disabled -start_at_zero"; - } - - if (!state.RunTimeTicks.HasValue) - { - args += " -flags -global_header -fflags +genpts"; - } - - return args; - } - - var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", - 5.ToString(UsCulture)); - - args += keyFrameArg; - - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; - - var hasCopyTs = false; - // Add resolution params, if specified - if (!hasGraphicalSubs) - { - var outputSizeParam = EncodingHelper.GetOutputSizeParam(state, videoCodec); - args += outputSizeParam; - hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1; - } - - if (state.RunTimeTicks.HasValue && state.VideoRequest.CopyTimestamps) - { - if (!hasCopyTs) - { - args += " -copyts"; - } - args += " -avoid_negative_ts disabled -start_at_zero"; - } - - var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - var qualityParam = EncodingHelper.GetVideoQualityParam(state, videoCodec, encodingOptions, GetDefaultH264Preset()); - - if (!string.IsNullOrEmpty(qualityParam)) - { - args += " " + qualityParam.Trim(); - } - - // This is for internal graphical subs - if (hasGraphicalSubs) - { - args += EncodingHelper.GetGraphicalSubtitleParam(state, videoCodec); - } - - if (!state.RunTimeTicks.HasValue) - { - args += " -flags -global_header"; - } - - return args; + return EncodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, GetDefaultH264Preset()); } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index afc48b64c..24ba0606d 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -134,7 +134,6 @@ namespace MediaBrowser.Api.Playback public string MimeType { get; set; } public bool EstimateContentLength { get; set; } - public bool EnableMpegtsM2TsMode { get; set; } public TranscodeSeekInfo TranscodeSeekInfo { get; set; } public long? EncodingDurationTicks { get; set; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8a1e2698a..939a473c5 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1773,6 +1773,114 @@ namespace MediaBrowser.Controller.MediaEncoding return args; } + public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string outputPath, string defaultH264Preset) + { + // Get the output codec name + var videoCodec = GetVideoEncoder(state, encodingOptions); + + var format = string.Empty; + var keyFrame = string.Empty; + + if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase) && + state.BaseRequest.Context == EncodingContext.Streaming) + { + // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js + format = " -f mp4 -movflags frag_keyframe+empty_moov"; + } + + var threads = GetNumberOfThreads(state, encodingOptions, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); + + var inputModifier = GetInputModifier(state, encodingOptions); + + return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", + inputModifier, + GetInputArgument(state, encodingOptions), + keyFrame, + GetMapArgs(state), + GetProgressiveVideoArguments(state, encodingOptions, videoCodec, defaultH264Preset), + threads, + GetProgressiveVideoAudioArguments(state, encodingOptions), + GetSubtitleEmbedArguments(state), + format, + outputPath + ).Trim(); + } + + public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultH264Preset) + { + var args = "-codec:v:0 " + videoCodec; + + if (state.EnableMpegtsM2TsMode) + { + args += " -mpegts_m2ts_mode 1"; + } + + if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) + { + args += " -bsf:v h264_mp4toannexb"; + } + + if (state.RunTimeTicks.HasValue && state.BaseRequest.CopyTimestamps) + { + args += " -copyts -avoid_negative_ts disabled -start_at_zero"; + } + + if (!state.RunTimeTicks.HasValue) + { + args += " -flags -global_header -fflags +genpts"; + } + + return args; + } + + var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", + 5.ToString(_usCulture)); + + args += keyFrameArg; + + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.BaseRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; + + var hasCopyTs = false; + // Add resolution params, if specified + if (!hasGraphicalSubs) + { + var outputSizeParam = GetOutputSizeParam(state, videoCodec); + args += outputSizeParam; + hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1; + } + + if (state.RunTimeTicks.HasValue && state.BaseRequest.CopyTimestamps) + { + if (!hasCopyTs) + { + args += " -copyts"; + } + args += " -avoid_negative_ts disabled -start_at_zero"; + } + + var qualityParam = GetVideoQualityParam(state, videoCodec, encodingOptions, defaultH264Preset); + + if (!string.IsNullOrEmpty(qualityParam)) + { + args += " " + qualityParam.Trim(); + } + + // This is for internal graphical subs + if (hasGraphicalSubs) + { + args += GetGraphicalSubtitleParam(state, videoCodec); + } + + if (!state.RunTimeTicks.HasValue) + { + args += " -flags -global_header"; + } + + return args; + } + public string GetProgressiveVideoAudioArguments(EncodingJobInfo state, EncodingOptions encodingOptions) { // If the video doesn't have an audio stream, return a default. diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index ac33b8c8c..6f566515e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -53,6 +53,8 @@ namespace MediaBrowser.Controller.MediaEncoding public string InputContainer { get; set; } public IsoType? IsoType { get; set; } + public bool EnableMpegtsM2TsMode { get; set; } + public BaseEncodingJobOptions BaseRequest { get; set; } public long? StartTimeTicks diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 41f146375..73be78dc9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -14,7 +14,6 @@ namespace MediaBrowser.Controller.MediaEncoding public string AudioCodec { get; set; } public DeviceProfile DeviceProfile { get; set; } - public EncodingContext Context { get; set; } public bool ReadInputAtNativeFramerate { get; set; } @@ -214,9 +213,12 @@ namespace MediaBrowser.Controller.MediaEncoding [ApiMember(Name = "VideoStreamIndex", Description = "Optional. The index of the video stream to use. If omitted the first video stream will be used.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? VideoStreamIndex { get; set; } + public EncodingContext Context { get; set; } + public BaseEncodingJobOptions() { EnableAutoStreamCopy = true; + Context = EncodingContext.Streaming; } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs index a4db8f3b8..05b3ca5fc 100644 --- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { } - protected override Task GetCommandLineArguments(EncodingJob state) + protected override string GetCommandLineArguments(EncodingJob state) { var audioTranscodeParams = new List(); @@ -78,7 +78,7 @@ namespace MediaBrowser.MediaEncoding.Encoder mapArgs, metadata).Trim(); - return Task.FromResult(result); + return result; } protected override string GetOutputFileExtension(EncodingJob state) diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 635c8deac..ef68fb90a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -76,7 +76,7 @@ namespace MediaBrowser.MediaEncoding.Encoder await AcquireResources(encodingJob, cancellationToken).ConfigureAwait(false); - var commandLineArgs = await GetCommandLineArguments(encodingJob).ConfigureAwait(false); + var commandLineArgs = GetCommandLineArguments(encodingJob); var process = ProcessFactory.Create(new ProcessOptions { @@ -265,7 +265,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return ConfigurationManager.GetConfiguration("encoding"); } - protected abstract Task GetCommandLineArguments(EncodingJob job); + protected abstract string GetCommandLineArguments(EncodingJob job); private string GetOutputFilePath(EncodingJob state) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index 1b26d3b2a..449c31ace 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -36,7 +36,6 @@ namespace MediaBrowser.MediaEncoding.Encoder public string MimeType { get; set; } public bool EstimateContentLength { get; set; } - public bool EnableMpegtsM2TsMode { get; set; } public TranscodeSeekInfo TranscodeSeekInfo { get; set; } public long? EncodingDurationTicks { get; set; } public string LiveStreamId { get; set; } diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index a779c1bca..96c126923 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -18,100 +18,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { } - protected override async Task GetCommandLineArguments(EncodingJob state) + protected override string GetCommandLineArguments(EncodingJob state) { // Get the output codec name var encodingOptions = GetEncodingOptions(); - var videoCodec = EncodingHelper.GetVideoEncoder(state, encodingOptions); - var format = string.Empty; - var keyFrame = string.Empty; - - if (string.Equals(Path.GetExtension(state.OutputFilePath), ".mp4", StringComparison.OrdinalIgnoreCase) && - state.Options.Context == EncodingContext.Streaming) - { - // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js - format = " -f mp4 -movflags frag_keyframe+empty_moov"; - } - - var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); - - var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions); - - var videoArguments = await GetVideoArguments(state, videoCodec).ConfigureAwait(false); - - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -threads {5} {6}{7} -y \"{8}\"", - inputModifier, - EncodingHelper.GetInputArgument(state, encodingOptions), - keyFrame, - EncodingHelper.GetMapArgs(state), - videoArguments, - threads, - EncodingHelper.GetProgressiveVideoAudioArguments(state, encodingOptions), - format, - state.OutputFilePath - ).Trim(); - } - - /// - /// Gets video arguments to pass to ffmpeg - /// - /// The state. - /// The video codec. - /// System.String. - private async Task GetVideoArguments(EncodingJob state, string videoCodec) - { - var args = "-codec:v:0 " + videoCodec; - - if (state.EnableMpegtsM2TsMode) - { - args += " -mpegts_m2ts_mode 1"; - } - - var isOutputMkv = string.Equals(state.Options.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase); - - if (state.RunTimeTicks.HasValue) - { - //args += " -copyts -avoid_negative_ts disabled -start_at_zero"; - } - - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) - { - if (state.VideoStream != null && EncodingHelper.IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) - { - args += " -bsf:v h264_mp4toannexb"; - } - - return args; - } - - var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", - 5.ToString(UsCulture)); - - args += keyFrameArg; - - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.Options.SubtitleMethod == SubtitleDeliveryMethod.Encode; - - // Add resolution params, if specified - if (!hasGraphicalSubs) - { - args += EncodingHelper.GetOutputSizeParam(state, videoCodec); - } - - var qualityParam = EncodingHelper.GetVideoQualityParam(state, videoCodec, GetEncodingOptions(), "superfast"); - - if (!string.IsNullOrEmpty(qualityParam)) - { - args += " " + qualityParam.Trim(); - } - - // This is for internal graphical subs - if (hasGraphicalSubs) - { - args += EncodingHelper.GetGraphicalSubtitleParam(state, videoCodec); - } - - return args; + return EncodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, state.OutputFilePath, "superfast"); } protected override string GetOutputFileExtension(EncodingJob state) -- cgit v1.2.3 From c9be9b41415ea67356cb73820d41e19f822ec727 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 24 Mar 2017 11:03:49 -0400 Subject: update hls params --- .../LiveTv/EmbyTV/EmbyTV.cs | 27 ++++ MediaBrowser.Api/Playback/BaseStreamingService.cs | 132 +----------------- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 9 +- MediaBrowser.Api/Playback/StreamState.cs | 8 ++ .../MediaBrowser.Controller.csproj | 1 + .../MediaEncoding/EncodingJobInfo.cs | 4 +- MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 149 +++++++++++++++++++++ MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 6 +- MediaBrowser.MediaEncoding/Encoder/JobLogger.cs | 122 ----------------- .../MediaBrowser.MediaEncoding.csproj | 1 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 14 +- MediaBrowser.Providers/Manager/ImageSaver.cs | 17 +-- .../Manager/ItemImageProvider.cs | 17 +-- 14 files changed, 219 insertions(+), 290 deletions(-) create mode 100644 MediaBrowser.Controller/MediaEncoding/JobLogger.cs delete mode 100644 MediaBrowser.MediaEncoding/Encoder/JobLogger.cs (limited to 'MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index eea562524..3bd2dd1bf 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -710,7 +710,34 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV throw new InvalidOperationException("SeriesId for program not found"); } + // If any timers have already been manually created, make sure they don't get cancelled + var existingTimers = (await GetTimersAsync(CancellationToken.None).ConfigureAwait(false)) + .Where(i => + { + if (string.Equals(i.ProgramId, info.ProgramId, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(info.ProgramId)) + { + return true; + } + + //if (string.Equals(i.SeriesId, info.SeriesId, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(info.SeriesId)) + //{ + // return true; + //} + + return false; + }) + .ToList(); + _seriesTimerProvider.Add(info); + + foreach (var timer in existingTimers) + { + timer.SeriesTimerId = info.Id; + timer.IsManual = true; + + _timerProvider.AddOrUpdate(timer); + } + await UpdateTimersForSeriesTimer(epgData, info, true, false).ConfigureAwait(false); return info.Id; diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index b3a00cc92..480508e6f 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -289,8 +289,10 @@ namespace MediaBrowser.Api.Playback // MUST read both stdout and stderr asynchronously or a deadlock may occurr //process.BeginOutputReadLine(); + state.TranscodingJob = transcodingJob; + // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - var task = Task.Run(() => StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream)); + new JobLogger(Logger).StartStreamingLog(state, process.StandardError.BaseStream, state.LogFileStream); // Wait for the file to exist before proceeeding while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) @@ -340,134 +342,6 @@ namespace MediaBrowser.Api.Playback // string.Equals(GetVideoEncoder(state), "libx264", StringComparison.OrdinalIgnoreCase); } - private async Task StartStreamingLog(TranscodingJob transcodingJob, StreamState state, Stream source, Stream target) - { - try - { - using (var reader = new StreamReader(source)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - ParseLogLine(line, transcodingJob, state); - - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - await target.FlushAsync().ConfigureAwait(false); - } - } - } - catch (ObjectDisposedException) - { - // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux - } - catch (Exception ex) - { - Logger.ErrorException("Error reading ffmpeg log", ex); - } - } - - private void ParseLogLine(string line, TranscodingJob transcodingJob, StreamState state) - { - float? framerate = null; - double? percent = null; - TimeSpan? transcodingPosition = null; - long? bytesTranscoded = null; - int? bitRate = null; - - var parts = line.Split(' '); - - var totalMs = state.RunTimeTicks.HasValue - ? TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds - : 0; - - var startMs = state.Request.StartTimeTicks.HasValue - ? TimeSpan.FromTicks(state.Request.StartTimeTicks.Value).TotalMilliseconds - : 0; - - for (var i = 0; i < parts.Length; i++) - { - var part = parts[i]; - - if (string.Equals(part, "fps=", StringComparison.OrdinalIgnoreCase) && - (i + 1 < parts.Length)) - { - var rate = parts[i + 1]; - float val; - - if (float.TryParse(rate, NumberStyles.Any, UsCulture, out val)) - { - framerate = val; - } - } - else if (state.RunTimeTicks.HasValue && - part.StartsWith("time=", StringComparison.OrdinalIgnoreCase)) - { - var time = part.Split(new[] { '=' }, 2).Last(); - TimeSpan val; - - if (TimeSpan.TryParse(time, UsCulture, out val)) - { - var currentMs = startMs + val.TotalMilliseconds; - - var percentVal = currentMs / totalMs; - percent = 100 * percentVal; - - transcodingPosition = val; - } - } - else if (part.StartsWith("size=", StringComparison.OrdinalIgnoreCase)) - { - var size = part.Split(new[] { '=' }, 2).Last(); - - int? scale = null; - if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1) - { - scale = 1024; - size = size.Replace("kb", string.Empty, StringComparison.OrdinalIgnoreCase); - } - - if (scale.HasValue) - { - long val; - - if (long.TryParse(size, NumberStyles.Any, UsCulture, out val)) - { - bytesTranscoded = val * scale.Value; - } - } - } - else if (part.StartsWith("bitrate=", StringComparison.OrdinalIgnoreCase)) - { - var rate = part.Split(new[] { '=' }, 2).Last(); - - int? scale = null; - if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1) - { - scale = 1024; - rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase); - } - - if (scale.HasValue) - { - float val; - - if (float.TryParse(rate, NumberStyles.Any, UsCulture, out val)) - { - bitRate = (int)Math.Ceiling(val * scale.Value); - } - } - } - } - - if (framerate.HasValue || percent.HasValue) - { - ApiEntryPoint.Instance.ReportTranscodingProgress(transcodingJob, state, transcodingPosition, framerate, percent, bytesTranscoded, bitRate); - } - } - /// /// Processes the exited. /// diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index d2f14f4b8..53813860a 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -268,7 +268,7 @@ namespace MediaBrowser.Api.Playback.Hls "hls/" + Path.GetFileNameWithoutExtension(outputPath)); } - var useGenericSegmenter = false; + var useGenericSegmenter = true; if (useGenericSegmenter) { var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); @@ -281,7 +281,9 @@ namespace MediaBrowser.Api.Playback.Hls segmentFormat = "mpegts"; } - return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + baseUrlParam = string.Format("\"{0}/\"", "hls/" + Path.GetFileNameWithoutExtension(outputPath)); + + return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_entry_prefix {12} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", inputModifier, EncodingHelper.GetInputArgument(state, encodingOptions), threads, @@ -293,7 +295,8 @@ namespace MediaBrowser.Api.Playback.Hls outputPath, outputTsArg, timeDeltaParam, - segmentFormat + segmentFormat, + baseUrlParam ).Trim(); } diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 24ba0606d..2f5f6227a 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -154,6 +154,8 @@ namespace MediaBrowser.Api.Playback DisposeLiveStream(); DisposeLogStream(); DisposeIsoMount(); + + TranscodingJob = null; } private void DisposeLogStream() @@ -476,5 +478,11 @@ namespace MediaBrowser.Api.Playback return true; } } + + public TranscodingJob TranscodingJob; + public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate) + { + ApiEntryPoint.Instance.ReportTranscodingProgress(TranscodingJob, this, transcodingPosition, framerate, percentComplete, bytesTranscoded, bitRate); + } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 4ebee531f..88153868f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -190,6 +190,7 @@ + diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 6f566515e..f5878864b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -12,7 +12,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Controller.MediaEncoding { // For now, a common base class until the API and MediaEncoding classes are unified - public class EncodingJobInfo + public abstract class EncodingJobInfo { private readonly ILogger _logger; @@ -115,5 +115,7 @@ namespace MediaBrowser.Controller.MediaEncoding IsoMount = null; } } + + public abstract void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate); } } diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs new file mode 100644 index 000000000..03e4f7771 --- /dev/null +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -0,0 +1,149 @@ +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Logging; +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; + +namespace MediaBrowser.Controller.MediaEncoding +{ + public class JobLogger + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly ILogger _logger; + + public JobLogger(ILogger logger) + { + _logger = logger; + } + + public async void StartStreamingLog(EncodingJobInfo state, Stream source, Stream target) + { + try + { + using (var reader = new StreamReader(source)) + { + while (!reader.EndOfStream) + { + var line = await reader.ReadLineAsync().ConfigureAwait(false); + + ParseLogLine(line, state); + + var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); + + await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await target.FlushAsync().ConfigureAwait(false); + } + } + } + catch (ObjectDisposedException) + { + // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux + } + catch (Exception ex) + { + _logger.ErrorException("Error reading ffmpeg log", ex); + } + } + + private void ParseLogLine(string line, EncodingJobInfo state) + { + float? framerate = null; + double? percent = null; + TimeSpan? transcodingPosition = null; + long? bytesTranscoded = null; + int? bitRate = null; + + var parts = line.Split(' '); + + var totalMs = state.RunTimeTicks.HasValue + ? TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds + : 0; + + var startMs = state.BaseRequest.StartTimeTicks.HasValue + ? TimeSpan.FromTicks(state.BaseRequest.StartTimeTicks.Value).TotalMilliseconds + : 0; + + for (var i = 0; i < parts.Length; i++) + { + var part = parts[i]; + + if (string.Equals(part, "fps=", StringComparison.OrdinalIgnoreCase) && + (i + 1 < parts.Length)) + { + var rate = parts[i + 1]; + float val; + + if (float.TryParse(rate, NumberStyles.Any, _usCulture, out val)) + { + framerate = val; + } + } + else if (state.RunTimeTicks.HasValue && + part.StartsWith("time=", StringComparison.OrdinalIgnoreCase)) + { + var time = part.Split(new[] { '=' }, 2).Last(); + TimeSpan val; + + if (TimeSpan.TryParse(time, _usCulture, out val)) + { + var currentMs = startMs + val.TotalMilliseconds; + + var percentVal = currentMs / totalMs; + percent = 100 * percentVal; + + transcodingPosition = val; + } + } + else if (part.StartsWith("size=", StringComparison.OrdinalIgnoreCase)) + { + var size = part.Split(new[] { '=' }, 2).Last(); + + int? scale = null; + if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1) + { + scale = 1024; + size = size.Replace("kb", string.Empty, StringComparison.OrdinalIgnoreCase); + } + + if (scale.HasValue) + { + long val; + + if (long.TryParse(size, NumberStyles.Any, _usCulture, out val)) + { + bytesTranscoded = val * scale.Value; + } + } + } + else if (part.StartsWith("bitrate=", StringComparison.OrdinalIgnoreCase)) + { + var rate = part.Split(new[] { '=' }, 2).Last(); + + int? scale = null; + if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1) + { + scale = 1024; + rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase); + } + + if (scale.HasValue) + { + float val; + + if (float.TryParse(rate, NumberStyles.Any, _usCulture, out val)) + { + bitRate = (int)Math.Ceiling(val * scale.Value); + } + } + } + } + + if (framerate.HasValue || percent.HasValue) + { + state.ReportTranscodingProgress(transcodingPosition, framerate, percent, bytesTranscoded, bitRate); + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index ef68fb90a..b6e695f1b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -242,7 +242,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private void OnTranscodeBeginning(EncodingJob job) { - job.ReportTranscodingProgress(null, null, null, null); + job.ReportTranscodingProgress(null, null, null, null, null); } private void OnTranscodeFailedToStart(string path, EncodingJob job) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index 449c31ace..883709de8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -377,7 +377,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return count; } - public void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded) + public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate) { var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null; @@ -385,8 +385,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!percentComplete.HasValue && ticks.HasValue && RunTimeTicks.HasValue) { - var pct = ticks.Value/RunTimeTicks.Value; - percentComplete = pct*100; + var pct = ticks.Value / RunTimeTicks.Value; + percentComplete = pct * 100; } if (percentComplete.HasValue) diff --git a/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs b/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs deleted file mode 100644 index cb6e58f17..000000000 --- a/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs +++ /dev/null @@ -1,122 +0,0 @@ -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Logging; -using System; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; - -namespace MediaBrowser.MediaEncoding.Encoder -{ - public class JobLogger - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly ILogger _logger; - - public JobLogger(ILogger logger) - { - _logger = logger; - } - - public async void StartStreamingLog(EncodingJob transcodingJob, Stream source, Stream target) - { - try - { - using (var reader = new StreamReader(source)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - ParseLogLine(line, transcodingJob); - - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffmpeg log", ex); - } - } - - private void ParseLogLine(string line, EncodingJob transcodingJob) - { - float? framerate = null; - double? percent = null; - TimeSpan? transcodingPosition = null; - long? bytesTranscoded = null; - - var parts = line.Split(' '); - - var totalMs = transcodingJob.RunTimeTicks.HasValue - ? TimeSpan.FromTicks(transcodingJob.RunTimeTicks.Value).TotalMilliseconds - : 0; - - var startMs = transcodingJob.Options.StartTimeTicks.HasValue - ? TimeSpan.FromTicks(transcodingJob.Options.StartTimeTicks.Value).TotalMilliseconds - : 0; - - for (var i = 0; i < parts.Length; i++) - { - var part = parts[i]; - - if (string.Equals(part, "fps=", StringComparison.OrdinalIgnoreCase) && - (i + 1 < parts.Length)) - { - var rate = parts[i + 1]; - float val; - - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out val)) - { - framerate = val; - } - } - else if (transcodingJob.RunTimeTicks.HasValue && - part.StartsWith("time=", StringComparison.OrdinalIgnoreCase)) - { - var time = part.Split(new[] { '=' }, 2).Last(); - TimeSpan val; - - if (TimeSpan.TryParse(time, _usCulture, out val)) - { - var currentMs = startMs + val.TotalMilliseconds; - - var percentVal = currentMs / totalMs; - percent = 100 * percentVal; - - transcodingPosition = val; - } - } - else if (part.StartsWith("size=", StringComparison.OrdinalIgnoreCase)) - { - var size = part.Split(new[] { '=' }, 2).Last(); - - int? scale = null; - if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1) - { - scale = 1024; - size = size.Replace("kb", string.Empty, StringComparison.OrdinalIgnoreCase); - } - - if (scale.HasValue) - { - long val; - - if (long.TryParse(size, NumberStyles.Any, _usCulture, out val)) - { - bytesTranscoded = val * scale.Value; - } - } - } - } - - if (framerate.HasValue || percent.HasValue) - { - transcodingJob.ReportTranscodingProgress(transcodingPosition, framerate, percent, bytesTranscoded); - } - } - } -} diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 63e789a59..ee19c4b66 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -55,7 +55,6 @@ - diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 1c7aa81e5..36df67b34 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -324,7 +324,7 @@ 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)) && options.EnableDirectStream) + if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream) && options.EnableDirectStream) { playMethods.Add(PlayMethod.DirectStream); } @@ -332,7 +332,7 @@ namespace MediaBrowser.Model.Dlna // 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)) && options.EnableDirectPlay) + IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay) && options.EnableDirectPlay) { playMethods.Add(PlayMethod.DirectPlay); } @@ -905,7 +905,7 @@ namespace MediaBrowser.Model.Dlna } } - return IsAudioEligibleForDirectPlay(item, maxBitrate); + return IsAudioEligibleForDirectPlay(item, maxBitrate, playMethod); } public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, string transcodingSubProtocol, string transcodingContainer) @@ -1035,7 +1035,7 @@ namespace MediaBrowser.Model.Dlna return null; } - private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, long? maxBitrate) + private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, long? maxBitrate, PlayMethod playMethod) { // Don't restrict by bitrate if coming from an external domain if (item.IsRemote) @@ -1045,19 +1045,19 @@ namespace MediaBrowser.Model.Dlna if (!maxBitrate.HasValue) { - _logger.Info("Cannot direct play due to unknown supported bitrate"); + _logger.Info("Cannot "+ playMethod + " due to unknown supported bitrate"); return false; } if (!item.Bitrate.HasValue) { - _logger.Info("Cannot direct play due to unknown content bitrate"); + _logger.Info("Cannot " + playMethod + " due to unknown content bitrate"); return false; } if (item.Bitrate.Value > maxBitrate.Value) { - _logger.Info("Bitrate exceeds DirectPlay limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), maxBitrate.Value.ToString(CultureInfo.InvariantCulture)); + _logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), maxBitrate.Value.ToString(CultureInfo.InvariantCulture)); return false; } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 75c4b46b2..7c797133f 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -172,18 +172,11 @@ namespace MediaBrowser.Providers.Manager try { - var currentFile = _fileSystem.GetFileInfo(currentPath); - - // This will fail if the file is hidden - if (currentFile.Exists) - { - if (currentFile.IsHidden) - { - _fileSystem.SetHidden(currentFile.FullName, false); - } - - _fileSystem.DeleteFile(currentFile.FullName); - } + _fileSystem.DeleteFile(currentPath); + } + catch (FileNotFoundException) + { + } finally { diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 9dff243c1..31cdc164c 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -373,20 +373,15 @@ namespace MediaBrowser.Providers.Manager continue; } - // Delete the source file - var currentFile = _fileSystem.GetFileInfo(image.Path); - - // Deletion will fail if the file is hidden so remove the attribute first - if (currentFile.Exists) + try { - if (currentFile.IsHidden) - { - _fileSystem.SetHidden(currentFile.FullName, false); - } - - _fileSystem.DeleteFile(currentFile.FullName); + _fileSystem.DeleteFile(image.Path); deleted = true; } + catch (FileNotFoundException) + { + + } } foreach (var image in deletedImages) -- cgit v1.2.3