Merge pull request #2381 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-01-05 23:36:59 -05:00 committed by GitHub
commit 0a202a58f8
34 changed files with 239 additions and 180 deletions

View file

@ -176,6 +176,18 @@ namespace Emby.Dlna.Didl
return new NullLogger();
}
private string GetMimeType(string input)
{
var mime = MimeTypes.GetMimeType(input);
if (string.Equals(mime, "video/mp2t", StringComparison.OrdinalIgnoreCase))
{
mime = "video/mpeg";
}
return mime;
}
private void AddVideoResource(DlnaOptions options, XmlWriter writer, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null)
{
if (streamInfo == null)
@ -360,7 +372,7 @@ namespace Emby.Dlna.Didl
var filename = url.Substring(0, url.IndexOf('?'));
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
? MimeTypes.GetMimeType(filename)
? GetMimeType(filename)
: mediaProfile.MimeType;
writer.WriteAttributeString("protocolInfo", String.Format(
@ -481,7 +493,7 @@ namespace Emby.Dlna.Didl
var filename = url.Substring(0, url.IndexOf('?'));
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
? MimeTypes.GetMimeType(filename)
? GetMimeType(filename)
: mediaProfile.MimeType;
var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container,
@ -760,7 +772,7 @@ namespace Emby.Dlna.Didl
// Seeing some LG models locking up due content with large lists of people
// The actual issue might just be due to processing a more metadata than it can handle
var limit = 10;
var limit = 6;
foreach (var actor in people)
{
@ -1007,7 +1019,7 @@ namespace Emby.Dlna.Didl
writer.WriteAttributeString("protocolInfo", String.Format(
"http-get:*:{0}:{1}",
MimeTypes.GetMimeType("file." + format),
GetMimeType("file." + format),
contentFeatures
));

View file

@ -23,7 +23,7 @@ namespace Emby.Dlna.Profiles
{
Match = HeaderMatchType.Substring,
Name = "User-Agent",
Value ="XiP"
Value ="Zip_"
}
}
};
@ -63,22 +63,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile
{
Container = "mp3",
AudioCodec = "mp3",
Type = DlnaProfileType.Audio
},
new DirectPlayProfile
{
Container = "alac",
AudioCodec = "alac",
Type = DlnaProfileType.Audio
},
new DirectPlayProfile
{
Container = "flac",
AudioCodec = "flac",
Container = "mp3,alac,flac",
Type = DlnaProfileType.Audio
},

View file

@ -86,7 +86,9 @@ namespace Emby.Dlna.Profiles
{
Container = "mp3",
AudioCodec = "mp3",
Type = DlnaProfileType.Audio
Type = DlnaProfileType.Audio,
// Transcoded audio won't be playable at all without this
TranscodeSeekInfo = TranscodeSeekInfo.Bytes
},
new TranscodingProfile
{

View file

@ -5,7 +5,7 @@
<Manufacturer>Echostar Technologies LLC</Manufacturer>
<ManufacturerUrl>http://www.echostar.com</ManufacturerUrl>
<Headers>
<HttpHeaderInfo name="User-Agent" value="XiP" match="Substring" />
<HttpHeaderInfo name="User-Agent" value="Zip_" match="Substring" />
</Headers>
</Identification>
<Manufacturer>Emby</Manufacturer>
@ -37,9 +37,7 @@
<XmlRootAttributes />
<DirectPlayProfiles>
<DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
<DirectPlayProfile container="alac" audioCodec="alac" type="Audio" />
<DirectPlayProfile container="flac" audioCodec="flac" type="Audio" />
<DirectPlayProfile container="mp3,alac,flac" type="Audio" />
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>

View file

@ -45,7 +45,7 @@
<DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Bytes" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
</TranscodingProfiles>

View file

@ -106,6 +106,11 @@ namespace Emby.Server.Core.EntryPoints
private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e)
{
if (_disposed)
{
return;
}
var info = e.Argument;
string usn;
@ -169,6 +174,11 @@ namespace Emby.Server.Core.EntryPoints
return;
}
if (_disposed)
{
return;
}
_logger.Debug("Calling Nat.Handle on " + identifier);
NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp);
}
@ -185,6 +195,11 @@ namespace Emby.Server.Core.EntryPoints
void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
{
if (_disposed)
{
return;
}
try
{
var device = e.Device;
@ -210,6 +225,11 @@ namespace Emby.Server.Core.EntryPoints
private List<string> _usnsHandled = new List<string>();
private void CreateRules(INatDevice device)
{
if (_disposed)
{
throw new ObjectDisposedException("PortMapper");
}
// On some systems the device discovered event seems to fire repeatedly
// This check will help ensure we're not trying to port map the same device over and over
@ -249,8 +269,10 @@ namespace Emby.Server.Core.EntryPoints
_logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString());
}
private bool _disposed = false;
public void Dispose()
{
_disposed = true;
DisposeNat();
}

View file

@ -288,6 +288,13 @@ namespace Emby.Server.Core.IO
{
try
{
if (!_fileSystem.DirectoryExists(path))
{
// Seeing a crash in the mono runtime due to an exception being thrown on a different thread
Logger.Info("Skipping realtime monitor for {0} because the path does not exist", path);
return;
}
var newWatcher = new FileSystemWatcher(path, "*")
{
IncludeSubdirectories = true

View file

@ -9,6 +9,7 @@ using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Threading;
@ -26,8 +27,9 @@ namespace Emby.Server.Implementations.Connect
private readonly IApplicationHost _appHost;
private readonly IFileSystem _fileSystem;
private readonly ITimerFactory _timerFactory;
private readonly IEncryptionManager _encryption;
public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory)
public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory, IEncryptionManager encryption)
{
_httpClient = httpClient;
_appPaths = appPaths;
@ -37,6 +39,7 @@ namespace Emby.Server.Implementations.Connect
_appHost = appHost;
_fileSystem = fileSystem;
_timerFactory = timerFactory;
_encryption = encryption;
}
public void Run()
@ -143,7 +146,7 @@ namespace Emby.Server.Implementations.Connect
private string CacheFilePath
{
get { return Path.Combine(_appPaths.DataPath, "wan.txt"); }
get { return Path.Combine(_appPaths.DataPath, "wan.dat"); }
}
private void CacheAddress(IpAddressInfo address)
@ -153,7 +156,14 @@ namespace Emby.Server.Implementations.Connect
try
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
_fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8);
}
catch (Exception ex)
{
}
try
{
_fileSystem.WriteAllText(path, _encryption.EncryptString(address.ToString()), Encoding.UTF8);
}
catch (Exception ex)
{
@ -169,7 +179,7 @@ namespace Emby.Server.Implementations.Connect
try
{
var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8);
var endpoint = _encryption.DecryptString(_fileSystem.ReadAllText(path, Encoding.UTF8));
IpAddressInfo ipAddress;
if (_networkManager.TryParseIpAddress(endpoint, out ipAddress))

View file

@ -2548,57 +2548,53 @@ namespace Emby.Server.Implementations.Data
{
using (var connection = CreateConnection(true))
{
return connection.RunInTransaction(db =>
var list = new List<BaseItem>();
using (var statement = PrepareStatementSafe(connection, commandText))
{
var list = new List<BaseItem>();
using (var statement = PrepareStatementSafe(db, commandText))
if (EnableJoinUserData(query))
{
if (EnableJoinUserData(query))
statement.TryBind("@UserId", query.User.Id);
}
BindSimilarParams(query, statement);
// Running this again will bind the params
GetWhereClauses(query, statement);
foreach (var row in statement.ExecuteQuery())
{
var item = GetItem(row, query);
if (item != null)
{
statement.TryBind("@UserId", query.User.Id);
list.Add(item);
}
}
}
BindSimilarParams(query, statement);
// Hack for right now since we currently don't support filtering out these duplicates within a query
if (query.EnableGroupByMetadataKey)
{
var limit = query.Limit ?? int.MaxValue;
limit -= 4;
var newList = new List<BaseItem>();
// Running this again will bind the params
GetWhereClauses(query, statement);
foreach (var item in list)
{
AddItem(newList, item);
foreach (var row in statement.ExecuteQuery())
if (newList.Count >= limit)
{
var item = GetItem(row, query);
if (item != null)
{
list.Add(item);
}
break;
}
}
// Hack for right now since we currently don't support filtering out these duplicates within a query
if (query.EnableGroupByMetadataKey)
{
var limit = query.Limit ?? int.MaxValue;
limit -= 4;
var newList = new List<BaseItem>();
list = newList;
}
foreach (var item in list)
{
AddItem(newList, item);
LogQueryTime("GetItemList", commandText, now);
if (newList.Count >= limit)
{
break;
}
}
list = newList;
}
LogQueryTime("GetItemList", commandText, now);
return list;
}, ReadTransactionMode);
return list;
}
}
}

