aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs47
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs5
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs21
-rw-r--r--MediaBrowser.Controller/MediaEncoding/ImageEncodingOptions.cs18
-rw-r--r--MediaBrowser.Dlna/DlnaManager.cs2
-rw-r--r--MediaBrowser.Dlna/PlayTo/Device.cs2
-rw-r--r--MediaBrowser.Dlna/Profiles/DefaultProfile.cs18
-rw-r--r--MediaBrowser.Dlna/Profiles/Xbox360Profile.cs14
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Default.xml7
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml7
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml7
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml2
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml7
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml7
-rw-r--r--MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs (renamed from MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs)2
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs158
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs (renamed from MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs)110
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj81
-rw-r--r--MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs36
-rw-r--r--MediaBrowser.MediaEncoding/packages.config4
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs58
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj10
-rw-r--r--MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs2
-rw-r--r--MediaBrowser.Server.Implementations/packages.config1
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs8
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj4
-rw-r--r--MediaBrowser.sln16
33 files changed, 469 insertions, 196 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 2002e594c..b510a640e 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -316,6 +316,7 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <param name="state">The state.</param>
/// <param name="videoCodec">The video codec.</param>
+ /// <param name="isHls">if set to <c>true</c> [is HLS].</param>
/// <returns>System.String.</returns>
protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls)
{
@@ -340,20 +341,17 @@ namespace MediaBrowser.Api.Playback
break;
}
- if (!isHls)
+ switch (qualitySetting)
{
- switch (qualitySetting)
- {
- case EncodingQuality.HighSpeed:
- param += " -crf 23";
- break;
- case EncodingQuality.HighQuality:
- param += " -crf 20";
- break;
- case EncodingQuality.MaxQuality:
- param += " -crf 18";
- break;
- }
+ case EncodingQuality.HighSpeed:
+ param += " -crf 23";
+ break;
+ case EncodingQuality.HighQuality:
+ param += " -crf 20";
+ break;
+ case EncodingQuality.MaxQuality:
+ param += " -crf 18";
+ break;
}
}
@@ -505,14 +503,13 @@ namespace MediaBrowser.Api.Playback
return string.Format("{4} -vf \"{0}scale=trunc({1}/2)*2:trunc({2}/2)*2{3}\"", yadifParam, widthParam, heightParam, assSubtitleParam, copyTsParam);
}
- // If Max dimensions were supplied
- //this makes my brain hurt. For width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
+ // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
if (request.MaxWidth.HasValue && request.MaxHeight.HasValue)
{
- var MaxwidthParam = request.MaxWidth.Value.ToString(UsCulture);
- var MaxheightParam = request.MaxHeight.Value.ToString(UsCulture);
+ var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
+ var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
- return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, MaxwidthParam, MaxheightParam, assSubtitleParam, copyTsParam);
+ return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, maxWidthParam, maxHeightParam, assSubtitleParam, copyTsParam);
}
var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
@@ -1032,11 +1029,6 @@ namespace MediaBrowser.Api.Playback
{
var hasFixedResolution = state.VideoRequest.HasFixedResolution;
- if (isHls)
- {
- return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
- }
-
if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
{
if (hasFixedResolution)
@@ -1047,7 +1039,6 @@ namespace MediaBrowser.Api.Playback
// With vpx when crf is used, b:v becomes a max rate
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
- //return string.Format(" -minrate:v ({0}*.95) -maxrate:v ({0}*1.05) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture));
}
if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
@@ -1055,13 +1046,17 @@ namespace MediaBrowser.Api.Playback
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
-
// H264
if (hasFixedResolution)
{
+ if (isHls)
+ {
+ return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
+ }
+
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
-
+
return string.Format(" -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture));
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 198376d6a..96b36ac7f 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -200,7 +200,7 @@ namespace MediaBrowser.Api.Playback.Hls
builder.AppendLine("#EXTM3U");
// Pad a little to satisfy the apple hls validator
- var paddedBitrate = Convert.ToInt32(bitrate * 1.05);
+ var paddedBitrate = Convert.ToInt32(bitrate * 1.15);
// Main stream
builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 78b3f2948..b4fe9a094 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -266,6 +266,11 @@ namespace MediaBrowser.Api.Playback.Progressive
return result;
}
+ /// <summary>
+ /// Gets the length of the estimated content.
+ /// </summary>
+ /// <param name="state">The state.</param>
+ /// <returns>System.Nullable{System.Int64}.</returns>
private long? GetEstimatedContentLength(StreamState state)
{
var totalBitrate = 0;
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 2e0d44e40..9915ac044 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -157,6 +157,7 @@
<Compile Include="Localization\ILocalizationManager.cs" />
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
<Compile Include="MediaEncoding\IEncodingManager.cs" />
+ <Compile Include="MediaEncoding\ImageEncodingOptions.cs" />
<Compile Include="MediaEncoding\IMediaEncoder.cs" />
<Compile Include="MediaEncoding\InternalMediaInfoResult.cs" />
<Compile Include="Net\IHasResultFactory.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 119688fa7..e9081fe8a 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -24,16 +24,23 @@ namespace MediaBrowser.Controller.MediaEncoding
string Version { get; }
/// <summary>
- /// Extracts the image.
+ /// Extracts the audio image.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{Stream}.</returns>
+ Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Extracts the video image.
/// </summary>
/// <param name="inputFiles">The input files.</param>
/// <param name="type">The type.</param>
- /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
/// <param name="threedFormat">The threed format.</param>
/// <param name="offset">The offset.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
- Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+ Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
/// <summary>
/// Extracts the text subtitle.
@@ -81,6 +88,14 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="type">The type.</param>
/// <returns>System.String.</returns>
string GetInputArgument(string[] inputFiles, InputType type);
+
+ /// <summary>
+ /// Encodes the image.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{Stream}.</returns>
+ Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken);
}
/// <summary>
diff --git a/MediaBrowser.Controller/MediaEncoding/ImageEncodingOptions.cs b/MediaBrowser.Controller/MediaEncoding/ImageEncodingOptions.cs
new file mode 100644
index 000000000..c76977f29
--- /dev/null
+++ b/MediaBrowser.Controller/MediaEncoding/ImageEncodingOptions.cs
@@ -0,0 +1,18 @@
+
+namespace MediaBrowser.Controller.MediaEncoding
+{
+ public class ImageEncodingOptions
+ {
+ public string InputPath { get; set; }
+
+ public int? Width { get; set; }
+
+ public int? Height { get; set; }
+
+ public int? MaxWidth { get; set; }
+
+ public int? MaxHeight { get; set; }
+
+ public string Format { get; set; }
+ }
+}
diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs
index edccc71c9..ec9ecb9ef 100644
--- a/MediaBrowser.Dlna/DlnaManager.cs
+++ b/MediaBrowser.Dlna/DlnaManager.cs
@@ -197,7 +197,7 @@ namespace MediaBrowser.Dlna
throw new ArgumentNullException("headers");
}
- return GetProfiles().FirstOrDefault(i => IsMatch(headers, i.Identification));
+ return GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
}
private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo)
diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs
index fa0bfbca8..c0f88f285 100644
--- a/MediaBrowser.Dlna/PlayTo/Device.cs
+++ b/MediaBrowser.Dlna/PlayTo/Device.cs
@@ -631,7 +631,7 @@ namespace MediaBrowser.Dlna.PlayTo
RendererCommands = TransportCommands.Create(document);
}
- internal TransportCommands AvCommands
+ private TransportCommands AvCommands
{
get;
set;
diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
index 0efe18755..6b5513e28 100644
--- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
@@ -57,24 +57,6 @@ namespace MediaBrowser.Dlna.Profiles
Type = DlnaProfileType.Video
}
};
-
- CodecProfiles = new[]
- {
- new CodecProfile
- {
- Type = CodecType.VideoCodec,
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoLevel,
- Value = "3",
- IsRequired = false
- }
- }
- }
- };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs
index 640317fbc..ed9edeb27 100644
--- a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs
+++ b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs
@@ -229,13 +229,6 @@ namespace MediaBrowser.Dlna.Profiles
Property = ProfileConditionValue.VideoBitrate,
Value = "10240000",
IsRequired = false
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoLevel,
- Value = "3",
- IsRequired = false
}
}
},
@@ -271,13 +264,6 @@ namespace MediaBrowser.Dlna.Profiles
Property = ProfileConditionValue.VideoBitrate,
Value = "15360000",
IsRequired = false
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoLevel,
- Value = "3",
- IsRequired = false
}
}
},
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
index 52b92c6f3..60f22a64a 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
@@ -30,12 +30,5 @@
</TranscodingProfile>
</TranscodingProfiles>
<ContainerProfiles />
- <CodecProfiles>
- <CodecProfile type="VideoCodec">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
- </Conditions>
- </CodecProfile>
- </CodecProfiles>
<MediaProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
index 3332e4d45..28bb3289e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
@@ -34,12 +34,5 @@
</TranscodingProfile>
</TranscodingProfiles>
<ContainerProfiles />
- <CodecProfiles>
- <CodecProfile type="VideoCodec">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
- </Conditions>
- </CodecProfile>
- </CodecProfiles>
<MediaProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
index b19cb0f7b..477fee2dd 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
@@ -34,12 +34,5 @@
</TranscodingProfile>
</TranscodingProfiles>
<ContainerProfiles />
- <CodecProfiles>
- <CodecProfile type="VideoCodec">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
- </Conditions>
- </CodecProfile>
- </CodecProfiles>
<MediaProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
index e7839ca77..ea2539197 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
@@ -73,7 +73,6 @@
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="false" />
<ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="10240000" isRequired="false" />
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
<CodecProfile type="VideoCodec" codec="wmv2,wmv3,vc1">
@@ -82,7 +81,6 @@
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
<ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
<ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="15360000" isRequired="false" />
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
<CodecProfile type="VideoAudioCodec" codec="ac3,wmav2,wmapro">
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
index 5243218fb..ef4fec99a 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
@@ -32,13 +32,6 @@
</TranscodingProfile>
</TranscodingProfiles>
<ContainerProfiles />
- <CodecProfiles>
- <CodecProfile type="VideoCodec">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
- </Conditions>
- </CodecProfile>
- </CodecProfiles>
<MediaProfiles>
<MediaProfile container="avi" type="Video" mimeType="video/x-msvideo">
<Conditions />
diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
index 126d7fe73..3e6623ac4 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
@@ -36,12 +36,5 @@
</TranscodingProfile>
</TranscodingProfiles>
<ContainerProfiles />
- <CodecProfiles>
- <CodecProfile type="VideoCodec">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
- </Conditions>
- </CodecProfile>
- </CodecProfiles>
<MediaProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs
index 18f1b92fe..b15b8d15d 100644
--- a/MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs
+++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs
@@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
-namespace MediaBrowser.Server.Implementations.BdInfo
+namespace MediaBrowser.MediaEncoding.BdInfo
{
/// <summary>
/// Class BdInfoExaminer
diff --git a/MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs
new file mode 100644
index 000000000..5e4221b0f
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs
@@ -0,0 +1,158 @@
+using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.MediaEncoding.Encoder
+{
+ public class ImageEncoder
+ {
+ private readonly string _ffmpegPath;
+ private readonly ILogger _logger;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ private static readonly SemaphoreSlim ResourcePool = new SemaphoreSlim(5, 5);
+
+ public ImageEncoder(string ffmpegPath, ILogger logger)
+ {
+ _ffmpegPath = ffmpegPath;
+ _logger = logger;
+ }
+
+ public async Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
+ {
+ ValidateInput(options);
+
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ FileName = _ffmpegPath,
+ Arguments = GetArguments(options),
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true
+ }
+ };
+
+ await ResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ process.Start();
+
+ var memoryStream = new MemoryStream();
+
+#pragma warning disable 4014
+ // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
+ process.StandardOutput.BaseStream.CopyToAsync(memoryStream);
+#pragma warning restore 4014
+
+ // MUST read both stdout and stderr asynchronously or a deadlock may occurr
+ process.BeginErrorReadLine();
+
+ var ranToCompletion = process.WaitForExit(5000);
+
+ if (!ranToCompletion)
+ {
+ try
+ {
+ _logger.Info("Killing ffmpeg process");
+
+ process.Kill();
+
+ process.WaitForExit(1000);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error killing process", ex);
+ }
+ }
+
+ ResourcePool.Release();
+
+ var exitCode = ranToCompletion ? process.ExitCode : -1;
+
+ process.Dispose();
+
+ if (exitCode == -1 || memoryStream.Length == 0)
+ {
+ memoryStream.Dispose();
+
+ var msg = string.Format("ffmpeg image encoding failed for {0}", options.InputPath);
+
+ _logger.Error(msg);
+
+ throw new ApplicationException(msg);
+ }
+
+ memoryStream.Position = 0;
+ return memoryStream;
+ }
+
+ private string GetArguments(ImageEncodingOptions options)
+ {
+ var vfScale = GetFilterGraph(options);
+ var outputFormat = GetOutputFormat(options);
+
+ return string.Format("-i file:\"{0}\" {1} -f {2}",
+ options.InputPath,
+ vfScale,
+ outputFormat);
+ }
+
+ private string GetFilterGraph(ImageEncodingOptions options)
+ {
+ if (!options.Width.HasValue &&
+ !options.Height.HasValue &&
+ !options.MaxHeight.HasValue &&
+ !options.MaxWidth.HasValue)
+ {
+ return string.Empty;
+ }
+
+ var widthScale = "-1";
+ var heightScale = "-1";
+
+ if (options.MaxWidth.HasValue)
+ {
+ widthScale = "min(iw," + options.MaxWidth.Value.ToString(_usCulture) + ")";
+ }
+ else if (options.Width.HasValue)
+ {
+ widthScale = options.Width.Value.ToString(_usCulture);
+ }
+
+ if (options.MaxHeight.HasValue)
+ {
+ heightScale = "min(ih," + options.MaxHeight.Value.ToString(_usCulture) + ")";
+ }
+ else if (options.Height.HasValue)
+ {
+ heightScale = options.Height.Value.ToString(_usCulture);
+ }
+
+ var scaleMethod = "lanczos";
+
+ return string.Format("-vf scale=\"{0}:{1}\" -sws_flags {2}",
+ widthScale,
+ heightScale,
+ scaleMethod);
+ }
+
+ private string GetOutputFormat(ImageEncodingOptions options)
+ {
+ return options.Format;
+ }
+
+ private void ValidateInput(ImageEncodingOptions options)
+ {
+
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index c646d80bc..55035a4ca 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -6,17 +6,15 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
-using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Server.Implementations.MediaEncoder
+namespace MediaBrowser.MediaEncoding.Encoder
{
/// <summary>
/// Class MediaEncoder
@@ -53,6 +51,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The FF probe resource pool
/// </summary>
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
+
private readonly IFileSystem _fileSystem;
public string FFMpegPath { get; private set; }
@@ -62,7 +61,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
public string Version { get; private set; }
public MediaEncoder(ILogger logger, IApplicationPaths appPaths,
- IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IFileSystem fileSystem)
+ IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version,
+ IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
@@ -85,7 +85,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <summary>
/// The _semaphoreLocks
/// </summary>
- private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
+ private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks =
+ new ConcurrentDictionary<string, SemaphoreSlim>();
/// <summary>
/// Gets the lock.
@@ -106,10 +107,10 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, InputType type, bool isAudio,
- CancellationToken cancellationToken)
+ CancellationToken cancellationToken)
{
return GetMediaInfoInternal(GetInputArgument(inputFiles, type), !isAudio,
- GetProbeSizeArgument(type), cancellationToken);
+ GetProbeSizeArgument(type), cancellationToken);
}
/// <summary>
@@ -172,8 +173,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <returns>Task{MediaInfoResult}.</returns>
/// <exception cref="System.ApplicationException"></exception>
private async Task<InternalMediaInfoResult> GetMediaInfoInternal(string inputPath, bool extractChapters,
- string probeSizeArgument,
- CancellationToken cancellationToken)
+ string probeSizeArgument,
+ CancellationToken cancellationToken)
{
var args = extractChapters
? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format"
@@ -191,7 +192,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
RedirectStandardError = true,
FileName = FFProbePath,
Arguments = string.Format(args,
- probeSizeArgument, inputPath).Trim(),
+ probeSizeArgument, inputPath).Trim(),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
@@ -225,7 +226,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
process.BeginErrorReadLine();
- result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
+ result =
+ _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
}
catch
{
@@ -295,7 +297,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, CancellationToken cancellationToken)
+ public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language,
+ CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -340,33 +343,35 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
}
- var encodingParam = string.IsNullOrEmpty(language) ? string.Empty :
- GetSubtitleLanguageEncodingParam(language) + " ";
+ var encodingParam = string.IsNullOrEmpty(language)
+ ? string.Empty
+ : GetSubtitleLanguageEncodingParam(language) + " ";
var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
{
- StartInfo = new ProcessStartInfo
- {
- RedirectStandardOutput = false,
- RedirectStandardError = true,
-
- CreateNoWindow = true,
- UseShellExecute = false,
- FileName = FFMpegPath,
- Arguments =
- string.Format("{0} -i \"{1}\" -c:s ass \"{2}\"", encodingParam, inputPath, outputPath),
-
- WindowStyle = ProcessWindowStyle.Hidden,
- ErrorDialog = false
- }
- };
+ RedirectStandardOutput = false,
+ RedirectStandardError = true,
+
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ FileName = FFMpegPath,
+ Arguments =
+ string.Format("{0} -i \"{1}\" -c:s ass \"{2}\"", encodingParam, inputPath, outputPath),
+
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false
+ }
+ };
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt");
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
- var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
+ var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
+ true);
try
{
@@ -525,7 +530,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentException">Must use inputPath list overload</exception>
- public async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex, bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
+ public async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex,
+ bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -535,7 +541,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
if (!File.Exists(outputPath))
{
- await ExtractTextSubtitleInternal(GetInputArgument(inputFiles, type), subtitleStreamIndex, copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false);
+ await
+ ExtractTextSubtitleInternal(GetInputArgument(inputFiles, type), subtitleStreamIndex,
+ copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false);
}
}
finally
@@ -559,7 +567,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// or
/// cancellationToken</exception>
/// <exception cref="System.ApplicationException"></exception>
- private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex, bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
+ private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex,
+ bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -571,11 +580,13 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
throw new ArgumentNullException("outputPath");
}
- string processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s ass \"{2}\"", inputPath, subtitleStreamIndex, outputPath);
+ string processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s ass \"{2}\"", inputPath,
+ subtitleStreamIndex, outputPath);
if (copySubtitleStream)
{
- processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s copy \"{2}\"", inputPath, subtitleStreamIndex, outputPath);
+ processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s copy \"{2}\"", inputPath,
+ subtitleStreamIndex, outputPath);
}
var process = new Process
@@ -600,7 +611,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt");
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
- var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
+ var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
+ true);
try
{
@@ -715,7 +727,18 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
}
}
- public async Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio,
+ public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
+ {
+ return ExtractImage(new[] { path }, InputType.File, true, null, null, cancellationToken);
+ }
+
+ public Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat,
+ TimeSpan? offset, CancellationToken cancellationToken)
+ {
+ return ExtractImage(inputFiles, type, false, threedFormat, offset, cancellationToken);
+ }
+
+ private async Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio,
Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
{
var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
@@ -773,7 +796,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
}
// 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\" -f image2 \"{1}\"", inputPath, "-", vf) :
+ var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail=80\" -f image2 \"{1}\"", inputPath, "-", vf) :
string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf);
var probeSize = GetProbeSizeArgument(type);
@@ -834,7 +857,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
_logger.ErrorException("Error killing process", ex);
}
}
-
+
resourcePool.Release();
var exitCode = ranToCompletion ? process.ExitCode : -1;
@@ -925,14 +948,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
return GetFileInputArgument(playableStreamFiles[0]);
}
- /// <summary>
- /// Gets the bluray input argument.
- /// </summary>
- /// <param name="blurayRoot">The bluray root.</param>
- /// <returns>System.String.</returns>
- private string GetBlurayInputArgument(string blurayRoot)
+ public Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
{
- return string.Format("bluray:\"{0}\"", blurayRoot);
+ return new ImageEncoder(FFMpegPath, _logger).EncodeImage(options, cancellationToken);
}
/// <summary>
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
new file mode 100644
index 000000000..fb1041f89
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>MediaBrowser.MediaEncoding</RootNamespace>
+ <AssemblyName>MediaBrowser.MediaEncoding</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="BDInfo">
+ <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\BDInfo.dll</HintPath>
+ </Reference>
+ <Reference Include="DvdLib">
+ <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BdInfo\BdInfoExaminer.cs" />
+ <Compile Include="Encoder\ImageEncoder.cs" />
+ <Compile Include="Encoder\MediaEncoder.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
+ <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
+ <Name>MediaBrowser.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
+ <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
+ <Name>MediaBrowser.Controller</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
+ <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
+ <Name>MediaBrowser.Model</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..6616e46ac
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MediaBrowser.MediaEncoding")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MediaBrowser.MediaEncoding")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("05f49ab9-2a90-4332-9d41-7817a9cccd90")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/MediaBrowser.MediaEncoding/packages.config b/MediaBrowser.MediaEncoding/packages.config
new file mode 100644
index 000000000..6e52b72b8
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index b3c3f278e..b2ca97f55 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
- using (var stream = await _mediaEncoder.ExtractImage(new[] { item.Path }, InputType.File, true, null, null, cancellationToken).ConfigureAwait(false))
+ using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false))
{
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 58fe7f66d..cb326c5ad 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -113,8 +113,6 @@ namespace MediaBrowser.Providers.MediaInfo
{
cancellationToken.ThrowIfCancellationRequested();
- cancellationToken.ThrowIfCancellationRequested();
-
var idString = item.Id.ToString("N");
var cachePath = Path.Combine(_appPaths.CachePath,
"ffprobe-video",
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index 354758497..70daa3f51 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.MediaInfo
var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, item.LocationType == LocationType.Remote, item.VideoType, item.IsoType, isoMount, item.PlayableStreamFileNames, out type);
- var stream = await _mediaEncoder.ExtractImage(inputPath, type, false, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
+ var stream = await _mediaEncoder.ExtractVideoImage(inputPath, type, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
return new DynamicImageResponse
{
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index 0a0b3f4bc..9279fd8d7 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -249,17 +249,24 @@ namespace MediaBrowser.Server.Implementations.IO
// Creating a FileSystemWatcher over the LAN can take hundreds of milliseconds, so wrap it in a Task to do them all in parallel
Task.Run(() =>
{
- var newWatcher = new FileSystemWatcher(path, "*") { IncludeSubdirectories = true, InternalBufferSize = 32767 };
+ try
+ {
+ var newWatcher = new FileSystemWatcher(path, "*")
+ {
+ IncludeSubdirectories = true,
+ InternalBufferSize = 32767
+ };
- newWatcher.Created += watcher_Changed;
- newWatcher.Deleted += watcher_Changed;
- newWatcher.Renamed += watcher_Changed;
- newWatcher.Changed += watcher_Changed;
+ newWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.DirectoryName |
+ NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size;
- newWatcher.Error += watcher_Error;
+ newWatcher.Created += watcher_Changed;
+ newWatcher.Deleted += watcher_Changed;
+ newWatcher.Renamed += watcher_Changed;
+ newWatcher.Changed += watcher_Changed;
+
+ newWatcher.Error += watcher_Error;
- try
- {
if (_fileSystemWatchers.TryAdd(path, newWatcher))
{
newWatcher.EnableRaisingEvents = true;
@@ -272,11 +279,7 @@ namespace MediaBrowser.Server.Implementations.IO
}
}
- catch (IOException ex)
- {
- Logger.ErrorException("Error watching path: {0}", ex, path);
- }
- catch (PlatformNotSupportedException ex)
+ catch (Exception ex)
{
Logger.ErrorException("Error watching path: {0}", ex, path);
}
@@ -346,7 +349,9 @@ namespace MediaBrowser.Server.Implementations.IO
{
try
{
- OnWatcherChanged(e);
+ Logger.Debug("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath);
+
+ ReportFileSystemChanged(e.FullPath);
}
catch (Exception ex)
{
@@ -354,13 +359,6 @@ namespace MediaBrowser.Server.Implementations.IO
}
}
- private void OnWatcherChanged(FileSystemEventArgs e)
- {
- Logger.Debug("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath);
-
- ReportFileSystemChanged(e.FullPath);
- }
-
public void ReportFileSystemChanged(string path)
{
if (string.IsNullOrEmpty(path))
@@ -370,12 +368,9 @@ namespace MediaBrowser.Server.Implementations.IO
var filename = Path.GetFileName(path);
- // Ignore certain files
- if (!string.IsNullOrEmpty(filename) && _alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase))
- {
- return;
- }
+ var monitorPath = !(!string.IsNullOrEmpty(filename) && _alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase));
+ // Ignore certain files
var tempIgnorePaths = _tempIgnoredPaths.Keys.ToList();
// If the parent of an ignored path has a change event, ignore that too
@@ -416,12 +411,15 @@ namespace MediaBrowser.Server.Implementations.IO
}))
{
- return;
+ monitorPath = false;
}
- // Avoid implicitly captured closure
- var affectedPath = path;
- _affectedPaths.AddOrUpdate(path, path, (key, oldValue) => affectedPath);
+ if (monitorPath)
+ {
+ // Avoid implicitly captured closure
+ var affectedPath = path;
+ _affectedPaths.AddOrUpdate(path, path, (key, oldValue) => affectedPath);
+ }
lock (_timerLock)
{
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 73a12caf2..ea7ef2ed6 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -48,14 +48,6 @@
<Reference Include="Alchemy">
<HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
</Reference>
- <Reference Include="BDInfo, Version=1.0.5167.21152, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\BDInfo.dll</HintPath>
- </Reference>
- <Reference Include="DvdLib, Version=1.0.5167.21152, Culture=neutral, PublicKeyToken=7a2f3f5ec8d93575, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
- </Reference>
<Reference Include="Mono.Nat, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Mono.Nat.1.2.3\lib\Net40\Mono.Nat.dll</HintPath>
@@ -105,7 +97,6 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
- <Compile Include="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Channels\ChannelImageProvider.cs" />
<Compile Include="Channels\ChannelItemImageProvider.cs" />
<Compile Include="Channels\ChannelManager.cs" />
@@ -191,7 +182,6 @@
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />
- <Compile Include="MediaEncoder\MediaEncoder.cs" />
<Compile Include="News\NewsEntryPoint.cs" />
<Compile Include="News\NewsService.cs" />
<Compile Include="Persistence\SqliteChapterRepository.cs" />
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
index f74865d2c..7237ffee5 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -178,7 +178,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
- using (var stream = await _encoder.ExtractImage(inputPath, type, false, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
+ using (var stream = await _encoder.ExtractVideoImage(inputPath, type, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
{
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs
index f4e7fd0a6..fde1e7f21 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs
@@ -37,6 +37,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
var createTableCommand
= "create table if not exists mediastreams ";
+ // Add PixelFormat column
+
createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PRIMARY KEY (ItemId, StreamIndex))";
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index f04536190..d82e880c9 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Alchemy" version="2.2.1" targetFramework="net45" />
- <package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.3" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.91.3" targetFramework="net45" />
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 06ffa37a1..6083158bc 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -33,13 +33,14 @@ using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Themes;
using MediaBrowser.Dlna;
using MediaBrowser.Dlna.PlayTo;
+using MediaBrowser.MediaEncoding.BdInfo;
+using MediaBrowser.MediaEncoding.Encoder;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Updates;
using MediaBrowser.Providers.Manager;
using MediaBrowser.Server.Implementations;
-using MediaBrowser.Server.Implementations.BdInfo;
using MediaBrowser.Server.Implementations.Channels;
using MediaBrowser.Server.Implementations.Collections;
using MediaBrowser.Server.Implementations.Configuration;
@@ -821,7 +822,10 @@ namespace MediaBrowser.ServerApplication
// Server implementations
list.Add(typeof(ServerApplicationPaths).Assembly);
- // Dlna implementations
+ // MediaEncoding
+ list.Add(typeof(MediaEncoder).Assembly);
+
+ // Dlna
list.Add(typeof(PlayToServerEntryPoint).Assembly);
list.AddRange(Assemblies.GetAssembliesWithParts());
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 227d0dd1d..d999841ca 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -195,6 +195,10 @@
<Project>{734098eb-6dc1-4dd0-a1ca-3140dcd2737c}</Project>
<Name>MediaBrowser.Dlna</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj">
+ <Project>{0bd82fa6-eb8a-4452-8af5-74f9c3849451}</Project>
+ <Name>MediaBrowser.MediaEncoding</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index e05b8ae6a..c2f9dff59 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ServerApplicat
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaBrowser.Dlna\MediaBrowser.Dlna.csproj", "{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -247,6 +249,20 @@ Global
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Win32.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x64.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Win32.ActiveCfg = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x64.ActiveCfg = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE