Merge pull request #3022 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-11-17 16:55:36 -05:00 committed by GitHub
commit fd5059147d
12 changed files with 88 additions and 77 deletions

View File

@ -1052,10 +1052,27 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{ {
_liveStreamsSemaphore.Release(); _liveStreamsSemaphore.Release();
} }
} }
private async Task<Tuple<ILiveStream, MediaSourceInfo, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) public async Task<List<ILiveStream>> GetLiveStreams(TunerHostInfo host, CancellationToken cancellationToken)
{
//await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
//try
//{
var hostId = host.Id;
return _liveStreams
.Where(i => string.Equals(i.TunerHostId, hostId, StringComparison.OrdinalIgnoreCase))
.ToList();
//}
//finally
//{
// _liveStreamsSemaphore.Release();
//}
}
private async Task<Tuple<ILiveStream, MediaSourceInfo>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken)
{ {
_logger.Info("Streaming Channel " + channelId); _logger.Info("Streaming Channel " + channelId);
@ -1072,7 +1089,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount); _logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount);
return new Tuple<ILiveStream, MediaSourceInfo, ITunerHost>(result, openedMediaSource, result.TunerHost); return new Tuple<ILiveStream, MediaSourceInfo>(result, openedMediaSource);
} }
foreach (var hostInstance in _liveTvManager.TunerHosts) foreach (var hostInstance in _liveTvManager.TunerHosts)
@ -1086,13 +1103,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
result.SharedStreamIds.Add(openedMediaSource.Id); result.SharedStreamIds.Add(openedMediaSource.Id);
_liveStreams.Add(result); _liveStreams.Add(result);
result.TunerHost = hostInstance;
result.OriginalStreamId = streamId; result.OriginalStreamId = streamId;
_logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}", _logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}",
streamId, openedMediaSource.Id, openedMediaSource.LiveStreamId); streamId, openedMediaSource.Id, openedMediaSource.LiveStreamId);
return new Tuple<ILiveStream, MediaSourceInfo, ITunerHost>(result, openedMediaSource, hostInstance); return new Tuple<ILiveStream, MediaSourceInfo>(result, openedMediaSource);
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {

View File

@ -598,7 +598,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner) if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner)
{ {
return new HdHomerunUdpStream(mediaSource, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Path), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); return new HdHomerunUdpStream(mediaSource, info, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Path), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment);
} }
// The UDP method is not working reliably on OSX, and on BSD it hasn't been tested yet // The UDP method is not working reliably on OSX, and on BSD it hasn't been tested yet
@ -618,10 +618,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
} }
mediaSource.Path = httpUrl; mediaSource.Path = httpUrl;
return new SharedHttpStream(mediaSource, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment);
} }
return new HdHomerunUdpStream(mediaSource, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number, profile), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); return new HdHomerunUdpStream(mediaSource, info, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number, profile), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment);
} }
public async Task Validate(TunerHostInfo info) public async Task Validate(TunerHostInfo info)

View File