View file

@ -182,7 +182,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
programsInfo.Add(GetProgram(channelNumber, schedule, programDict[schedule.programID]));
}
_logger.Info("Finished with EPGData");
}
}
@ -322,8 +321,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
{
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
_logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
_logger.Info("Mapping Stations to Channel");
foreach (ScheduleDirect.Map map in root.map)
{
var channelNumber = map.logicalChannelNumber;
@ -353,7 +351,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
});
}
}
_logger.Info("Added " + GetChannelPairCacheCount(listingsId) + " channels to the dictionary");
foreach (ChannelInfo channel in channels)
{

View file

@ -103,7 +103,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
TunerHostId = info.Id,
IsHD = i.HD == 1,
AudioCodec = i.AudioCodec,
VideoCodec = i.VideoCodec
VideoCodec = i.VideoCodec,
ChannelType = ChannelType.TV
});
}

View file

@ -4,7 +4,7 @@ namespace Emby.Server.Implementations.Sync
{
public class SyncHelper
{
public static int? AdjustBitrate(int? profileBitrate, string quality)
public static long? AdjustBitrate(long? profileBitrate, string quality)
{
if (profileBitrate.HasValue)
{

View file

@ -59,15 +59,8 @@ namespace Emby.Server.Implementations.Sync
_mediaSourceManager = mediaSourceManager;
}
public async Task EnsureJobItems(SyncJob job)
public async Task EnsureJobItems(SyncJob job, User user)
{
var user = _userManager.GetUserById(job.UserId);
if (user == null)
{
throw new InvalidOperationException("Cannot proceed with sync because user no longer exists.");
}
var items = (await GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
.ToList();
@ -385,7 +378,16 @@ namespace Emby.Server.Implementations.Sync
if (job.SyncNewContent)
{
await EnsureJobItems(job).ConfigureAwait(false);
var user = _userManager.GetUserById(job.UserId);
if (user == null)
{
await _syncManager.CancelJob(job.Id).ConfigureAwait(false);
}
else
{
await EnsureJobItems(job, user).ConfigureAwait(false);
}
}
}
}

View file

@ -181,7 +181,7 @@ namespace Emby.Server.Implementations.Sync
await _repo.Create(job).ConfigureAwait(false);
await processor.EnsureJobItems(job).ConfigureAwait(false);
await processor.EnsureJobItems(job, user).ConfigureAwait(false);
// If it already has a converting status then is must have been aborted during conversion
var jobItemsResult = GetJobItems(new SyncJobItemQuery

View file

@ -205,7 +205,8 @@ namespace MediaBrowser.Api.Playback
}
else
{
args += "-map -0:v";
// No known video stream
args += "-vn";
}
if (state.AudioStream != null)
@ -395,8 +396,6 @@ namespace MediaBrowser.Api.Playback
{
param += " -crf 23";
}
param += " -tune zerolatency";
}
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
@ -536,6 +535,11 @@ namespace MediaBrowser.Api.Playback
}
}
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
{
param += " -x264opts:0 subme=0:rc_lookahead=10:me_range=4:me=dia:no_chroma_me:8x8dct=0:partitions=none";
}
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
@ -1492,8 +1496,16 @@ namespace MediaBrowser.Api.Playback
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
{
// h264
return string.Format(" -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture));
}
// h264
return string.Format(" -maxrate {0} -bufsize {1}",
return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture));
}

