From 5c84cadb5ec25b03e88fb7ab15a795a1275a97fd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 16 Jan 2015 15:54:37 -0500 Subject: update translations --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index e800b4254..cf31afd5d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -357,6 +357,8 @@ namespace MediaBrowser.MediaEncoding.Encoder } }; + _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); process.Start(); -- cgit v1.2.3 From 5bb75227dba6772d0c801b94ede87d08e5c9a1d6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 Feb 2015 14:01:21 -0500 Subject: update roku api --- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 - MediaBrowser.Api/Playback/BifService.cs | 186 --------------------- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 7 +- .../MediaInfo/FFProbeProvider.cs | 4 +- .../Session/SessionManager.cs | 3 +- 5 files changed, 10 insertions(+), 191 deletions(-) delete mode 100644 MediaBrowser.Api/Playback/BifService.cs (limited to 'MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs') diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 286b807b6..06f65c448 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -110,7 +110,6 @@ - diff --git a/MediaBrowser.Api/Playback/BifService.cs b/MediaBrowser.Api/Playback/BifService.cs deleted file mode 100644 index 181cdfe89..000000000 --- a/MediaBrowser.Api/Playback/BifService.cs +++ /dev/null @@ -1,186 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using ServiceStack; -using System; -using System.Collections.Concurrent; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.Playback -{ - [Route("/Videos/{Id}/index.bif", "GET")] - public class GetBifFile - { - [ApiMember(Name = "MediaSourceId", Description = "The media version id, if playing an alternate version", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string MediaSourceId { get; set; } - - [ApiMember(Name = "MaxWidth", Description = "Optional. The maximum horizontal resolution of the encoded video.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] - public int? MaxWidth { get; set; } - - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - public class BifService : BaseApiService - { - private readonly IServerApplicationPaths _appPaths; - private readonly ILibraryManager _libraryManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - - public BifService(IServerApplicationPaths appPaths, ILibraryManager libraryManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem) - { - _appPaths = appPaths; - _libraryManager = libraryManager; - _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - } - - public object Get(GetBifFile request) - { - return ToStaticFileResult(GetBifFile(request).Result); - } - - private async Task GetBifFile(GetBifFile request) - { - var widthVal = request.MaxWidth.HasValue ? request.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; - - var item = _libraryManager.GetItemById(request.Id); - var mediaSources = ((IHasMediaSources)item).GetMediaSources(false).ToList(); - var mediaSource = mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId)) ?? mediaSources.First(); - - var path = Path.Combine(_appPaths.ImageCachePath, "bif", request.Id, request.MediaSourceId, widthVal, "index.bif"); - - if (File.Exists(path)) - { - return path; - } - - var protocol = mediaSource.Protocol; - - var inputPath = MediaEncoderHelpers.GetInputArgument(mediaSource.Path, protocol, null, mediaSource.PlayableStreamFileNames); - - var semaphore = GetLock(path); - - await semaphore.WaitAsync().ConfigureAwait(false); - - try - { - if (File.Exists(path)) - { - return path; - } - - await _mediaEncoder.ExtractVideoImagesOnInterval(inputPath, protocol, mediaSource.Video3DFormat, - TimeSpan.FromSeconds(10), Path.GetDirectoryName(path), "img_", request.MaxWidth, CancellationToken.None) - .ConfigureAwait(false); - - var images = new DirectoryInfo(Path.GetDirectoryName(path)) - .EnumerateFiles() - .Where(img => string.Equals(img.Extension, ".jpg", StringComparison.Ordinal)) - .OrderBy(i => i.FullName) - .ToList(); - - using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) - { - var magicNumber = new byte[] { 0x89, 0x42, 0x49, 0x46, 0x0d, 0x0a, 0x1a, 0x0a }; - await fs.WriteAsync(magicNumber, 0, magicNumber.Length); - - // version - var bytes = GetBytes(0); - await fs.WriteAsync(bytes, 0, bytes.Length); - - // image count - bytes = GetBytes(images.Count); - await fs.WriteAsync(bytes, 0, bytes.Length); - - // interval in ms - bytes = GetBytes(10000); - await fs.WriteAsync(bytes, 0, bytes.Length); - - // reserved - for (var i = 20; i <= 63; i++) - { - bytes = new byte[] { 0x00 }; - await fs.WriteAsync(bytes, 0, bytes.Length); - } - - // write the bif index - var index = 0; - long imageOffset = 64 + (8 * images.Count) + 8; - - foreach (var img in images) - { - bytes = GetBytes(index); - await fs.WriteAsync(bytes, 0, bytes.Length); - - bytes = GetBytes(imageOffset); - await fs.WriteAsync(bytes, 0, bytes.Length); - - imageOffset += img.Length; - - index++; - } - - bytes = new byte[] { 0xff, 0xff, 0xff, 0xff }; - await fs.WriteAsync(bytes, 0, bytes.Length); - - bytes = GetBytes(imageOffset); - await fs.WriteAsync(bytes, 0, bytes.Length); - - // write the images - foreach (var img in images) - { - using (var imgStream = _fileSystem.GetFileStream(img.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) - { - await imgStream.CopyToAsync(fs).ConfigureAwait(false); - } - } - } - - return path; - } - finally - { - semaphore.Release(); - } - } - - private byte[] GetBytes(int value) - { - byte[] bytes = BitConverter.GetBytes(value); - if (!BitConverter.IsLittleEndian) - Array.Reverse(bytes); - return bytes; - } - - private byte[] GetBytes(long value) - { - var intVal = Convert.ToInt32(value); - return GetBytes(intVal); - - //byte[] bytes = BitConverter.GetBytes(value); - //if (BitConverter.IsLittleEndian) - // Array.Reverse(bytes); - //return bytes; - } - - private static readonly ConcurrentDictionary SemaphoreLocks = new ConcurrentDictionary(); - - /// - /// Gets the lock. - /// - /// The filename. - /// System.Object. - private static SemaphoreSlim GetLock(string filename) - { - return SemaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1)); - } - } -} diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index d631cab98..cb6e9f21e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -36,6 +36,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// The json serializer. private readonly IJsonSerializer _jsonSerializer; + /// + /// The _thumbnail resource pool + /// + private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); + /// /// The video image resource pool /// @@ -458,7 +463,7 @@ namespace MediaBrowser.MediaEncoding.Encoder int? maxWidth, CancellationToken cancellationToken) { - var resourcePool = _videoImageResourcePool; + var resourcePool = _thumbnailResourcePool; var inputArgument = GetInputArgument(inputFiles, protocol); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index acca43cf8..90afba0b5 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -1,5 +1,4 @@ -using System.IO; -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Configuration; @@ -20,6 +19,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Serialization; using System; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 4bce7db9f..6166e3d65 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -516,7 +516,8 @@ namespace MediaBrowser.Server.Implementations.Session Item = session.NowPlayingItem, ItemId = (session.NowPlayingItem == null ? null : session.NowPlayingItem.Id), SessionId = session.Id, - MediaSourceId = (session.PlayState == null ? null : session.PlayState.MediaSourceId) + MediaSourceId = (session.PlayState == null ? null : session.PlayState.MediaSourceId), + PositionTicks = session.PlayState == null ? null : session.PlayState.PositionTicks }); } catch (Exception ex) -- cgit v1.2.3 From 49df4a31b18ad0f9f62d36c645b3592c7600f90c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 Feb 2015 15:05:39 -0500 Subject: update thumbnail generation --- MediaBrowser.Api/PluginService.cs | 5 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 67 +++++++++++++--------- 2 files changed, 41 insertions(+), 31 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs') diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index f9098f5bf..f5c8935f8 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -1,5 +1,4 @@ -using System.Threading; -using MediaBrowser.Common; +using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Security; using MediaBrowser.Common.Updates; @@ -8,12 +7,12 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; using ServiceStack; -using ServiceStack.Text.Controller; using ServiceStack.Web; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Api diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index cb6e9f21e..b75d7bee3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -331,8 +331,8 @@ namespace MediaBrowser.MediaEncoding.Encoder // -f image2 -f webp // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) : - string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf); + var args = useIFrame ? string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) : + string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf); var probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol); @@ -363,7 +363,7 @@ namespace MediaBrowser.MediaEncoding.Encoder }; _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - + await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); process.Start(); @@ -479,7 +479,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); + var args = string.Format("-i {0} -threads 1 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); var probeSize = GetProbeSizeArgument(new[] { inputArgument }, protocol); @@ -506,41 +506,52 @@ namespace MediaBrowser.MediaEncoding.Encoder await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - process.Start(); - - // Need to give ffmpeg enough time to make all the thumbnails, which could be a while, - // but we still need to detect if the process hangs. - // Making the assumption that as long as new jpegs are showing up, everything is good. - - bool isResponsive = true; - int lastCount = 0; + bool ranToCompletion; - while (isResponsive && !process.WaitForExit(120000)) + try { - int jpegCount = Directory.GetFiles(targetDirectory, "*.jpg").Count(); - isResponsive = (jpegCount > lastCount); - lastCount = jpegCount; - } + process.Start(); - bool ranToCompletion = process.HasExited; + // Need to give ffmpeg enough time to make all the thumbnails, which could be a while, + // but we still need to detect if the process hangs. + // Making the assumption that as long as new jpegs are showing up, everything is good. - if (!ranToCompletion) - { - try + bool isResponsive = true; + int lastCount = 0; + + while (isResponsive && !process.WaitForExit(30000)) { - _logger.Info("Killing ffmpeg process"); + cancellationToken.ThrowIfCancellationRequested(); - process.StandardInput.WriteLine("q"); + int jpegCount = Directory.GetFiles(targetDirectory) + .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase)); - process.WaitForExit(1000); + isResponsive = (jpegCount > lastCount); + lastCount = jpegCount; } - catch (Exception ex) + + ranToCompletion = process.HasExited; + + if (!ranToCompletion) { - _logger.ErrorException("Error killing process", ex); + try + { + _logger.Info("Killing ffmpeg process"); + + process.StandardInput.WriteLine("q"); + + process.WaitForExit(1000); + } + catch (Exception ex) + { + _logger.ErrorException("Error killing process", ex); + } } } - - resourcePool.Release(); + finally + { + resourcePool.Release(); + } var exitCode = ranToCompletion ? process.ExitCode : -1; -- cgit v1.2.3