@ -11,6 +11,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using MediaBrowser.Model.LiveTv;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{ {
@ -23,8 +24,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly int _numTuners; private readonly int _numTuners;
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment) public HdHomerunUdpStream(MediaSourceInfo mediaSource, TunerHostInfo tunerHostInfo, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment)
: base(mediaSource, environment, fileSystem, logger, appPaths) : base(mediaSource, tunerHostInfo, environment, fileSystem, logger, appPaths)
{ {
_appHost = appHost; _appHost = appHost;
_socketFactory = socketFactory; _socketFactory = socketFactory;

View File

@ -10,6 +10,7 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using MediaBrowser.Model.LiveTv;
namespace Emby.Server.Implementations.LiveTv.TunerHosts namespace Emby.Server.Implementations.LiveTv.TunerHosts
{ {
@ -21,7 +22,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{ {
get { return SharedStreamIds.Count; } get { return SharedStreamIds.Count; }
} }
public ITunerHost TunerHost { get; set; }
public string OriginalStreamId { get; set; } public string OriginalStreamId { get; set; }
public bool EnableStreamSharing { get; set; } public bool EnableStreamSharing { get; set; }
public string UniqueId { get; private set; } public string UniqueId { get; private set; }
@ -35,7 +36,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
protected readonly ILogger Logger; protected readonly ILogger Logger;
protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource(); protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource();
public LiveStream(MediaSourceInfo mediaSource, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths) public string TunerHostId { get; private set; }
public LiveStream(MediaSourceInfo mediaSource, TunerHostInfo tuner, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths)
{ {
OriginalMediaSource = mediaSource; OriginalMediaSource = mediaSource;
Environment = environment; Environment = environment;
@ -45,6 +48,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
EnableStreamSharing = true; EnableStreamSharing = true;
SharedStreamIds = new List<string>(); SharedStreamIds = new List<string>();
UniqueId = Guid.NewGuid().ToString("N"); UniqueId = Guid.NewGuid().ToString("N");
TunerHostId = tuner.Id;
AppPaths = appPaths; AppPaths = appPaths;

View File

@ -77,16 +77,28 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
{ {
var tunerCount = info.TunerCount;
if (tunerCount > 0)
{
var liveStreams = await EmbyTV.EmbyTV.Current.GetLiveStreams(info, cancellationToken).ConfigureAwait(false);
if (liveStreams.Count >= info.TunerCount)
{
throw new LiveTvConflictException();
}
}
var sources = await GetChannelStreamMediaSources(info, channelId, cancellationToken).ConfigureAwait(false); var sources = await GetChannelStreamMediaSources(info, channelId, cancellationToken).ConfigureAwait(false);
var mediaSource = sources.First(); var mediaSource = sources.First();
if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping) if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping)
{ {
return new SharedHttpStream(mediaSource, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment);
} }
return new LiveStream(mediaSource, _environment, FileSystem, Logger, Config.ApplicationPaths); return new LiveStream(mediaSource, info, _environment, FileSystem, Logger, Config.ApplicationPaths);
} }
public async Task Validate(TunerHostInfo info) public async Task Validate(TunerHostInfo info)

View File

@ -14,6 +14,7 @@ using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using System.Globalization; using System.Globalization;
using MediaBrowser.Controller.IO; using MediaBrowser.Controller.IO;
using MediaBrowser.Model.LiveTv;
namespace Emby.Server.Implementations.LiveTv.TunerHosts namespace Emby.Server.Implementations.LiveTv.TunerHosts
{ {
@ -22,8 +23,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
public SharedHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment) public SharedHttpStream(MediaSourceInfo mediaSource, TunerHostInfo tunerHostInfo, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment)
: base(mediaSource, environment, fileSystem, logger, appPaths) : base(mediaSource, tunerHostInfo, environment, fileSystem, logger, appPaths)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_appHost = appHost; _appHost = appHost;

View File

@ -114,12 +114,14 @@ namespace MediaBrowser.Api
foreach (var link in video.GetLinkedAlternateVersions()) foreach (var link in video.GetLinkedAlternateVersions())
{ {
link.PrimaryVersionId = null; link.SetPrimaryVersionId(null);
link.LinkedAlternateVersions = Video.EmptyLinkedChildArray;
link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
} }
video.LinkedAlternateVersions = Video.EmptyLinkedChildArray; video.LinkedAlternateVersions = Video.EmptyLinkedChildArray;
video.SetPrimaryVersionId(null);
video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
} }
@ -174,7 +176,7 @@ namespace MediaBrowser.Api
foreach (var item in items.Where(i => i.Id != primaryVersion.Id)) foreach (var item in items.Where(i => i.Id != primaryVersion.Id))
{ {
item.PrimaryVersionId = primaryVersion.Id.ToString("N"); item.SetPrimaryVersionId(primaryVersion.Id.ToString("N"));
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);

View File

@ -84,6 +84,20 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public void SetPrimaryVersionId(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
PrimaryVersionId = null;
}
else
{
PrimaryVersionId = id;
}
PresentationUniqueKey = CreatePresentationUniqueKey();
}
public override string CreatePresentationUniqueKey() public override string CreatePresentationUniqueKey()
{ {
if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
@ -667,8 +681,6 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException("media"); throw new ArgumentNullException("media");
} }
var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id);
var locationType = media.LocationType; var locationType = media.LocationType;
var info = new MediaSourceInfo var info = new MediaSourceInfo
@ -676,8 +688,8 @@ namespace MediaBrowser.Controller.Entities
Id = media.Id.ToString("N"), Id = media.Id.ToString("N"),
IsoType = media.IsoType, IsoType = media.IsoType,
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
MediaStreams = mediaStreams, MediaStreams = MediaSourceManager.GetMediaStreams(media.Id),
Name = GetMediaSourceName(media, mediaStreams), Name = GetMediaSourceName(media),
Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path, Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path,
RunTimeTicks = media.RunTimeTicks, RunTimeTicks = media.RunTimeTicks,
Video3DFormat = media.Video3DFormat, Video3DFormat = media.Video3DFormat,
@ -740,12 +752,20 @@ namespace MediaBrowser.Controller.Entities
return info; return info;
} }
private static string GetMediaSourceName(Video video, List<MediaStream> mediaStreams) private static string GetMediaSourceName(Video video)
{ {
var terms = new List<string>(); var terms = new List<string>();
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); var locationType = video.LocationType;
var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); var path = video.Path;
if ((locationType == LocationType.FileSystem || locationType == LocationType.Offline) && !string.IsNullOrWhiteSpace(path))
{
terms.Add(System.IO.Path.GetFileName(path));
}
else
{
terms.Add(video.Name);
}
if (video.Video3DFormat.HasValue) if (video.Video3DFormat.HasValue)
{ {
@ -779,50 +799,6 @@ namespace MediaBrowser.Controller.Entities
} }
} }
if (videoStream != null)
{
if (videoStream.Width.HasValue)
{
if (videoStream.Width.Value >= 3800)
{
terms.Add("4K");
}
else if (videoStream.Width.Value >= 1900)
{
terms.Add("1080P");
}
else if (videoStream.Width.Value >= 1270)
{
terms.Add("720P");
}
else if (videoStream.Width.Value >= 700)
{
terms.Add("480P");
}
else
{
terms.Add("SD");
}
}
}
if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
{
terms.Add(videoStream.Codec.ToUpper());
}
if (audioStream != null)
{
var audioCodec = string.Equals(audioStream.Codec, "dca", StringComparison.OrdinalIgnoreCase)
? audioStream.Profile
: audioStream.Codec;
if (!string.IsNullOrEmpty(audioCodec))
{
terms.Add(audioCodec.ToUpper());
}
}
return string.Join("/", terms.ToArray(terms.Count)); return string.Join("/", terms.ToArray(terms.Count));
} }