View file

@ -103,7 +103,7 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
var waitForSegments = state.SegmentLength >= 10 ? 2 : (state.SegmentLength > 3 || !isLive ? 3 : 3);
var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
}
}

View file

@ -265,9 +265,15 @@ namespace MediaBrowser.Api.Playback.Hls
double startSeconds = 0;
var lengths = GetSegmentLengths(state);
if (requestedIndex >= lengths.Length)
{
var msg = string.Format("Invalid segment index requested: {0} - Segment count: {1}", requestedIndex, lengths.Length);
throw new ArgumentException(msg);
}
for (var i = 0; i < requestedIndex; i++)
{
startSeconds += lengths[requestedIndex];
startSeconds += lengths[i];
}
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
@ -279,9 +285,15 @@ namespace MediaBrowser.Api.Playback.Hls
double startSeconds = 0;
var lengths = GetSegmentLengths(state);
if (requestedIndex >= lengths.Length)
{
var msg = string.Format("Invalid segment index requested: {0} - Segment count: {1}", requestedIndex, lengths.Length);
throw new ArgumentException(msg);
}
for (var i = 0; i <= requestedIndex; i++)
{
startSeconds += lengths[requestedIndex];
startSeconds += lengths[i];
}
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
@ -348,6 +360,8 @@ namespace MediaBrowser.Api.Playback.Hls
return;
}
Logger.Debug("Deleting partial HLS file {0}", file.FullName);
try
{
FileSystem.DeleteFile(file.FullName);
@ -723,7 +737,7 @@ namespace MediaBrowser.Api.Playback.Hls
foreach (var length in segmentLengths)
{
builder.AppendLine("#EXTINF:" + length.ToString("0.0000", UsCulture) + ",");
builder.AppendLine("#EXTINF:" + length.ToString("0.0000", UsCulture) + ", nodesc");
builder.AppendLine(string.Format("hls1/{0}/{1}{2}{3}",
@ -826,7 +840,7 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -bsf:v h264_mp4toannexb";
}
args += " -flags -global_header";
//args += " -flags -global_header";
}
else
{
@ -851,7 +865,7 @@ namespace MediaBrowser.Api.Playback.Hls
args += GetGraphicalSubtitleParam(state, codec);
}
args += " -flags -global_header";
//args += " -flags -global_header";
}
if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
@ -875,27 +889,25 @@ namespace MediaBrowser.Api.Playback.Hls
var inputModifier = GetInputModifier(state, false);
// If isEncoding is true we're actually starting ffmpeg
var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
var toTimeParam = string.Empty;
var timestampOffsetParam = string.Empty;
if (state.IsOutputVideo && !EnableCopyTs(state) && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
{
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0);
}
var startNumber = GetStartNumber(state);
var startNumberParam = isEncoding ? startNumber.ToString(UsCulture) : "0";
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
var enableSplittingOnNonKeyFrames = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && false;
var useGenericSegmenter = true;
// TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time
var hlsProtocolSupportsSplittingByTime = false;
if (enableSplittingOnNonKeyFrames && !hlsProtocolSupportsSplittingByTime)
if (useGenericSegmenter)
{
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
return string.Format("{0} {10} {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} -break_non_keyframes 1 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
var timeDeltaParam = String.Empty;
if (isEncoding && startNumber > 0)
{
var startTime = state.SegmentLength * startNumber;
timeDeltaParam = string.Format("-segment_time_delta -{0}", startTime);
}
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 mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
inputModifier,
GetInputArgument(state),
threads,
@ -906,27 +918,21 @@ namespace MediaBrowser.Api.Playback.Hls
startNumberParam,
outputPath,
outputTsArg,
toTimeParam
).Trim();
timeDeltaParam
).Trim();
}
var splitByTime = hlsProtocolSupportsSplittingByTime && enableSplittingOnNonKeyFrames;
var splitByTimeArg = splitByTime ? " -hls_flags split_by_time" : "";
return string.Format("{0}{12} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"",
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {6} -individual_header_trailer 0 -start_number {7} -hls_list_size {8} -y \"{9}\"",
inputModifier,
GetInputArgument(state),
threads,
mapArgs,
GetVideoArguments(state),
timestampOffsetParam,
GetAudioArguments(state),
state.SegmentLength.ToString(UsCulture),
splitByTimeArg,
startNumberParam,
state.HlsListSize.ToString(UsCulture),
outputPath,
toTimeParam
outputPath
).Trim();
}

