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)