mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-22 10:04:44 +01:00
extracted a media encoding interface to keep ffmpeg out of nuget packages
This commit is contained in:
@@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// <summary>
|
||||
/// Class ImageManager
|
||||
/// </summary>
|
||||
public class ImageManager : IDisposable
|
||||
public class ImageManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the image size cache.
|
||||
@@ -681,28 +681,5 @@ namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
return _locks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected void Dispose(bool dispose)
|
||||
{
|
||||
if (dispose)
|
||||
{
|
||||
ImageSizeCache.Dispose();
|
||||
ResizedImageCache.Dispose();
|
||||
CroppedImageCache.Dispose();
|
||||
EnhancedImageCache.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,7 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Reference Include="protobuf-net">
|
||||
<HintPath>..\packages\protobuf-net.2.0.0.621\lib\net40\protobuf-net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@@ -111,6 +110,7 @@
|
||||
<Compile Include="Library\ChildrenChangedEventArgs.cs" />
|
||||
<Compile Include="Library\DtoBuilder.cs" />
|
||||
<Compile Include="Providers\IProviderManager.cs" />
|
||||
<Compile Include="Providers\MediaInfo\MediaEncoderHelpers.cs" />
|
||||
<Compile Include="Providers\MetadataProviderPriority.cs" />
|
||||
<Compile Include="Providers\Music\LastfmAlbumProvider.cs" />
|
||||
<Compile Include="Providers\Music\FanArtAlbumProvider.cs" />
|
||||
@@ -134,7 +134,6 @@
|
||||
<Compile Include="Localization\RatingsDefinition.cs" />
|
||||
<Compile Include="Localization\USRatingsDictionary.cs" />
|
||||
<Compile Include="MediaInfo\FFMpegManager.cs" />
|
||||
<Compile Include="MediaInfo\FFProbeResult.cs" />
|
||||
<Compile Include="Persistence\IDisplayPreferencesRepository.cs" />
|
||||
<Compile Include="Persistence\IItemRepository.cs" />
|
||||
<Compile Include="Persistence\IRepository.cs" />
|
||||
@@ -201,15 +200,8 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="MediaInfo\fonts\ARIALUNI.TTF" />
|
||||
<EmbeddedResource Include="MediaInfo\fonts\fonts.conf" />
|
||||
<EmbeddedResource Include="MediaInfo\ffmpeg20130405.zip" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="MediaInfo\readme.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>if $(ConfigurationName) == Release (
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,354 +0,0 @@
|
||||
using MediaBrowser.Model.Entities;
|
||||
using ProtoBuf;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.MediaInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a class that we can use to deserialize the ffprobe json output
|
||||
/// Sample output:
|
||||
/// http://stackoverflow.com/questions/7708373/get-ffmpeg-information-in-friendly-way
|
||||
/// </summary>
|
||||
[ProtoContract]
|
||||
public class FFProbeResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the streams.
|
||||
/// </summary>
|
||||
/// <value>The streams.</value>
|
||||
[ProtoMember(1)]
|
||||
public FFProbeMediaStreamInfo[] streams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format.
|
||||
/// </summary>
|
||||
/// <value>The format.</value>
|
||||
[ProtoMember(2)]
|
||||
public FFProbeMediaFormatInfo format { get; set; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public List<ChapterInfo> Chapters { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stream within the output
|
||||
/// </summary>
|
||||
[ProtoContract]
|
||||
public class FFProbeMediaStreamInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the index.
|
||||
/// </summary>
|
||||
/// <value>The index.</value>
|
||||
[ProtoMember(1)]
|
||||
public int index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the profile.
|
||||
/// </summary>
|
||||
/// <value>The profile.</value>
|
||||
[ProtoMember(2)]
|
||||
public string profile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec_name.
|
||||
/// </summary>
|
||||
/// <value>The codec_name.</value>
|
||||
[ProtoMember(3)]
|
||||
public string codec_name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec_long_name.
|
||||
/// </summary>
|
||||
/// <value>The codec_long_name.</value>
|
||||
[ProtoMember(4)]
|
||||
public string codec_long_name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec_type.
|
||||
/// </summary>
|
||||
/// <value>The codec_type.</value>
|
||||
[ProtoMember(5)]
|
||||
public string codec_type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sample_rate.
|
||||
/// </summary>
|
||||
/// <value>The sample_rate.</value>
|
||||
[ProtoMember(6)]
|
||||
public string sample_rate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channels.
|
||||
/// </summary>
|
||||
/// <value>The channels.</value>
|
||||
[ProtoMember(7)]
|
||||
public int channels { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the avg_frame_rate.
|
||||
/// </summary>
|
||||
/// <value>The avg_frame_rate.</value>
|
||||
[ProtoMember(8)]
|
||||
public string avg_frame_rate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration.
|
||||
/// </summary>
|
||||
/// <value>The duration.</value>
|
||||
[ProtoMember(9)]
|
||||
public string duration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bit_rate.
|
||||
/// </summary>
|
||||
/// <value>The bit_rate.</value>
|
||||
[ProtoMember(10)]
|
||||
public string bit_rate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width.
|
||||
/// </summary>
|
||||
/// <value>The width.</value>
|
||||
[ProtoMember(11)]
|
||||
public int width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
[ProtoMember(12)]
|
||||
public int height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display_aspect_ratio.
|
||||
/// </summary>
|
||||
/// <value>The display_aspect_ratio.</value>
|
||||
[ProtoMember(13)]
|
||||
public string display_aspect_ratio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>The tags.</value>
|
||||
[ProtoMember(14)]
|
||||
public Dictionary<string, string> tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bits_per_sample.
|
||||
/// </summary>
|
||||
/// <value>The bits_per_sample.</value>
|
||||
[ProtoMember(17)]
|
||||
public int bits_per_sample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the r_frame_rate.
|
||||
/// </summary>
|
||||
/// <value>The r_frame_rate.</value>
|
||||
[ProtoMember(18)]
|
||||
public string r_frame_rate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the has_b_frames.
|
||||
/// </summary>
|
||||
/// <value>The has_b_frames.</value>
|
||||
[ProtoMember(19)]
|
||||
public int has_b_frames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sample_aspect_ratio.
|
||||
/// </summary>
|
||||
/// <value>The sample_aspect_ratio.</value>
|
||||
[ProtoMember(20)]
|
||||
public string sample_aspect_ratio { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pix_fmt.
|
||||
/// </summary>
|
||||
/// <value>The pix_fmt.</value>
|
||||
[ProtoMember(21)]
|
||||
public string pix_fmt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level.
|
||||
/// </summary>
|
||||
/// <value>The level.</value>
|
||||
[ProtoMember(22)]
|
||||
public int level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time_base.
|
||||
/// </summary>
|
||||
/// <value>The time_base.</value>
|
||||
[ProtoMember(23)]
|
||||
public string time_base { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start_time.
|
||||
/// </summary>
|
||||
/// <value>The start_time.</value>
|
||||
[ProtoMember(24)]
|
||||
public string start_time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec_time_base.
|
||||
/// </summary>
|
||||
/// <value>The codec_time_base.</value>
|
||||
[ProtoMember(25)]
|
||||
public string codec_time_base { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec_tag.
|
||||
/// </summary>
|
||||
/// <value>The codec_tag.</value>
|
||||
[ProtoMember(26)]
|
||||
public string codec_tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec_tag_string.
|
||||
/// </summary>
|
||||
/// <value>The codec_tag_string.</value>
|
||||
[ProtoMember(27)]
|
||||
public string codec_tag_string { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sample_fmt.
|
||||
/// </summary>
|
||||
/// <value>The sample_fmt.</value>
|
||||
[ProtoMember(28)]
|
||||
public string sample_fmt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the dmix_mode.
|
||||
/// </summary>
|
||||
/// <value>The dmix_mode.</value>
|
||||
[ProtoMember(29)]
|
||||
public string dmix_mode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start_pts.
|
||||
/// </summary>
|
||||
/// <value>The start_pts.</value>
|
||||
[ProtoMember(30)]
|
||||
public string start_pts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the is_avc.
|
||||
/// </summary>
|
||||
/// <value>The is_avc.</value>
|
||||
[ProtoMember(31)]
|
||||
public string is_avc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the nal_length_size.
|
||||
/// </summary>
|
||||
/// <value>The nal_length_size.</value>
|
||||
[ProtoMember(32)]
|
||||
public string nal_length_size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ltrt_cmixlev.
|
||||
/// </summary>
|
||||
/// <value>The ltrt_cmixlev.</value>
|
||||
[ProtoMember(33)]
|
||||
public string ltrt_cmixlev { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ltrt_surmixlev.
|
||||
/// </summary>
|
||||
/// <value>The ltrt_surmixlev.</value>
|
||||
[ProtoMember(34)]
|
||||
public string ltrt_surmixlev { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the loro_cmixlev.
|
||||
/// </summary>
|
||||
/// <value>The loro_cmixlev.</value>
|
||||
[ProtoMember(35)]
|
||||
public string loro_cmixlev { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the loro_surmixlev.
|
||||
/// </summary>
|
||||
/// <value>The loro_surmixlev.</value>
|
||||
[ProtoMember(36)]
|
||||
public string loro_surmixlev { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the disposition.
|
||||
/// </summary>
|
||||
/// <value>The disposition.</value>
|
||||
[ProtoMember(37)]
|
||||
public Dictionary<string, string> disposition { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class MediaFormat
|
||||
/// </summary>
|
||||
[ProtoContract]
|
||||
public class FFProbeMediaFormatInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the filename.
|
||||
/// </summary>
|
||||
/// <value>The filename.</value>
|
||||
[ProtoMember(1)]
|
||||
public string filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the nb_streams.
|
||||
/// </summary>
|
||||
/// <value>The nb_streams.</value>
|
||||
[ProtoMember(2)]
|
||||
public int nb_streams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format_name.
|
||||
/// </summary>
|
||||
/// <value>The format_name.</value>
|
||||
[ProtoMember(3)]
|
||||
public string format_name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format_long_name.
|
||||
/// </summary>
|
||||
/// <value>The format_long_name.</value>
|
||||
[ProtoMember(4)]
|
||||
public string format_long_name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start_time.
|
||||
/// </summary>
|
||||
/// <value>The start_time.</value>
|
||||
[ProtoMember(5)]
|
||||
public string start_time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration.
|
||||
/// </summary>
|
||||
/// <value>The duration.</value>
|
||||
[ProtoMember(6)]
|
||||
public string duration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size.
|
||||
/// </summary>
|
||||
/// <value>The size.</value>
|
||||
[ProtoMember(7)]
|
||||
public string size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bit_rate.
|
||||
/// </summary>
|
||||
/// <value>The bit_rate.</value>
|
||||
[ProtoMember(8)]
|
||||
public string bit_rate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>The tags.</value>
|
||||
[ProtoMember(9)]
|
||||
public Dictionary<string, string> tags { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
33054d71c54e6c262d24d16153c05d45718aeb26
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<fontconfig>
|
||||
|
||||
<dir></dir>
|
||||
<alias>
|
||||
<family>Arial</family>
|
||||
<prefer>Arial Unicode MS</prefer>
|
||||
</alias>
|
||||
</fontconfig>
|
||||
@@ -1,5 +0,0 @@
|
||||
This is the 32-bit static build of ffmpeg, located at:
|
||||
|
||||
http://ffmpeg.zeranoe.com/builds/
|
||||
|
||||
The zip file contains both ffmpeg and ffprobe, and is suffixed with the date of the build.
|
||||
@@ -1,13 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public interface IProviderManager : IDisposable
|
||||
public interface IProviderManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Downloads the and save image.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
@@ -15,8 +16,11 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
public abstract class BaseFFMpegProvider<T> : BaseMetadataProvider
|
||||
where T : BaseItem
|
||||
{
|
||||
protected BaseFFMpegProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
|
||||
protected readonly IMediaEncoder MediaEncoder;
|
||||
|
||||
protected BaseFFMpegProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder) : base(logManager, configurationManager)
|
||||
{
|
||||
MediaEncoder = mediaEncoder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,7 +57,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return Kernel.Instance.FFMpegManager.FFMpegVersion;
|
||||
return MediaEncoder.Version;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.MediaInfo;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -17,13 +18,17 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// Provides a base class for extracting media information through ffprobe
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class BaseFFProbeProvider<T> : BaseFFMpegProvider<T>, IDisposable
|
||||
public abstract class BaseFFProbeProvider<T> : BaseFFMpegProvider<T>
|
||||
where T : BaseItem
|
||||
{
|
||||
protected BaseFFProbeProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
|
||||
protected BaseFFProbeProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IProtobufSerializer protobufSerializer)
|
||||
: base(logManager, configurationManager, mediaEncoder)
|
||||
{
|
||||
ProtobufSerializer = protobufSerializer;
|
||||
}
|
||||
|
||||
protected readonly IProtobufSerializer ProtobufSerializer;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the FF probe cache.
|
||||
/// </summary>
|
||||
@@ -81,11 +86,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
OnPreFetch(myItem, isoMount);
|
||||
|
||||
var inputPath = isoMount == null ?
|
||||
Kernel.Instance.FFMpegManager.GetInputArgument(myItem) :
|
||||
Kernel.Instance.FFMpegManager.GetInputArgument((Video)item, isoMount);
|
||||
|
||||
var result = await Kernel.Instance.FFMpegManager.RunFFProbe(item, inputPath, item.DateModified, FFProbeCache, cancellationToken).ConfigureAwait(false);
|
||||
var result = await GetMediaInfo(item, isoMount, item.DateModified, FFProbeCache, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -110,6 +111,61 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media info.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="isoMount">The iso mount.</param>
|
||||
/// <param name="lastDateModified">The last date modified.</param>
|
||||
/// <param name="cache">The cache.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{MediaInfoResult}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">inputPath
|
||||
/// or
|
||||
/// cache</exception>
|
||||
private async Task<MediaInfoResult> GetMediaInfo(BaseItem item, IIsoMount isoMount, DateTime lastDateModified, FileSystemRepository cache, CancellationToken cancellationToken)
|
||||
{
|
||||
if (cache == null)
|
||||
{
|
||||
throw new ArgumentNullException("cache");
|
||||
}
|
||||
|
||||
// Put the ffmpeg version into the cache name so that it's unique per-version
|
||||
// We don't want to try and deserialize data based on an old version, which could potentially fail
|
||||
var resourceName = item.Id + "_" + lastDateModified.Ticks + "_" + MediaEncoder.Version;
|
||||
|
||||
// Forumulate the cache file path
|
||||
var cacheFilePath = cache.GetResourcePath(resourceName, ".pb");
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Avoid File.Exists by just trying to deserialize
|
||||
try
|
||||
{
|
||||
return ProtobufSerializer.DeserializeFromFile<MediaInfoResult>(cacheFilePath);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// Cache file doesn't exist
|
||||
}
|
||||
|
||||
var type = InputType.AudioFile;
|
||||
var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath };
|
||||
|
||||
var video = item as Video;
|
||||
|
||||
if (video != null)
|
||||
{
|
||||
inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type);
|
||||
}
|
||||
|
||||
var info = await MediaEncoder.GetMediaInfo(inputPath, type, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
ProtobufSerializer.SerializeToFile(info, cacheFilePath);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [refresh on version change].
|
||||
/// </summary>
|
||||
@@ -147,7 +203,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// Normalizes the FF probe result.
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
private void NormalizeFFProbeResult(FFProbeResult result)
|
||||
private void NormalizeFFProbeResult(MediaInfoResult result)
|
||||
{
|
||||
if (result.format != null && result.format.tags != null)
|
||||
{
|
||||
@@ -180,7 +236,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// <param name="result">The result.</param>
|
||||
/// <param name="isoMount">The iso mount.</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected abstract void Fetch(T item, CancellationToken cancellationToken, FFProbeResult result, IIsoMount isoMount);
|
||||
protected abstract void Fetch(T item, CancellationToken cancellationToken, MediaInfoResult result, IIsoMount isoMount);
|
||||
|
||||
/// <summary>
|
||||
/// Converts ffprobe stream info to our MediaStream class
|
||||
@@ -188,7 +244,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// <param name="streamInfo">The stream info.</param>
|
||||
/// <param name="formatInfo">The format info.</param>
|
||||
/// <returns>MediaStream.</returns>
|
||||
protected MediaStream GetMediaStream(FFProbeMediaStreamInfo streamInfo, FFProbeMediaFormatInfo formatInfo)
|
||||
protected MediaStream GetMediaStream(MediaStreamInfo streamInfo, MediaFormatInfo formatInfo)
|
||||
{
|
||||
var stream = new MediaStream
|
||||
{
|
||||
@@ -360,22 +416,5 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
return new Dictionary<string, string>(dict, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected virtual void Dispose(bool dispose)
|
||||
{
|
||||
if (dispose)
|
||||
{
|
||||
FFProbeCache.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Collections.Concurrent;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -16,8 +17,8 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// </summary>
|
||||
public class FFMpegAudioImageProvider : BaseFFMpegProvider<Audio>
|
||||
{
|
||||
public FFMpegAudioImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
|
||||
: base(logManager, configurationManager)
|
||||
public FFMpegAudioImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder)
|
||||
: base(logManager, configurationManager, mediaEncoder)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -94,12 +95,11 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
try
|
||||
{
|
||||
var imageSucceeded = await Kernel.Instance.FFMpegManager.ExtractAudioImage(audio.Path, path, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!imageSucceeded)
|
||||
{
|
||||
success = ProviderRefreshStatus.Failure;
|
||||
}
|
||||
await MediaEncoder.ExtractImage(new[] { audio.Path }, InputType.AudioFile, null, path, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
success = ProviderRefreshStatus.Failure;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Linq;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -26,12 +27,12 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// <param name="isoManager">The iso manager.</param>
|
||||
/// <param name="logManager">The log manager.</param>
|
||||
/// <param name="configurationManager">The configuration manager.</param>
|
||||
public FfMpegVideoImageProvider(IIsoManager isoManager, ILogManager logManager, IServerConfigurationManager configurationManager)
|
||||
: base(logManager, configurationManager)
|
||||
public FfMpegVideoImageProvider(IIsoManager isoManager, ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder)
|
||||
: base(logManager, configurationManager, mediaEncoder)
|
||||
{
|
||||
_isoManager = isoManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority.
|
||||
/// </summary>
|
||||
@@ -57,7 +58,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
|
||||
if (video != null)
|
||||
{
|
||||
if (video.VideoType == VideoType.Iso && video.IsoType.HasValue && _isoManager.CanMount(item.Path))
|
||||
if (video.VideoType == VideoType.Iso && _isoManager.CanMount(item.Path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -139,25 +140,23 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
// If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in.
|
||||
// Always use 10 seconds for dvd because our duration could be out of whack
|
||||
var imageOffset = video.VideoType != VideoType.Dvd && video.RunTimeTicks.HasValue && video.RunTimeTicks.Value > 0
|
||||
? TimeSpan.FromTicks(Convert.ToInt64(video.RunTimeTicks.Value * .1))
|
||||
: TimeSpan.FromSeconds(10);
|
||||
var imageOffset = video.VideoType != VideoType.Dvd && video.RunTimeTicks.HasValue &&
|
||||
video.RunTimeTicks.Value > 0
|
||||
? TimeSpan.FromTicks(Convert.ToInt64(video.RunTimeTicks.Value * .1))
|
||||
: TimeSpan.FromSeconds(10);
|
||||
|
||||
var inputPath = isoMount == null ?
|
||||
Kernel.Instance.FFMpegManager.GetInputArgument(video) :
|
||||
Kernel.Instance.FFMpegManager.GetInputArgument(video, isoMount);
|
||||
InputType type;
|
||||
|
||||
var success = await Kernel.Instance.FFMpegManager.ExtractImage(inputPath, imageOffset, path, cancellationToken).ConfigureAwait(false);
|
||||
var inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type);
|
||||
|
||||
if (success)
|
||||
{
|
||||
video.PrimaryImagePath = path;
|
||||
SetLastRefreshed(video, DateTime.UtcNow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastRefreshed(video, DateTime.UtcNow, ProviderRefreshStatus.Failure);
|
||||
}
|
||||
await MediaEncoder.ExtractImage(inputPath, type, imageOffset, path, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
video.PrimaryImagePath = path;
|
||||
SetLastRefreshed(video, DateTime.UtcNow);
|
||||
}
|
||||
catch
|
||||
{
|
||||
SetLastRefreshed(video, DateTime.UtcNow, ProviderRefreshStatus.Failure);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.MediaInfo;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
@@ -18,7 +18,8 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// </summary>
|
||||
public class FFProbeAudioInfoProvider : BaseFFProbeProvider<Audio>
|
||||
{
|
||||
public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
|
||||
public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IProtobufSerializer protobufSerializer)
|
||||
: base(logManager, configurationManager, mediaEncoder, protobufSerializer)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -42,7 +43,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="isoMount">The iso mount.</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected override void Fetch(Audio audio, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount)
|
||||
protected override void Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount)
|
||||
{
|
||||
if (data.streams == null)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.MediaInfo;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
@@ -21,8 +21,8 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// </summary>
|
||||
public class FFProbeVideoInfoProvider : BaseFFProbeProvider<Video>
|
||||
{
|
||||
public FFProbeVideoInfoProvider(IIsoManager isoManager, IBlurayExaminer blurayExaminer, IProtobufSerializer protobufSerializer, ILogManager logManager, IServerConfigurationManager configurationManager)
|
||||
: base(logManager, configurationManager)
|
||||
public FFProbeVideoInfoProvider(IIsoManager isoManager, IBlurayExaminer blurayExaminer, IProtobufSerializer protobufSerializer, ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder)
|
||||
: base(logManager, configurationManager, mediaEncoder, protobufSerializer)
|
||||
{
|
||||
if (isoManager == null)
|
||||
{
|
||||
@@ -39,7 +39,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
|
||||
_blurayExaminer = blurayExaminer;
|
||||
_isoManager = isoManager;
|
||||
_protobufSerializer = protobufSerializer;
|
||||
|
||||
BdInfoCache = new FileSystemRepository(Path.Combine(ConfigurationManager.ApplicationPaths.CachePath, "bdinfo"));
|
||||
}
|
||||
@@ -61,11 +60,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// </summary>
|
||||
private readonly IIsoManager _isoManager;
|
||||
|
||||
/// <summary>
|
||||
/// The _protobuf serializer
|
||||
/// </summary>
|
||||
private readonly IProtobufSerializer _protobufSerializer;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true or false indicating if the provider should refresh when the contents of it's directory changes
|
||||
/// </summary>
|
||||
@@ -187,7 +181,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="isoMount">The iso mount.</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected override void Fetch(Video video, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount)
|
||||
protected override void Fetch(Video video, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount)
|
||||
{
|
||||
if (data.format != null)
|
||||
{
|
||||
@@ -335,13 +329,13 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
|
||||
try
|
||||
{
|
||||
result = _protobufSerializer.DeserializeFromFile<BlurayDiscInfo>(cacheFile);
|
||||
result = ProtobufSerializer.DeserializeFromFile<BlurayDiscInfo>(cacheFile);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
result = GetBDInfo(inputPath);
|
||||
|
||||
_protobufSerializer.SerializeToFile(result, cacheFile);
|
||||
ProtobufSerializer.SerializeToFile(result, cacheFile);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -422,19 +416,5 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
return _blurayExaminer.GetDiscInfo(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool dispose)
|
||||
{
|
||||
if (dispose)
|
||||
{
|
||||
BdInfoCache.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(dispose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.MediaInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MediaEncoderHelpers
|
||||
/// </summary>
|
||||
public static class MediaEncoderHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the input argument.
|
||||
/// </summary>
|
||||
/// <param name="video">The video.</param>
|
||||
/// <param name="isoMount">The iso mount.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>System.String[][].</returns>
|
||||
public static string[] GetInputArgument(Video video, IIsoMount isoMount, out InputType type)
|
||||
{
|
||||
var inputPath = isoMount == null ? new[] { video.Path } : new[] { isoMount.MountedPath };
|
||||
|
||||
type = InputType.VideoFile;
|
||||
|
||||
switch (video.VideoType)
|
||||
{
|
||||
case VideoType.BluRay:
|
||||
type = InputType.Bluray;
|
||||
break;
|
||||
case VideoType.Dvd:
|
||||
type = InputType.Dvd;
|
||||
inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray();
|
||||
break;
|
||||
case VideoType.Iso:
|
||||
if (video.IsoType.HasValue)
|
||||
{
|
||||
switch (video.IsoType.Value)
|
||||
{
|
||||
case IsoType.BluRay:
|
||||
type = InputType.Bluray;
|
||||
break;
|
||||
case IsoType.Dvd:
|
||||
type = InputType.Dvd;
|
||||
inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return inputPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the input.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>InputType.</returns>
|
||||
public static InputType GetInputType(BaseItem item)
|
||||
{
|
||||
var type = InputType.AudioFile;
|
||||
|
||||
var video = item as Video;
|
||||
|
||||
if (video != null)
|
||||
{
|
||||
switch (video.VideoType)
|
||||
{
|
||||
case VideoType.BluRay:
|
||||
type = InputType.Bluray;
|
||||
break;
|
||||
case VideoType.Dvd:
|
||||
type = InputType.Dvd;
|
||||
break;
|
||||
case VideoType.Iso:
|
||||
if (video.IsoType.HasValue)
|
||||
{
|
||||
switch (video.IsoType.Value)
|
||||
{
|
||||
case IsoType.BluRay:
|
||||
type = InputType.Bluray;
|
||||
break;
|
||||
case IsoType.Dvd:
|
||||
type = InputType.Dvd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user