View file

@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Playback
PlaybackInfoResponse result,
DeviceProfile profile,
AuthorizationInfo auth,
int? maxBitrate,
long? maxBitrate,
long startTimeTicks,
string mediaSourceId,
int? audioStreamIndex,
@ -249,7 +249,7 @@ namespace MediaBrowser.Api.Playback
MediaSourceInfo mediaSource,
DeviceProfile profile,
AuthorizationInfo auth,
int? maxBitrate,
long? maxBitrate,
long startTimeTicks,
string mediaSourceId,
int? audioStreamIndex,
@ -383,7 +383,7 @@ namespace MediaBrowser.Api.Playback
}
}
private int? GetMaxBitrate(int? clientMaxBitrate)
private long? GetMaxBitrate(long? clientMaxBitrate)
{
var maxBitrate = clientMaxBitrate;
var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit;
@ -425,7 +425,7 @@ namespace MediaBrowser.Api.Playback
}
}
private void SortMediaSources(PlaybackInfoResponse result, int? maxBitrate)
private void SortMediaSources(PlaybackInfoResponse result, long? maxBitrate)
{
var originalList = result.MediaSources.ToList();

View file

@ -93,13 +93,9 @@ namespace MediaBrowser.Api.Playback
{
return 3;
}
return 6;
}
if (!RunTimeTicks.HasValue)
{
return 3;
}
return 3;
}
}