View File

@ -63,8 +63,8 @@ namespace MediaBrowser.Controller.LiveTv
void Close(); void Close();
int ConsumerCount { get; } int ConsumerCount { get; }
string OriginalStreamId { get; set; } string OriginalStreamId { get; set; }
string TunerHostId { get; }
bool EnableStreamSharing { get; set; } bool EnableStreamSharing { get; set; }
ITunerHost TunerHost { get; set; }
MediaSourceInfo OpenedMediaSource { get; set; } MediaSourceInfo OpenedMediaSource { get; set; }
string UniqueId { get; } string UniqueId { get; }
List<string> SharedStreamIds { get; } List<string> SharedStreamIds { get; }

View File

@ -1341,13 +1341,11 @@ namespace MediaBrowser.Model.Dlna
return false; return false;
} }
if (!item.Bitrate.HasValue) // If we don't know the bitrate, then force a transcode if requested max bitrate is under 40 mbps
{ var itemBitrate = item.Bitrate ??
_logger.Info("Cannot " + playMethod + " due to unknown content bitrate"); 40000000;
return false;
}
if (item.Bitrate.Value > maxBitrate.Value) if (itemBitrate > maxBitrate.Value)
{ {
_logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), maxBitrate.Value.ToString(CultureInfo.InvariantCulture)); _logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), maxBitrate.Value.ToString(CultureInfo.InvariantCulture));
return false; return false;

View File

@ -47,6 +47,7 @@ namespace MediaBrowser.Model.LiveTv
public bool EnableStreamLooping { get; set; } public bool EnableStreamLooping { get; set; }
public bool EnableNewHdhrChannelIds { get; set; } public bool EnableNewHdhrChannelIds { get; set; }
public string Source { get; set; } public string Source { get; set; }
public int TunerCount { get; set; }
public TunerHostInfo() public TunerHostInfo()
{ {

View File

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.36.11")] [assembly: AssemblyVersion("3.2.36.12")]