diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 670acd37f..5166d5413 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -296,8 +296,8 @@
{4f26d5d8-a7b0-42b3-ba42-7cb7d245934e}
SocketHttpListener.Portable
-
- ..\packages\Emby.XmlTv.1.0.7\lib\portable-net45+win8\Emby.XmlTv.dll
+
+ ..\packages\Emby.XmlTv.1.0.8\lib\portable-net45+win8\Emby.XmlTv.dll
True
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index 21c4006a6..fc0a826b4 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -268,12 +268,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
var results = reader.GetChannels();
// Should this method be async?
- return results.Select(c => new ChannelInfo()
+ return results.Select(c => new ChannelInfo
{
Id = c.Id,
Name = c.DisplayName,
ImageUrl = c.Icon != null && !String.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null,
- Number = c.Id
+ Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number
}).ToList();
}
diff --git a/Emby.Server.Implementations/packages.config b/Emby.Server.Implementations/packages.config
index ccabbc27b..ac4e885c7 100644
--- a/Emby.Server.Implementations/packages.config
+++ b/Emby.Server.Implementations/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 5eea7598b..1b6d55e33 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -912,7 +912,12 @@ namespace MediaBrowser.Api.Playback.Hls
segmentFormat = "mpegts";
}
- return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
+ var videoCodec = EncodingHelper.GetVideoEncoder(state, ApiEntryPoint.Instance.GetEncodingOptions());
+ var breakOnNonKeyFrames = state.Request.BreakOnNonKeyFrames && string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase);
+
+ var breakOnNonKeyFramesArg = breakOnNonKeyFrames ? " -break_non_keyframes 1" : "";
+
+ return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0{12} -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
inputModifier,
EncodingHelper.GetInputArgument(state, encodingOptions),
threads,
@@ -924,7 +929,8 @@ namespace MediaBrowser.Api.Playback.Hls
outputPath,
outputTsArg,
timeDeltaParam,
- segmentFormat
+ segmentFormat,
+ breakOnNonKeyFramesArg
).Trim();
}
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 4e4e8858e..0ee0dab30 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -127,7 +127,7 @@ namespace MediaBrowser.Api.Playback
SetDeviceSpecificData(item, result.MediaSource, profile, authInfo, request.MaxStreamingBitrate,
request.StartTimeTicks ?? 0, result.MediaSource.Id, request.AudioStreamIndex,
- request.SubtitleStreamIndex, request.MaxAudioChannels, request.PlaySessionId, request.UserId, true, true, true, true);
+ request.SubtitleStreamIndex, request.MaxAudioChannels, request.PlaySessionId, request.UserId, true, true, true, true, true, true);
}
else
{
@@ -169,7 +169,7 @@ namespace MediaBrowser.Api.Playback
{
var mediaSourceId = request.MediaSourceId;
- SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex, request.MaxAudioChannels, request.UserId, request.EnableDirectPlay, request.ForceDirectPlayRemoteMediaSource, request.EnableDirectStream, request.EnableTranscoding);
+ SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex, request.MaxAudioChannels, request.UserId, request.EnableDirectPlay, request.ForceDirectPlayRemoteMediaSource, request.EnableDirectStream, request.EnableTranscoding, request.AllowVideoStreamCopy, request.AllowAudioStreamCopy);
}
return info;
@@ -255,13 +255,15 @@ namespace MediaBrowser.Api.Playback
bool enableDirectPlay,
bool forceDirectPlayRemoteMediaSource,
bool enableDirectStream,
- bool enableTranscoding)
+ bool enableTranscoding,
+ bool allowVideoStreamCopy,
+ bool allowAudioStreamCopy)
{
var item = _libraryManager.GetItemById(itemId);
foreach (var mediaSource in result.MediaSources)
{
- SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, maxAudioChannels, result.PlaySessionId, userId, enableDirectPlay, forceDirectPlayRemoteMediaSource, enableDirectStream, enableTranscoding);
+ SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, maxAudioChannels, result.PlaySessionId, userId, enableDirectPlay, forceDirectPlayRemoteMediaSource, enableDirectStream, enableTranscoding, allowVideoStreamCopy, allowAudioStreamCopy);
}
SortMediaSources(result, maxBitrate);
@@ -282,7 +284,9 @@ namespace MediaBrowser.Api.Playback
bool enableDirectPlay,
bool forceDirectPlayRemoteMediaSource,
bool enableDirectStream,
- bool enableTranscoding)
+ bool enableTranscoding,
+ bool allowVideoStreamCopy,
+ bool allowAudioStreamCopy)
{
var streamBuilder = new StreamBuilder(_mediaEncoder, Logger);
@@ -418,6 +422,15 @@ namespace MediaBrowser.Api.Playback
{
streamInfo.StartPositionTicks = startTimeTicks;
mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
+
+ if (!allowVideoStreamCopy)
+ {
+ mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
+ }
+ if (!allowAudioStreamCopy)
+ {
+ mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
+ }
mediaSource.TranscodingContainer = streamInfo.Container;
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
}
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index 551dbf378..ecb6350cd 100644
--- a/MediaBrowser.Api/Playback/StreamRequest.cs
+++ b/MediaBrowser.Api/Playback/StreamRequest.cs
@@ -43,6 +43,7 @@ namespace MediaBrowser.Api.Playback
public int? SegmentLength { get; set; }
public int? MinSegments { get; set; }
+ public bool BreakOnNonKeyFrames { get; set; }
}
public class VideoStreamRequest : StreamRequest
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index dd31d39b1..996009524 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -188,6 +188,14 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return null;
}
+ if (string.Equals(container, "ogm", StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+ if (string.Equals(container, "divx", StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
// Seeing reported failures here, not sure yet if this is related to specfying input format
if (string.Equals(container, "m4v", StringComparison.OrdinalIgnoreCase))
@@ -750,6 +758,11 @@ namespace MediaBrowser.Controller.MediaEncoding
var request = state.BaseRequest;
+ if (!request.AllowVideoStreamCopy)
+ {
+ return false;
+ }
+
if (videoStream.IsInterlaced)
{
if (request.DeInterlace)
@@ -895,6 +908,11 @@ namespace MediaBrowser.Controller.MediaEncoding
var request = state.BaseRequest;
+ if (!request.AllowAudioStreamCopy)
+ {
+ return false;
+ }
+
// Source and target codecs must match
if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
index 73be78dc9..f044db3d0 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
@@ -72,6 +72,9 @@ namespace MediaBrowser.Controller.MediaEncoding
[ApiMember(Name = "EnableAutoStreamCopy", Description = "Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool EnableAutoStreamCopy { get; set; }
+ public bool AllowVideoStreamCopy { get; set; }
+ public bool AllowAudioStreamCopy { get; set; }
+
///
/// Gets or sets the audio sample rate.
///
@@ -218,6 +221,8 @@ namespace MediaBrowser.Controller.MediaEncoding
public BaseEncodingJobOptions()
{
EnableAutoStreamCopy = true;
+ AllowVideoStreamCopy = true;
+ AllowAudioStreamCopy = true;
Context = EncodingContext.Streaming;
}
}
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 36df67b34..120238967 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -484,6 +484,8 @@ namespace MediaBrowser.Model.Dlna
playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps;
playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest;
+ playlistItem.BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames;
+
if (transcodingProfile.MinSegments > 0)
{
playlistItem.MinSegments = transcodingProfile.MinSegments;
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 5705e6477..2c009b37f 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -40,6 +40,7 @@ namespace MediaBrowser.Model.Dlna
public int? SegmentLength { get; set; }
public int? MinSegments { get; set; }
+ public bool BreakOnNonKeyFrames { get; set; }
public bool RequireAvc { get; set; }
public bool DeInterlace { get; set; }
@@ -305,6 +306,8 @@ namespace MediaBrowser.Model.Dlna
{
list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture)));
}
+
+ list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString()));
}
return list;
diff --git a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs
index 425fb9c93..badd3c5b1 100644
--- a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.MediaInfo;
+using System;
+using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Session;
using System.Collections.Generic;
using System.Linq;
@@ -47,16 +48,11 @@ namespace MediaBrowser.Model.Dlna
{
if (i.MediaSource.Bitrate.HasValue)
{
- if (i.MediaSource.Bitrate.Value <= maxBitrate.Value)
- {
- return 0;
- }
-
- return 2;
+ return Math.Abs(i.MediaSource.Bitrate.Value - maxBitrate.Value);
}
}
- return 1;
+ return 0;
}).ToList();
}
diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs
index 350556e90..9623a68b0 100644
--- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs
+++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs
@@ -48,6 +48,9 @@ namespace MediaBrowser.Model.Dlna
[XmlAttribute("segmentLength")]
public int SegmentLength { get; set; }
+ [XmlAttribute("breakOnNonKeyFrames")]
+ public bool BreakOnNonKeyFrames { get; set; }
+
public List GetAudioCodecs()
{
List list = new List();
diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs
index 16c9464ac..0518064c9 100644
--- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs
+++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs
@@ -28,6 +28,8 @@ namespace MediaBrowser.Model.MediaInfo
public bool EnableDirectStream { get; set; }
public bool EnableTranscoding { get; set; }
public bool ForceDirectPlayRemoteMediaSource { get; set; }
+ public bool AllowVideoStreamCopy { get; set; }
+ public bool AllowAudioStreamCopy { get; set; }
public PlaybackInfoRequest()
{
@@ -35,6 +37,8 @@ namespace MediaBrowser.Model.MediaInfo
EnableDirectPlay = true;
EnableDirectStream = true;
EnableTranscoding = true;
+ AllowVideoStreamCopy = true;
+ AllowAudioStreamCopy = true;
}
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
index ab2cd3bed..1c6157c03 100644
--- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
@@ -160,12 +160,7 @@ namespace MediaBrowser.Providers.Movies
var results = searchResults.results ?? new List();
- var index = 0;
- var resultTuples = results.Select(result => new Tuple(result, index++)).ToList();
-
- return resultTuples.OrderBy(i => GetSearchResultOrder(i.Item1, year))
- .ThenBy(i => i.Item2)
- .Select(i => i.Item1)
+ return results
.Select(i =>
{
var remoteResult = new RemoteSearchResult
@@ -217,12 +212,7 @@ namespace MediaBrowser.Providers.Movies
var results = searchResults.results ?? new List();
- var index = 0;
- var resultTuples = results.Select(result => new Tuple(result, index++)).ToList();
-
- return resultTuples.OrderBy(i => GetSearchResultOrder(i.Item1, year))
- .ThenBy(i => i.Item2)
- .Select(i => i.Item1)
+ return results
.Select(i =>
{
var remoteResult = new RemoteSearchResult
@@ -253,40 +243,6 @@ namespace MediaBrowser.Providers.Movies
}
}
- private int GetSearchResultOrder(TmdbMovieSearchResult result, int? year)
- {
- if (year.HasValue)
- {
- DateTime r;
-
- // These dates are always in this exact format
- if (DateTime.TryParseExact(result.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
- {
- // Allow one year tolernace, preserve order from Tmdb
- return Math.Abs(r.Year - year.Value);
- }
- }
-
- return int.MaxValue;
- }
-
- private int GetSearchResultOrder(TvResult result, int? year)
- {
- if (year.HasValue)
- {
- DateTime r;
-
- // These dates are always in this exact format
- if (DateTime.TryParseExact(result.first_air_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
- {
- // Allow one year tolernace, preserve order from Tmdb
- return Math.Abs(r.Year - year.Value);
- }
- }
-
- return int.MaxValue;
- }
-
///
/// Class TmdbMovieSearchResult
///
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 0112684be..9de987955 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.2.10.1")]
+[assembly: AssemblyVersion("3.2.10.2")]