View file

@ -243,6 +243,8 @@ namespace MediaBrowser.Api.Session
[ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsPersistentIdentifier { get; set; }
public bool SupportsContentUploading { get; set; }
public PostCapabilities()
{
SupportsPersistentIdentifier = true;
@ -559,6 +561,8 @@ namespace MediaBrowser.Api.Session
SupportsSync = request.SupportsSync,
SupportsContentUploading = request.SupportsContentUploading,
SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
});
}

View file

@ -827,8 +827,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
{
// h264
return string.Format(" -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture));
}
// h264
return string.Format(" -maxrate {0} -bufsize {1}",
return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture));
}
@ -896,7 +904,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
else
{
args += "-map -0:v";
// No known video stream
args += "-vn";
}
if (state.AudioStream != null)

View file

@ -41,7 +41,7 @@ namespace MediaBrowser.Model.Dlna
/// <summary>
/// The application's configured quality setting
/// </summary>
public int? MaxBitrate { get; set; }
public long? MaxBitrate { get; set; }
/// <summary>
/// Gets or sets the context.
@ -59,7 +59,7 @@ namespace MediaBrowser.Model.Dlna
/// Gets the maximum bitrate.
/// </summary>
/// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
public int? GetMaxBitrate(bool isAudio)
public long? GetMaxBitrate(bool isAudio)
{
if (MaxBitrate.HasValue)
{

View file

@ -51,8 +51,8 @@ namespace MediaBrowser.Model.Dlna
public int? MaxIconWidth { get; set; }
public int? MaxIconHeight { get; set; }
public int? MaxStreamingBitrate { get; set; }
public int? MaxStaticBitrate { get; set; }
public long? MaxStreamingBitrate { get; set; }
public long? MaxStaticBitrate { get; set; }
public int? MusicStreamingTranscodingBitrate { get; set; }
public int? MaxStaticMusicBitrate { get; set; }

View file

@ -93,7 +93,7 @@ namespace MediaBrowser.Model.Dlna
return GetOptimalStream(streams, options.GetMaxBitrate(false));
}
private StreamInfo GetOptimalStream(List<StreamInfo> streams, int? maxBitrate)
private StreamInfo GetOptimalStream(List<StreamInfo> streams, long? maxBitrate)
{
streams = StreamInfoSorter.SortMediaSources(streams, maxBitrate);
@ -277,25 +277,26 @@ namespace MediaBrowser.Model.Dlna
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
}
int transcodingBitrate = options.AudioTranscodingBitrate ??
long transcodingBitrate = options.AudioTranscodingBitrate ??
options.Profile.MusicStreamingTranscodingBitrate ??
128000;
int? configuredBitrate = options.GetMaxBitrate(true);
var configuredBitrate = options.GetMaxBitrate(true);
if (configuredBitrate.HasValue)
{
transcodingBitrate = Math.Min(configuredBitrate.Value, transcodingBitrate);
}
playlistItem.AudioBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate);
var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate);
playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
}
return playlistItem;
}
private int? GetBitrateForDirectPlayCheck(MediaSourceInfo item, AudioOptions options, bool isAudio)
private long? GetBitrateForDirectPlayCheck(MediaSourceInfo item, AudioOptions options, bool isAudio)
{
if (item.Protocol == MediaProtocol.File)
{
@ -583,11 +584,11 @@ namespace MediaBrowser.Model.Dlna
int audioBitrate = GetAudioBitrate(playlistItem.SubProtocol, options.GetMaxBitrate(false), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream);
playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate);
int? maxBitrateSetting = options.GetMaxBitrate(false);
var maxBitrateSetting = options.GetMaxBitrate(false);
// Honor max rate
if (maxBitrateSetting.HasValue)
{
int videoBitrate = maxBitrateSetting.Value;
var videoBitrate = maxBitrateSetting.Value;
if (playlistItem.AudioBitrate.HasValue)
{
@ -595,15 +596,16 @@ namespace MediaBrowser.Model.Dlna
}
// Make sure the video bitrate is lower than bitrate settings but at least 64k
int currentValue = playlistItem.VideoBitrate ?? videoBitrate;
playlistItem.VideoBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000);
long currentValue = playlistItem.VideoBitrate ?? videoBitrate;
var longBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000);
playlistItem.VideoBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
}
}
return playlistItem;
}
private int GetAudioBitrate(string subProtocol, int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream)
private int GetAudioBitrate(string subProtocol, long? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream)
{
int defaultBitrate = audioStream == null ? 192000 : audioStream.BitRate ?? 192000;
// Reduce the bitrate if we're downmixing
@ -865,7 +867,7 @@ namespace MediaBrowser.Model.Dlna
}
private bool IsEligibleForDirectPlay(MediaSourceInfo item,
int? maxBitrate,
long? maxBitrate,
MediaStream subtitleStream,
VideoOptions options,
PlayMethod playMethod)
@ -960,7 +962,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate)
private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, long? maxBitrate)
{
if (!maxBitrate.HasValue)
{

View file

@ -7,7 +7,7 @@ namespace MediaBrowser.Model.Dlna
{
public class StreamInfoSorter
{
public static List<StreamInfo> SortMediaSources(List<StreamInfo> streams, int? maxBitrate)
public static List<StreamInfo> SortMediaSources(List<StreamInfo> streams, long? maxBitrate)
{
return streams.OrderBy(i =>
{

View file

@ -7,7 +7,7 @@ namespace MediaBrowser.Model.MediaInfo
public string OpenToken { get; set; }
public string UserId { get; set; }
public string PlaySessionId { get; set; }
public int? MaxStreamingBitrate { get; set; }
public long? MaxStreamingBitrate { get; set; }
public long? StartTimeTicks { get; set; }
public int? AudioStreamIndex { get; set; }
public int? SubtitleStreamIndex { get; set; }

View file

@ -8,7 +8,7 @@ namespace MediaBrowser.Model.MediaInfo
public string UserId { get; set; }
public int? MaxStreamingBitrate { get; set; }
public long? MaxStreamingBitrate { get; set; }
public long? StartTimeTicks { get; set; }

View file

@ -10,7 +10,7 @@ namespace MediaBrowser.Model.Session
public List<string> SupportedCommands { get; set; }
public bool SupportsMediaControl { get; set; }
public bool SupportsContentUploading { get; set; }
public string MessageCallbackUrl { get; set; }
public bool SupportsPersistentIdentifier { get; set; }

View file

@ -36,6 +36,7 @@
DisplayMessage = 28,
SetRepeatMode = 29,
ChannelUp = 30,
ChannelDown = 31
ChannelDown = 31,
SetMaxStreamingBitrate = 31
}
}

View file

@ -93,6 +93,12 @@ namespace MediaBrowser.Providers.TV
return;
}
// Check this in order to avoid logging an exception due to directory not existing
if (!_fileSystem.DirectoryExists(seriesDataPath))
{
return;
}
var episodeFiles = _fileSystem.GetFilePaths(seriesDataPath)
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
.Select(Path.GetFileNameWithoutExtension)

View file

@ -143,7 +143,8 @@ namespace MediaBrowser.Providers.TV
Url = ServerTimeUrl,
CancellationToken = cancellationToken,
EnableHttpCompression = true,
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool,
BufferContent = false
}).ConfigureAwait(false))
{
@ -239,7 +240,8 @@ namespace MediaBrowser.Providers.TV
Url = string.Format(UpdatesUrl, lastUpdateTime),
CancellationToken = cancellationToken,
EnableHttpCompression = true,
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool,
BufferContent = false
}).ConfigureAwait(false))
{

View file

@ -237,7 +237,8 @@ namespace MediaBrowser.Providers.TV
{
Url = url,
ResourcePool = TvDbResourcePool,
CancellationToken = cancellationToken
CancellationToken = cancellationToken,
BufferContent = false
}).ConfigureAwait(false))
{
@ -281,7 +282,8 @@ namespace MediaBrowser.Providers.TV
{
Url = url,
ResourcePool = TvDbResourcePool,
CancellationToken = cancellationToken
CancellationToken = cancellationToken,
BufferContent = false
}).ConfigureAwait(false))
{
@ -535,7 +537,8 @@ namespace MediaBrowser.Providers.TV
{
Url = url,
ResourcePool = TvDbResourcePool,
CancellationToken = cancellationToken
CancellationToken = cancellationToken,
BufferContent = false
}).ConfigureAwait(false))
{
@ -1664,7 +1667,8 @@ namespace MediaBrowser.Providers.TV
{
CancellationToken = cancellationToken,
Url = url,
ResourcePool = TvDbResourcePool
ResourcePool = TvDbResourcePool,
BufferContent = false
});
}
}

