diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 98cc8dddaf..b530a1e8bc 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -1,11 +1,11 @@
-using System.Globalization;
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -27,6 +27,20 @@ namespace MediaBrowser.Api.LiveTv
[ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string UserId { get; set; }
+
+ ///
+ /// Skips over a given number of items within the results. Use for paging.
+ ///
+ /// The start index.
+ [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? StartIndex { get; set; }
+
+ ///
+ /// The maximum number of items to return
+ ///
+ /// The limit.
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
}
[Route("/LiveTv/Channels/{Id}", "GET")]
@@ -116,26 +130,26 @@ namespace MediaBrowser.Api.LiveTv
public string SeriesTimerId { get; set; }
}
- [Route("/LiveTv/Programs", "GET")]
+ [Route("/LiveTv/Programs", "GET,POST")]
[Api(Description = "Gets available live tv epgs..")]
public class GetPrograms : IReturn>
{
- [ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ [ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string ChannelIds { get; set; }
- [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string UserId { get; set; }
- [ApiMember(Name = "MinStartDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "MinStartDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string MinStartDate { get; set; }
- [ApiMember(Name = "MaxStartDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "MaxStartDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string MaxStartDate { get; set; }
- [ApiMember(Name = "MinEndDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "MinEndDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string MinEndDate { get; set; }
- [ApiMember(Name = "MaxEndDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "MaxEndDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string MaxEndDate { get; set; }
}
@@ -260,7 +274,9 @@ namespace MediaBrowser.Api.LiveTv
var result = _liveTvManager.GetChannels(new ChannelQuery
{
ChannelType = request.Type,
- UserId = request.UserId
+ UserId = request.UserId,
+ StartIndex = request.StartIndex,
+ Limit = request.Limit
}, CancellationToken.None).Result;
@@ -309,6 +325,11 @@ namespace MediaBrowser.Api.LiveTv
return ToOptimizedResult(result);
}
+ public object Post(GetPrograms request)
+ {
+ return Get(request);
+ }
+
public object Get(GetRecordings request)
{
var result = _liveTvManager.GetRecordings(new RecordingQuery
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index dc34fca77c..c400da5bf3 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -253,25 +253,44 @@ namespace MediaBrowser.Api.Playback
return returnFirstIfNoIndex ? streams.FirstOrDefault() : null;
}
+ protected EncodingQuality GetQualitySetting()
+ {
+ var quality = ServerConfigurationManager.Configuration.MediaEncodingQuality;
+
+ if (quality == EncodingQuality.Auto)
+ {
+ var cpuCount = Environment.ProcessorCount;
+
+ if (cpuCount >= 4)
+ {
+ return EncodingQuality.HighQuality;
+ }
+
+ return EncodingQuality.HighSpeed;
+ }
+
+ return quality;
+ }
+
///
/// Gets the number of threads.
///
/// System.Int32.
/// Unrecognized MediaEncodingQuality value.
- protected int GetNumberOfThreads()
+ protected int GetNumberOfThreads(bool isWebm)
{
- var quality = ServerConfigurationManager.Configuration.MediaEncodingQuality;
+ // Webm: http://www.webmproject.org/docs/encoder-parameters/
+ // The decoder will usually automatically use an appropriate number of threads according to how many cores are available but it can only use multiple threads
+ // for the coefficient data if the encoder selected --token-parts > 0 at encode time.
- switch (quality)
+ switch (GetQualitySetting())
{
- case EncodingQuality.Auto:
- return 0;
case EncodingQuality.HighSpeed:
return 2;
case EncodingQuality.HighQuality:
- return 2;
+ return isWebm ? Math.Min(3, Environment.ProcessorCount - 1) : 2;
case EncodingQuality.MaxQuality:
- return 0;
+ return isWebm ? Math.Max(2, Environment.ProcessorCount - 1) : 0;
default:
throw new Exception("Unrecognized MediaEncodingQuality value.");
}
@@ -285,30 +304,74 @@ namespace MediaBrowser.Api.Playback
/// System.String.
protected string GetVideoQualityParam(StreamState state, string videoCodec)
{
- var args = string.Empty;
-
// webm
if (videoCodec.Equals("libvpx", StringComparison.OrdinalIgnoreCase))
{
- args = "-speed 16 -quality good -profile:v 0 -slices 8";
+ // http://www.webmproject.org/docs/encoder-parameters/
+ return "-speed 16 -quality good -profile:v 0 -slices 8";
}
// asf/wmv
- else if (videoCodec.Equals("wmv2", StringComparison.OrdinalIgnoreCase))
+ if (videoCodec.Equals("wmv2", StringComparison.OrdinalIgnoreCase))
{
- args = "-g 100 -qmax 15";
+ return "-g 100 -qmax 15";
}
- else if (videoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase))
+ if (videoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase))
{
- args = "-preset superfast";
- }
- else if (videoCodec.Equals("mpeg4", StringComparison.OrdinalIgnoreCase))
- {
- args = "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
+ return "-preset superfast";
}
- return args.Trim();
+ if (videoCodec.Equals("mpeg4", StringComparison.OrdinalIgnoreCase))
+ {
+ return "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
+ }
+
+ return string.Empty;
+ }
+
+ protected string GetAudioFilterParam(StreamState state, bool isHls)
+ {
+ var volParam = string.Empty;
+ var audioSampleRate = string.Empty;
+
+ var channels = GetNumAudioChannelsParam(state.Request, state.AudioStream);
+
+ // Boost volume to 200% when downsampling from 6ch to 2ch
+ if (channels.HasValue && channels.Value <= 2 && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
+ {
+ volParam = ",volume=2.000000";
+ }
+
+ if (state.Request.AudioSampleRate.HasValue)
+ {
+ audioSampleRate = state.Request.AudioSampleRate.Value + ":";
+ }
+
+ var adelay = isHls ? "adelay=1," : string.Empty;
+
+ var pts = string.Empty;
+
+ if (state.SubtitleStream != null)
+ {
+ if (state.SubtitleStream.Codec.IndexOf("srt", StringComparison.OrdinalIgnoreCase) != -1 ||
+ state.SubtitleStream.Codec.IndexOf("subrip", StringComparison.OrdinalIgnoreCase) != -1 ||
+ string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
+ {
+ var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
+
+ pts = string.Format(",asetpts=PTS-{0}/TB",
+ Math.Round(seconds).ToString(UsCulture));
+ }
+ }
+
+ return string.Format("-af \"{0}aresample={1}async=1{2}{3}\"",
+
+ adelay,
+ audioSampleRate,
+ volParam,
+ pts);
}
///
@@ -323,6 +386,7 @@ namespace MediaBrowser.Api.Playback
// http://sonnati.wordpress.com/2012/10/19/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-vi/
var assSubtitleParam = string.Empty;
+ var copyTsParam = string.Empty;
var request = state.VideoRequest;
@@ -333,7 +397,8 @@ namespace MediaBrowser.Api.Playback
string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
{
- assSubtitleParam = GetTextSubtitleParam(state, request.StartTimeTicks, performTextSubtitleConversion);
+ assSubtitleParam = GetTextSubtitleParam(state, performTextSubtitleConversion);
+ copyTsParam = " -copyts";
}
}
@@ -343,7 +408,7 @@ namespace MediaBrowser.Api.Playback
var widthParam = request.Width.Value.ToString(UsCulture);
var heightParam = request.Height.Value.ToString(UsCulture);
- return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", widthParam, heightParam, assSubtitleParam);
+ return string.Format("{3} -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", widthParam, heightParam, assSubtitleParam, copyTsParam);
}
var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
@@ -354,8 +419,8 @@ namespace MediaBrowser.Api.Playback
var widthParam = request.Width.Value.ToString(UsCulture);
return isH264Output ?
- string.Format(" -vf \"scale={0}:trunc(ow/a/2)*2{1}\"", widthParam, assSubtitleParam) :
- string.Format(" -vf \"scale={0}:-1{1}\"", widthParam, assSubtitleParam);
+ string.Format("{2} -vf \"scale={0}:trunc(ow/a/2)*2{1}\"", widthParam, assSubtitleParam, copyTsParam) :
+ string.Format("{2} -vf \"scale={0}:-1{1}\"", widthParam, assSubtitleParam, copyTsParam);
}
// If a fixed height was requested
@@ -364,8 +429,8 @@ namespace MediaBrowser.Api.Playback
var heightParam = request.Height.Value.ToString(UsCulture);
return isH264Output ?
- string.Format(" -vf \"scale=trunc(oh*a*2)/2:{0}{1}\"", heightParam, assSubtitleParam) :
- string.Format(" -vf \"scale=-1:{0}{1}\"", heightParam, assSubtitleParam);
+ string.Format("{2} -vf \"scale=trunc(oh*a*2)/2:{0}{1}\"", heightParam, assSubtitleParam, copyTsParam) :
+ string.Format("{2} -vf \"scale=-1:{0}{1}\"", heightParam, assSubtitleParam, copyTsParam);
}
// If a max width was requested
@@ -374,8 +439,8 @@ namespace MediaBrowser.Api.Playback
var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
return isH264Output ?
- string.Format(" -vf \"scale=min(iw\\,{0}):trunc(ow/a/2)*2{1}\"", maxWidthParam, assSubtitleParam) :
- string.Format(" -vf \"scale=min(iw\\,{0}):-1{1}\"", maxWidthParam, assSubtitleParam);
+ string.Format("{2} -vf \"scale=min(iw\\,{0}):trunc(ow/a/2)*2{1}\"", maxWidthParam, assSubtitleParam, copyTsParam) :
+ string.Format("{2} -vf \"scale=min(iw\\,{0}):-1{1}\"", maxWidthParam, assSubtitleParam, copyTsParam);
}
// If a max height was requested
@@ -384,8 +449,8 @@ namespace MediaBrowser.Api.Playback
var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
return isH264Output ?
- string.Format(" -vf \"scale=trunc(oh*a*2)/2:min(ih\\,{0}){1}\"", maxHeightParam, assSubtitleParam) :
- string.Format(" -vf \"scale=-1:min(ih\\,{0}){1}\"", maxHeightParam, assSubtitleParam);
+ string.Format("{2} -vf \"scale=trunc(oh*a*2)/2:min(ih\\,{0}){1}\"", maxHeightParam, assSubtitleParam, copyTsParam) :
+ string.Format("{2} -vf \"scale=-1:min(ih\\,{0}){1}\"", maxHeightParam, assSubtitleParam, copyTsParam);
}
if (state.VideoStream == null)
@@ -408,45 +473,45 @@ namespace MediaBrowser.Api.Playback
var widthParam = outputSize.Width.ToString(UsCulture);
var heightParam = outputSize.Height.ToString(UsCulture);
- return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", widthParam, heightParam, assSubtitleParam);
+ return string.Format("{3} -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", widthParam, heightParam, assSubtitleParam, copyTsParam);
}
// Otherwise use -vf scale since ffmpeg will ensure internally that the aspect ratio is preserved
- return string.Format(" -vf \"scale={0}:-1{1}\"", Convert.ToInt32(outputSize.Width), assSubtitleParam);
+ return string.Format("{2} -vf \"scale={0}:-1{1}\"", Convert.ToInt32(outputSize.Width), assSubtitleParam, copyTsParam);
}
///
/// Gets the text subtitle param.
///
/// The state.
- /// The start time ticks.
/// if set to true [perform conversion].
/// System.String.
- protected string GetTextSubtitleParam(StreamState state, long? startTimeTicks, bool performConversion)
+ protected string GetTextSubtitleParam(StreamState state, bool performConversion)
{
- var path = state.SubtitleStream.IsExternal ? GetConvertedAssPath(state.MediaPath, state.SubtitleStream, startTimeTicks, performConversion) :
- GetExtractedAssPath(state, startTimeTicks, performConversion);
+ var path = state.SubtitleStream.IsExternal ? GetConvertedAssPath(state.MediaPath, state.SubtitleStream, performConversion) :
+ GetExtractedAssPath(state, performConversion);
if (string.IsNullOrEmpty(path))
{
return string.Empty;
}
- return string.Format(",ass='{0}'", path.Replace('\\', '/').Replace(":/", "\\:/"));
+ var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
+
+ return string.Format(",ass='{0}',setpts=PTS -{1}/TB",
+ path.Replace('\\', '/').Replace(":/", "\\:/"),
+ Math.Round(seconds).ToString(UsCulture));
}
///
/// Gets the extracted ass path.
///
/// The state.
- /// The start time ticks.
/// if set to true [perform conversion].
/// System.String.
- private string GetExtractedAssPath(StreamState state, long? startTimeTicks, bool performConversion)
+ private string GetExtractedAssPath(StreamState state, bool performConversion)
{
- var offset = TimeSpan.FromTicks(startTimeTicks ?? 0);
-
- var path = FFMpegManager.Instance.GetSubtitleCachePath(state.MediaPath, state.SubtitleStream, offset, ".ass");
+ var path = FFMpegManager.Instance.GetSubtitleCachePath(state.MediaPath, state.SubtitleStream, ".ass");
if (performConversion)
{
@@ -460,7 +525,7 @@ namespace MediaBrowser.Api.Playback
Directory.CreateDirectory(parentPath);
- var task = MediaEncoder.ExtractTextSubtitle(inputPath, type, state.SubtitleStream.Index, offset, path, CancellationToken.None);
+ var task = MediaEncoder.ExtractTextSubtitle(inputPath, type, state.SubtitleStream.Index, path, CancellationToken.None);
Task.WaitAll(task);
}
@@ -478,14 +543,11 @@ namespace MediaBrowser.Api.Playback
///
/// The media path.
/// The subtitle stream.
- /// The start time ticks.
/// if set to true [perform conversion].
/// System.String.
- private string GetConvertedAssPath(string mediaPath, MediaStream subtitleStream, long? startTimeTicks, bool performConversion)
+ private string GetConvertedAssPath(string mediaPath, MediaStream subtitleStream, bool performConversion)
{
- var offset = TimeSpan.FromTicks(startTimeTicks ?? 0);
-
- var path = FFMpegManager.Instance.GetSubtitleCachePath(mediaPath, subtitleStream, offset, ".ass");
+ var path = FFMpegManager.Instance.GetSubtitleCachePath(mediaPath, subtitleStream, ".ass");
if (performConversion)
{
@@ -495,7 +557,7 @@ namespace MediaBrowser.Api.Playback
Directory.CreateDirectory(parentPath);
- var task = MediaEncoder.ConvertTextSubtitleToAss(subtitleStream.Path, path, subtitleStream.Language, offset, CancellationToken.None);
+ var task = MediaEncoder.ConvertTextSubtitleToAss(subtitleStream.Path, path, subtitleStream.Language, CancellationToken.None);
Task.WaitAll(task);
}
@@ -534,9 +596,9 @@ namespace MediaBrowser.Api.Playback
videoSizeParam = string.Format(",scale={0}:{1}", state.VideoStream.Width.Value.ToString(UsCulture), state.VideoStream.Height.Value.ToString(UsCulture));
}
- return string.Format(" -filter_complex \"[0:{0}]format=yuva444p{3},lut=u=128:v=128:y=gammaval(.3)[sub] ; [0:{1}] [sub] overlay{2}\"",
- state.SubtitleStream.Index,
- state.VideoStream.Index,
+ return string.Format(" -filter_complex \"[0:{0}]format=yuva444p{3},lut=u=128:v=128:y=gammaval(.3)[sub] ; [0:{1}] [sub] overlay{2}\"",
+ state.SubtitleStream.Index,
+ state.VideoStream.Index,
outputSizeParam,
videoSizeParam);
}
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 9abedde4b4..9c42c77292 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -113,7 +113,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (isPlaylistNewlyCreated)
{
var minimumSegmentCount = 3;
- var quality = ServerConfigurationManager.Configuration.MediaEncodingQuality;
+ var quality = GetQualitySetting();
if (quality == EncodingQuality.HighSpeed || quality == EncodingQuality.HighQuality)
{
@@ -267,9 +267,9 @@ namespace MediaBrowser.Api.Playback.Hls
var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds);
- var threads = GetNumberOfThreads();
+ var threads = GetNumberOfThreads(false);
- var args = string.Format("{0}{1} {2} {3} -i {4}{5} -threads {6} {7} {8} -sc_threshold 0 {9} -hls_time 10 -start_number 0 -hls_list_size 1440 \"{10}\"",
+ var args = string.Format("{0}{1} {2} {3} -i {4}{5} -map_metadata -1 -threads {6} {7} {8} -sc_threshold 0 {9} -hls_time 10 -start_number 0 -hls_list_size 1440 \"{10}\"",
itsOffset,
probeSize,
GetUserAgentParam(state.MediaPath),
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 583082500c..8fbb42f24c 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -80,21 +80,7 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -ab " + bitrate.Value.ToString(UsCulture);
}
- var volParam = string.Empty;
- var audioSampleRate = string.Empty;
-
- // Boost volume to 200% when downsampling from 6ch to 2ch
- if (channels.HasValue && channels.Value <= 2 && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
- {
- volParam = ",volume=2.000000";
- }
-
- if (state.Request.AudioSampleRate.HasValue)
- {
- audioSampleRate = state.Request.AudioSampleRate.Value + ":";
- }
-
- args += string.Format(" -af \"adelay=1,aresample={0}async=1{1}\"", audioSampleRate, volParam);
+ args += " " + GetAudioFilterParam(state, true);
return args;
}
diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
index baf7f48fe1..050c06627d 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Playback.Progressive
const string vn = " -vn";
- var threads = GetNumberOfThreads();
+ var threads = GetNumberOfThreads(false);
return string.Format("{0} -i {1}{2} -threads {3}{4} {5} -id3v2_version 3 -write_id3v1 1 \"{6}\"",
GetFastSeekCommandLineParameter(request),
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index e367801d25..440632825e 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using System;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@@ -106,6 +107,7 @@ namespace MediaBrowser.Api.Playback.Progressive
var transferMode = GetHeader("transferMode.dlna.org");
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
+ responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
var contentFeatures = string.Empty;
var extension = GetOutputFileExtension(state);
@@ -118,22 +120,22 @@ namespace MediaBrowser.Api.Playback.Progressive
const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
- //if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
- //{
- // contentFeatures = "DLNA.ORG_PN=MP3";
- //}
- //else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
- //{
- // contentFeatures = "DLNA.ORG_PN=AAC_ISO";
- //}
- //else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
- //{
- // contentFeatures = "DLNA.ORG_PN=WMABASE";
- //}
- //else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
- //{
- // contentFeatures = "DLNA.ORG_PN=AVI";
- //}
+ if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=MP3";
+ }
+ else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=AAC_ISO";
+ }
+ else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=WMABASE";
+ }
+ else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
+ {
+ contentFeatures = "DLNA.ORG_PN=AVI";
+ }
//else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
//{
// contentFeatures = "DLNA.ORG_PN=MPEG4_P2_SP_AAC";
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index cdc8e2ffb0..c3ec02a59f 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -104,9 +104,9 @@ namespace MediaBrowser.Api.Playback.Progressive
format = " -f mp4 -movflags frag_keyframe+empty_moov";
}
- var threads = string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase) ? 2 : GetNumberOfThreads();
+ var threads = GetNumberOfThreads(string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase));
- return string.Format("{0} {1} {2} -i {3}{4}{5} {6} {7} -threads {8} {9}{10} \"{11}\"",
+ return string.Format("{0} {1} {2} -i {3}{4}{5} {6} {7} -map_metadata -1 -threads {8} {9}{10} \"{11}\"",
probeSize,
GetUserAgentParam(state.MediaPath),
GetFastSeekCommandLineParameter(state.Request),
@@ -170,6 +170,7 @@ namespace MediaBrowser.Api.Playback.Progressive
if (bitrate.HasValue)
{
qualityParam += string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
+ //qualityParam += string.Format(" -maxrate {0} -bufsize {1}", bitrate.Value.ToString(UsCulture), (bitrate.Value * 2).ToString(UsCulture));
}
if (!string.IsNullOrEmpty(qualityParam))
@@ -238,21 +239,7 @@ namespace MediaBrowser.Api.Playback.Progressive
args += " -ab " + bitrate.Value.ToString(UsCulture);
}
- var volParam = string.Empty;
- var AudioSampleRate = string.Empty;
-
- // Boost volume to 200% when downsampling from 6ch to 2ch
- if (channels.HasValue && channels.Value <= 2 && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
- {
- volParam = ",volume=2.000000";
- }
-
- if (state.Request.AudioSampleRate.HasValue)
- {
- AudioSampleRate = state.Request.AudioSampleRate.Value + ":";
- }
-
- args += string.Format(" -af \"aresample={0}async=1{1}\"", AudioSampleRate, volParam);
+ args += " " + GetAudioFilterParam(state, true);
return args;
}
diff --git a/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs b/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs
index 31fa78fdb8..82643779b3 100644
--- a/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs
+++ b/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs
@@ -40,11 +40,10 @@ namespace MediaBrowser.Common.MediaInfo
/// The input files.
/// The type.
/// Index of the subtitle stream.
- /// The offset.
/// The output path.
/// The cancellation token.
/// Task.
- Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex, TimeSpan offset, string outputPath, CancellationToken cancellationToken);
+ Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex, string outputPath, CancellationToken cancellationToken);
///
/// Converts the text subtitle to ass.
@@ -52,10 +51,9 @@ namespace MediaBrowser.Common.MediaInfo
/// The input path.
/// The output path.
/// The language.
- /// The offset.
/// The cancellation token.
/// Task.
- Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, TimeSpan offset, CancellationToken cancellationToken);
+ Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, CancellationToken cancellationToken);
///
/// Gets the media info.
diff --git a/MediaBrowser.Common/Net/MimeTypes.cs b/MediaBrowser.Common/Net/MimeTypes.cs
index 47536a341e..85b9b1f38f 100644
--- a/MediaBrowser.Common/Net/MimeTypes.cs
+++ b/MediaBrowser.Common/Net/MimeTypes.cs
@@ -67,7 +67,7 @@ namespace MediaBrowser.Common.Net
}
if (ext.Equals(".avi", StringComparison.OrdinalIgnoreCase))
{
- return "video/avi";
+ return "video/x-msvideo";
}
if (ext.Equals(".m4v", StringComparison.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
index ced53299d8..6442229499 100644
--- a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
+++ b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
@@ -235,12 +235,11 @@ namespace MediaBrowser.Controller.MediaInfo
///
/// The media path.
/// The subtitle stream.
- /// The offset.
/// The output extension.
/// System.String.
- public string GetSubtitleCachePath(string mediaPath, MediaStream subtitleStream, TimeSpan? offset, string outputExtension)
+ public string GetSubtitleCachePath(string mediaPath, MediaStream subtitleStream, string outputExtension)
{
- var ticksParam = offset.HasValue ? "_" + offset.Value.Ticks : "";
+ var ticksParam = string.Empty;
if (subtitleStream.IsExternal)
{
diff --git a/MediaBrowser.Model/LiveTv/ChannelQuery.cs b/MediaBrowser.Model/LiveTv/ChannelQuery.cs
index 578f3039bb..eb3b20ce3b 100644
--- a/MediaBrowser.Model/LiveTv/ChannelQuery.cs
+++ b/MediaBrowser.Model/LiveTv/ChannelQuery.cs
@@ -17,5 +17,17 @@ namespace MediaBrowser.Model.LiveTv
///
/// The user identifier.
public string UserId { get; set; }
+
+ ///
+ /// Skips over a given number of items within the results. Use for paging.
+ ///
+ /// The start index.
+ public int? StartIndex { get; set; }
+
+ ///
+ /// The maximum number of items to return
+ ///
+ /// The limit.
+ public int? Limit { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
index b9cabded7d..21e50f4001 100644
--- a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
@@ -51,7 +51,7 @@ namespace MediaBrowser.Providers.Movies
{
var list = new List();
- var results = FetchImages(item, _jsonSerializer);
+ var results = await FetchImages((BaseItem)item, _jsonSerializer, cancellationToken).ConfigureAwait(false);
if (results == null)
{
@@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.Movies
var tmdbImageUrl = tmdbSettings.images.base_url + "original";
- list.AddRange(GetPosters(results, item).Select(i => new RemoteImageInfo
+ list.AddRange(GetPosters(results).Select(i => new RemoteImageInfo
{
Url = tmdbImageUrl + i.file_path,
CommunityRating = i.vote_average,
@@ -75,7 +75,7 @@ namespace MediaBrowser.Providers.Movies
RatingType = RatingType.Score
}));
- list.AddRange(GetBackdrops(results, item).Select(i => new RemoteImageInfo
+ list.AddRange(GetBackdrops(results).Select(i => new RemoteImageInfo
{
Url = tmdbImageUrl + i.file_path,
CommunityRating = i.vote_average,
@@ -119,9 +119,8 @@ namespace MediaBrowser.Providers.Movies
/// Gets the posters.
///
/// The images.
- /// The item.
/// IEnumerable{MovieDbProvider.Poster}.
- private IEnumerable GetPosters(MovieDbProvider.Images images, IHasImages item)
+ private IEnumerable GetPosters(MovieDbProvider.Images images)
{
return images.posters ?? new List();
}
@@ -130,9 +129,8 @@ namespace MediaBrowser.Providers.Movies
/// Gets the backdrops.
///
/// The images.
- /// The item.
/// IEnumerable{MovieDbProvider.Backdrop}.
- private IEnumerable GetBackdrops(MovieDbProvider.Images images, IHasImages item)
+ private IEnumerable GetBackdrops(MovieDbProvider.Images images)
{
var eligibleBackdrops = images.backdrops == null ? new List() :
images.backdrops
@@ -147,10 +145,14 @@ namespace MediaBrowser.Providers.Movies
///
/// The item.
/// The json serializer.
+ /// The cancellation token.
/// Task{MovieImages}.
- private MovieDbProvider.Images FetchImages(IHasImages item, IJsonSerializer jsonSerializer)
+ private async Task FetchImages(BaseItem item, IJsonSerializer jsonSerializer,
+ CancellationToken cancellationToken)
{
- var path = MovieDbProvider.Current.GetDataFilePath((BaseItem)item);
+ await MovieDbProvider.Current.EnsureMovieInfo(item, cancellationToken).ConfigureAwait(false);
+
+ var path = MovieDbProvider.Current.GetDataFilePath(item);
if (!string.IsNullOrEmpty(path))
{
diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs
index 453284751c..4d3a5baac1 100644
--- a/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs
@@ -52,7 +52,7 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrEmpty(id))
{
- await MovieDbPersonProvider.Current.DownloadPersonInfoIfNeeded(id, cancellationToken).ConfigureAwait(false);
+ await MovieDbPersonProvider.Current.EnsurePersonInfo(id, cancellationToken).ConfigureAwait(false);
var dataFilePath = MovieDbPersonProvider.GetPersonDataFilePath(_config.ApplicationPaths, id);
diff --git a/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs b/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs
index c16c504125..70ad6611a1 100644
--- a/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbPersonProvider.cs
@@ -235,7 +235,7 @@ namespace MediaBrowser.Providers.Movies
/// Task.
private async Task FetchInfo(Person person, string id, bool isForcedRefresh, CancellationToken cancellationToken)
{
- await DownloadPersonInfoIfNeeded(id, cancellationToken).ConfigureAwait(false);
+ await EnsurePersonInfo(id, cancellationToken).ConfigureAwait(false);
if (isForcedRefresh || !HasAltMeta(person))
{
@@ -249,7 +249,7 @@ namespace MediaBrowser.Providers.Movies
}
}
- internal async Task DownloadPersonInfoIfNeeded(string id, CancellationToken cancellationToken)
+ internal async Task EnsurePersonInfo(string id, CancellationToken cancellationToken)
{
var personDataPath = GetPersonDataPath(ConfigurationManager.ApplicationPaths, id);
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index fed1b444e8..8dd64fd14c 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -558,6 +558,31 @@ namespace MediaBrowser.Providers.Movies
JsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
+ internal Task EnsureMovieInfo(BaseItem item, CancellationToken cancellationToken)
+ {
+ var path = GetDataFilePath(item);
+
+ var fileInfo = _fileSystem.GetFileSystemInfo(path);
+
+ if (fileInfo.Exists)
+ {
+ // If it's recent or automatic updates are enabled, don't re-download
+ if (ConfigurationManager.Configuration.EnableTmdbUpdates || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7)
+ {
+ return Task.FromResult(true);
+ }
+ }
+
+ var id = item.GetProviderId(MetadataProviders.Tmdb);
+
+ if (string.IsNullOrEmpty(id))
+ {
+ return Task.FromResult(true);
+ }
+
+ return DownloadMovieInfo(id, item is BoxSet, item.GetPreferredMetadataLanguage(), cancellationToken);
+ }
+
///
/// Gets the data file path.
///
@@ -575,7 +600,7 @@ namespace MediaBrowser.Providers.Movies
return GetDataFilePath(item is BoxSet, id, item.GetPreferredMetadataLanguage());
}
- internal string GetDataFilePath(bool isBoxset, string tmdbId, string preferredLanguage)
+ private string GetDataFilePath(bool isBoxset, string tmdbId, string preferredLanguage)
{
var path = GetMovieDataPath(ConfigurationManager.ApplicationPaths, isBoxset, tmdbId);
diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
index 291d2ff4dd..d9a367e2cc 100644
--- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
@@ -69,7 +69,7 @@ namespace MediaBrowser.Providers.Movies
/// Task.
public async Task Run(IProgress progress, CancellationToken cancellationToken)
{
- if (!_config.Configuration.EnableInternetProviders)
+ if (!_config.Configuration.EnableInternetProviders && !_config.Configuration.EnableTmdbUpdates)
{
progress.Report(100);
return;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index 7dc210cccf..b6622a3100 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -98,7 +98,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
});
}
- var returnChannels = channels.OrderBy(i =>
+ channels = channels.OrderBy(i =>
{
double number = 0;
@@ -109,14 +109,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return number;
- }).ThenBy(i => i.Name)
- .Select(i => _tvDtoService.GetChannelInfoDto(i, GetCurrentProgram(i.ChannelInfo.Id), user))
- .ToArray();
+ }).ThenBy(i => i.Name);
+
+ var allChannels = channels.ToList();
+ IEnumerable allEnumerable = allChannels;
+
+ if (query.StartIndex.HasValue)
+ {
+ allEnumerable = allEnumerable.Skip(query.StartIndex.Value);
+ }
+
+ if (query.Limit.HasValue)
+ {
+ allEnumerable = allEnumerable.Take(query.Limit.Value);
+ }
+
+ var returnChannels = allEnumerable
+ .Select(i => _tvDtoService.GetChannelInfoDto(i, GetCurrentProgram(i.ChannelInfo.Id), user))
+ .ToArray();
var result = new QueryResult
{
Items = returnChannels,
- TotalRecordCount = returnChannels.Length
+ TotalRecordCount = allChannels.Count
};
return Task.FromResult(result);
@@ -575,9 +590,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.Where(i => _tvDtoService.GetInternalSeriesTimerId(currentServiceName, i.SeriesTimerId) == guid);
}
- IEnumerable entities = await GetEntities(recordings, service.Name, cancellationToken).ConfigureAwait(false);
+ recordings = recordings.OrderByDescending(i => i.StartDate);
- entities = entities.OrderByDescending(i => i.RecordingInfo.StartDate);
+ IEnumerable entities = await GetEntities(recordings, service.Name, cancellationToken).ConfigureAwait(false);
if (user != null)
{
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
index 990b695ae4..bcc857a805 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
@@ -96,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
return _semaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1));
}
-
+
///
/// Gets the media info.
///
@@ -378,11 +378,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The input path.
/// The output path.
/// The language.
- /// The offset.
/// The cancellation token.
/// Task.
- public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, TimeSpan offset,
- CancellationToken cancellationToken)
+ public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -392,7 +390,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
if (!File.Exists(outputPath))
{
- await ConvertTextSubtitleToAssInternal(inputPath, outputPath, language, offset).ConfigureAwait(false);
+ await ConvertTextSubtitleToAssInternal(inputPath, outputPath, language).ConfigureAwait(false);
}
}
finally
@@ -409,13 +407,12 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The input path.
/// The output path.
/// The language.
- /// The offset.
/// Task.
/// inputPath
/// or
/// outputPath
///
- private async Task ConvertTextSubtitleToAssInternal(string inputPath, string outputPath, string language, TimeSpan offset)
+ private async Task ConvertTextSubtitleToAssInternal(string inputPath, string outputPath, string language)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -427,8 +424,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
throw new ArgumentNullException("outputPath");
}
-
- var slowSeekParam = offset.TotalSeconds > 0 ? " -ss " + offset.TotalSeconds.ToString(UsCulture) : string.Empty;
var encodingParam = string.IsNullOrEmpty(language) ? string.Empty :
GetSubtitleLanguageEncodingParam(language) + " ";
@@ -444,7 +439,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
UseShellExecute = false,
FileName = FFMpegPath,
Arguments =
- string.Format("{0} -i \"{1}\" {2} -c:s ass \"{3}\"", encodingParam, inputPath, slowSeekParam, outputPath),
+ string.Format("{0} -i \"{1}\" -c:s ass \"{2}\"", encodingParam, inputPath, outputPath),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
@@ -557,7 +552,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
return string.Empty;
}
-
+
///
/// Gets the subtitle language encoding param.
///
@@ -598,7 +593,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
case "vie":
return "-sub_charenc windows-1258";
case "kor":
- return "-sub_charenc cp949";
+ return "-sub_charenc cp949";
default:
return "-sub_charenc windows-1252";
}
@@ -610,12 +605,11 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The input files.
/// The type.
/// Index of the subtitle stream.
- /// The offset.
/// The output path.
/// The cancellation token.
/// Task.
/// Must use inputPath list overload
- public async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex, TimeSpan offset, string outputPath, CancellationToken cancellationToken)
+ public async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex, string outputPath, CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -625,7 +619,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
if (!File.Exists(outputPath))
{
- await ExtractTextSubtitleInternal(GetInputArgument(inputFiles, type), subtitleStreamIndex, offset, outputPath, cancellationToken).ConfigureAwait(false);
+ await ExtractTextSubtitleInternal(GetInputArgument(inputFiles, type), subtitleStreamIndex, outputPath, cancellationToken).ConfigureAwait(false);
}
}
finally
@@ -639,7 +633,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
///
/// The input path.
/// Index of the subtitle stream.
- /// The offset.
/// The output path.
/// The cancellation token.
/// Task.
@@ -649,7 +642,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// or
/// cancellationToken
///
- private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex, TimeSpan offset, string outputPath, CancellationToken cancellationToken)
+ private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex, string outputPath, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -661,9 +654,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
throw new ArgumentNullException("outputPath");
}
-
- var slowSeekParam = GetSlowSeekCommandLineParameter(offset);
- var fastSeekParam = GetFastSeekCommandLineParameter(offset);
var process = new Process
{
@@ -676,7 +666,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
RedirectStandardError = true,
FileName = FFMpegPath,
- Arguments = string.Format(" {0} -i {1} {2} -map 0:{3} -an -vn -c:s ass \"{4}\"", fastSeekParam, inputPath, slowSeekParam, subtitleStreamIndex, outputPath),
+ Arguments = string.Format("-i {0} -map 0:{1} -an -vn -c:s ass \"{2}\"", inputPath, subtitleStreamIndex, outputPath),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
}
@@ -872,8 +862,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
switch (threedFormat.Value)
{
case Video3DFormat.HalfSideBySide:
- vf = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,scale=600:600/dar";
- // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not.
+ vf = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,scale=600:600/dar";
+ // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not.
break;
case Video3DFormat.FullSideBySide:
vf = "crop=iw/2:ih:0:0,setdar=dar=a,,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,scale=600:600/dar";
@@ -882,7 +872,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
case Video3DFormat.HalfTopAndBottom:
vf = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,scale=600:600/dar";
//htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600
- break;
+ break;
case Video3DFormat.FullTopAndBottom:
vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,scale=600:600/dar";
// ftab crop heigt in half, set the display aspect,crop out any black bars we may have made the scale width to 600
@@ -892,7 +882,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 \"thumbnail,{2}\" -f image2 \"{1}\"", inputPath, outputPath, vf) :
- string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, outputPath, vf);
+ string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, outputPath, vf);
var probeSize = GetProbeSizeArgument(type);
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index d693f90e24..e5fbc7d9fa 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -90,6 +90,12 @@ namespace MediaBrowser.Server.Implementations.Session
var vals = message.Data.Split('|');
+ if (vals.Length < 3)
+ {
+ _logger.Error("Client sent invalid identity message.");
+ return;
+ }
+
var client = vals[0];
var deviceId = vals[1];
var version = vals[2];
diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js
index f2b2d6b7b1..cbe815c03a 100644
--- a/MediaBrowser.WebDashboard/ApiClient.js
+++ b/MediaBrowser.WebDashboard/ApiClient.js
@@ -436,13 +436,26 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
self.getLiveTvPrograms = function (options) {
- var url = self.getUrl("LiveTv/Programs", options || {});
+ options = options || {};
+
+ if (options.channelIds) {
- return self.ajax({
- type: "GET",
- url: url,
- dataType: "json"
- });
+ return self.ajax({
+ type: "POST",
+ url: self.getUrl("LiveTv/Programs"),
+ data: JSON.stringify(options),
+ contentType: "application/json",
+ dataType: "json"
+ });
+
+ } else {
+
+ return self.ajax({
+ type: "GET",
+ url: self.getUrl("LiveTv/Programs", options),
+ dataType: "json"
+ });
+ }
};
self.getLiveTvRecordings = function (options) {
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 3bb7e71050..c47d67815e 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file