View file

@ -162,9 +162,6 @@
<Content Include="dashboard-ui\components\remotecontrol.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\components\remotecontrolautoplay.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\components\tvproviders\xmltv.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -258,6 +255,9 @@
<Content Include="dashboard-ui\css\images\empty.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\videoosd.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\touchicon144.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -420,9 +420,6 @@
<Content Include="dashboard-ui\devices\ios\ios.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\htmlmediarenderer.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\sections.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -648,9 +645,6 @@
<Content Include="dashboard-ui\css\livetv.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\mediaplayer-video.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\nowplaying.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -816,9 +810,6 @@
<Content Include="dashboard-ui\scripts\channelslatest.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\chromecast.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\dashboard\cinemamodeconfiguration.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -903,9 +894,6 @@
<Content Include="dashboard-ui\scripts\mediacontroller.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\mediaplayer-video.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\metadatasubtitles.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -978,6 +966,9 @@
<Content Include="dashboard-ui\userpassword.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\videoosd.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\wizardagreement.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -1027,9 +1018,6 @@
<Content Include="dashboard-ui\scripts\notifications.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\remotecontrol.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\moviecollections.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -1388,9 +1376,6 @@
<Content Include="dashboard-ui\css\images\clients\dlna.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\mediaplayer.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\strings\ar.json">

View file

@ -245,7 +245,7 @@ namespace Rssdp.Infrastructure
return;
}
WriteTrace(String.Format("Search Request Received From {0}, Target = {1}", remoteEndPoint.ToString(), searchTarget));
//WriteTrace(String.Format("Search Request Received From {0}, Target = {1}", remoteEndPoint.ToString(), searchTarget));
if (IsDuplicateSearchRequest(searchTarget, remoteEndPoint))
{