mirror of
https://github.com/jellyfin/jellyfin
synced 2024-09-06 08:04:44 +00:00
add live stream params
This commit is contained in:
parent
c4a271534e
commit
6ea8e7868d
|
@ -371,7 +371,7 @@ namespace Emby.Server.Implementations.Library
|
|||
var tuple = GetProvider(request.OpenToken);
|
||||
var provider = tuple.Item1;
|
||||
|
||||
var mediaSourceTuple = await provider.OpenMediaSource(tuple.Item2, request.AllowMediaProbe, cancellationToken).ConfigureAwait(false);
|
||||
var mediaSourceTuple = await provider.OpenMediaSource(tuple.Item2, request.EnableMediaProbe, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var mediaSource = mediaSourceTuple.Item1;
|
||||
|
||||
|
|
|
@ -1514,7 +1514,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
}
|
||||
|
||||
private DateTime _lastRecordingRefreshTime;
|
||||
private async Task RefreshRecordings(CancellationToken cancellationToken)
|
||||
private async Task RefreshRecordings(Guid internalLiveTvFolderId, CancellationToken cancellationToken)
|
||||
{
|
||||
const int cacheMinutes = 2;
|
||||
|
||||
|
@ -1542,10 +1542,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
});
|
||||
|
||||
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
|
||||
var parentFolderId = folder.Id;
|
||||
|
||||
var recordingTasks = results.SelectMany(i => i.ToList()).Select(i => CreateRecordingRecord(i.Item1, i.Item2.Name, parentFolderId, cancellationToken));
|
||||
var recordingTasks = results.SelectMany(i => i.ToList()).Select(i => CreateRecordingRecord(i.Item1, i.Item2.Name, internalLiveTvFolderId, cancellationToken));
|
||||
|
||||
var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false);
|
||||
|
||||
|
@ -1559,7 +1557,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions dtoOptions, User user)
|
||||
private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions dtoOptions, Guid internalLiveTvFolderId, User user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
|
@ -1571,21 +1569,31 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
return new QueryResult<BaseItem>();
|
||||
}
|
||||
|
||||
var folders = EmbyTV.EmbyTV.Current.GetRecordingFolders()
|
||||
var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders()
|
||||
.SelectMany(i => i.Locations)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Select(i => _libraryManager.FindByPath(i, true))
|
||||
.Where(i => i != null)
|
||||
.Where(i => i.IsVisibleStandalone(user))
|
||||
.Select(i => i.Id)
|
||||
.ToList();
|
||||
|
||||
if (folders.Count == 0)
|
||||
var excludeItemTypes = new List<string>();
|
||||
|
||||
if (!query.IsInProgress.HasValue)
|
||||
{
|
||||
folderIds.Add(internalLiveTvFolderId);
|
||||
|
||||
excludeItemTypes.Add(typeof(LiveTvChannel).Name);
|
||||
excludeItemTypes.Add(typeof(LiveTvProgram).Name);
|
||||
}
|
||||
|
||||
if (folderIds.Count == 0)
|
||||
{
|
||||
return new QueryResult<BaseItem>();
|
||||
}
|
||||
|
||||
var includeItemTypes = new List<string>();
|
||||
var excludeItemTypes = new List<string>();
|
||||
var genres = new List<string>();
|
||||
|
||||
if (query.IsMovie.HasValue)
|
||||
|
@ -1631,7 +1639,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
{
|
||||
MediaTypes = new[] { MediaType.Video },
|
||||
Recursive = true,
|
||||
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(),
|
||||
AncestorIds = folderIds.Select(i => i.ToString("N")).ToArray(),
|
||||
IsFolder = false,
|
||||
IsVirtualItem = false,
|
||||
Limit = query.Limit,
|
||||
|
@ -1714,12 +1722,24 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
return new QueryResult<BaseItem>();
|
||||
}
|
||||
|
||||
if (_services.Count == 1 && !(query.IsInProgress ?? false) && (!query.IsLibraryItem.HasValue || query.IsLibraryItem.Value))
|
||||
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (_services.Count == 1 && (!query.IsInProgress.HasValue || !query.IsInProgress.Value) && (!query.IsLibraryItem.HasValue || query.IsLibraryItem.Value))
|
||||
{
|
||||
return GetEmbyRecordings(query, options, user);
|
||||
if (!query.IsInProgress.HasValue)
|
||||
{
|
||||
await RefreshRecordings(folder.Id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return GetEmbyRecordings(query, options, folder.Id, user);
|
||||
}
|
||||
|
||||
await RefreshRecordings(cancellationToken).ConfigureAwait(false);
|
||||
return await GetInternalRecordingsFromServices(query, user, options, folder.Id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetInternalRecordingsFromServices(RecordingQuery query, User user, DtoOptions options, Guid internalLiveTvFolderId, CancellationToken cancellationToken)
|
||||
{
|
||||
await RefreshRecordings(internalLiveTvFolderId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var internalQuery = new InternalItemsQuery(user)
|
||||
{
|
||||
|
@ -2620,7 +2640,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
|
||||
}, new DtoOptions(), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var recordings = recordingResult.Items.OfType<ILiveTvRecording>().ToList();
|
||||
var embyServiceName = EmbyTV.EmbyTV.Current.Name;
|
||||
var recordings = recordingResult.Items.Where(i => !string.Equals(i.ServiceName, embyServiceName, StringComparison.OrdinalIgnoreCase)).OfType<ILiveTvRecording>().ToList();
|
||||
|
||||
var groups = new List<BaseItemDto>();
|
||||
|
||||
|
|
|
@ -848,6 +848,11 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
{
|
||||
return string.Empty;
|
||||
}
|
||||
// No known video stream
|
||||
if (state.VideoStream == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var codec = EncodingHelper.GetVideoEncoder(state, ApiEntryPoint.Instance.GetEncodingOptions());
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ namespace MediaBrowser.Api.Playback
|
|||
SubtitleStreamIndex = request.SubtitleStreamIndex,
|
||||
UserId = request.UserId,
|
||||
OpenToken = mediaSource.OpenToken,
|
||||
AllowMediaProbe = request.AllowMediaProbe
|
||||
EnableMediaProbe = request.EnableMediaProbe
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
|
|
|
@ -635,8 +635,10 @@ namespace MediaBrowser.Model.Dlna
|
|||
MediaStream videoStream = item.VideoStream;
|
||||
|
||||
// TODO: This doesn't accout for situation of device being able to handle media bitrate, but wifi connection not fast enough
|
||||
bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), subtitleStream, options, PlayMethod.DirectPlay));
|
||||
bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || IsEligibleForDirectPlay(item, options.GetMaxBitrate(false), subtitleStream, options, PlayMethod.DirectStream));
|
||||
var directPlayEligibilityResult = IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), subtitleStream, options, PlayMethod.DirectPlay);
|
||||
var directStreamEligibilityResult = IsEligibleForDirectPlay(item, options.GetMaxBitrate(false), subtitleStream, options, PlayMethod.DirectStream);
|
||||
bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayEligibilityResult.Item1);
|
||||
bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamEligibilityResult.Item1);
|
||||
|
||||
_logger.Info("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}",
|
||||
options.Profile.Name ?? "Unknown Profile",
|
||||
|
@ -669,6 +671,16 @@ namespace MediaBrowser.Model.Dlna
|
|||
transcodeReasons.AddRange(directPlayInfo.Item2);
|
||||
}
|
||||
|
||||
if (directPlayEligibilityResult.Item2.HasValue)
|
||||
{
|
||||
transcodeReasons.Add(directPlayEligibilityResult.Item2.Value);
|
||||
}
|
||||
|
||||
if (directStreamEligibilityResult.Item2.HasValue)
|
||||
{
|
||||
transcodeReasons.Add(directStreamEligibilityResult.Item2.Value);
|
||||
}
|
||||
|
||||
// Can't direct play, find the transcoding profile
|
||||
TranscodingProfile transcodingProfile = null;
|
||||
foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
|
||||
|
@ -1136,7 +1148,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
mediaSource.Path ?? "Unknown path");
|
||||
}
|
||||
|
||||
private bool IsEligibleForDirectPlay(MediaSourceInfo item,
|
||||
private Tuple<bool, TranscodeReason?> IsEligibleForDirectPlay(MediaSourceInfo item,
|
||||
long? maxBitrate,
|
||||
MediaStream subtitleStream,
|
||||
VideoOptions options,
|
||||
|
@ -1149,11 +1161,18 @@ namespace MediaBrowser.Model.Dlna
|
|||
if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed)
|
||||
{
|
||||
_logger.Info("Not eligible for {0} due to unsupported subtitles", playMethod);
|
||||
return false;
|
||||
return new Tuple<bool, TranscodeReason?>(false, TranscodeReason.SubtitleCodecNotSupported);
|
||||
}
|
||||
}
|
||||
|
||||
return IsAudioEligibleForDirectPlay(item, maxBitrate, playMethod);
|
||||
var result = IsAudioEligibleForDirectPlay(item, maxBitrate, playMethod);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return new Tuple<bool, TranscodeReason?>(result, null);
|
||||
}
|
||||
|
||||
return new Tuple<bool, TranscodeReason?>(result, TranscodeReason.ContainerBitrateExceedsLimit);
|
||||
}
|
||||
|
||||
public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, string transcodingSubProtocol, string transcodingContainer)
|
||||
|
|
|
@ -17,13 +17,13 @@ namespace MediaBrowser.Model.MediaInfo
|
|||
|
||||
public bool EnableDirectPlay { get; set; }
|
||||
public bool EnableDirectStream { get; set; }
|
||||
public bool AllowMediaProbe { get; set; }
|
||||
public bool EnableMediaProbe { get; set; }
|
||||
|
||||
public LiveStreamRequest()
|
||||
{
|
||||
EnableDirectPlay = true;
|
||||
EnableDirectStream = true;
|
||||
AllowMediaProbe = true;
|
||||
EnableMediaProbe = true;
|
||||
}
|
||||
|
||||
public LiveStreamRequest(AudioOptions options)
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace MediaBrowser.Model.MediaInfo
|
|||
public bool AllowVideoStreamCopy { get; set; }
|
||||
public bool AllowAudioStreamCopy { get; set; }
|
||||
public bool AutoOpenLiveStream { get; set; }
|
||||
public bool AllowMediaProbe { get; set; }
|
||||
public bool EnableMediaProbe { get; set; }
|
||||
|
||||
public PlaybackInfoRequest()
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace MediaBrowser.Model.MediaInfo
|
|||
EnableTranscoding = true;
|
||||
AllowVideoStreamCopy = true;
|
||||
AllowAudioStreamCopy = true;
|
||||
AllowMediaProbe = true;
|
||||
EnableMediaProbe = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace MediaBrowser.Model.Session
|
|||
VideoFramerateNotSupported = 17,
|
||||
VideoLevelNotSupported = 18,
|
||||
VideoProfileNotSupported = 19,
|
||||
AudioBitDepthNotSupported = 20
|
||||
AudioBitDepthNotSupported = 20,
|
||||
SubtitleCodecNotSupported = 21
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
|
||||
{
|
||||
if (!item.IsLocked)
|
||||
if (!item.IsLocked && !item.LockedFields.Contains(MetadataFields.Genres))
|
||||
{
|
||||
var taggedItems = item.IsAccessedByName ?
|
||||
item.GetTaggedItems(new Controller.Entities.InternalItemsQuery()
|
||||
|
@ -31,22 +31,19 @@ namespace MediaBrowser.Providers.Music
|
|||
}) :
|
||||
item.GetRecursiveChildren(i => i is IHasArtist && !i.IsFolder).ToList();
|
||||
|
||||
if (!item.LockedFields.Contains(MetadataFields.Genres))
|
||||
var currentList = item.Genres.ToList();
|
||||
|
||||
item.Genres = taggedItems.SelectMany(i => i.Genres)
|
||||
.DistinctNames()
|
||||
.ToList();
|
||||
|
||||
if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
var currentList = item.Genres.ToList();
|
||||
|
||||
item.Genres = taggedItems.SelectMany(i => i.Genres)
|
||||
.DistinctNames()
|
||||
.ToList();
|
||||
|
||||
if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
updateType = updateType | ItemUpdateType.MetadataEdit;
|
||||
}
|
||||
updateType = updateType | ItemUpdateType.MetadataEdit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return updateType;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Controller.Configuration;
|
||||
using System;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Playlists;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
|
@ -6,7 +7,7 @@ using MediaBrowser.Model.Entities;
|
|||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Providers.Manager;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
|
@ -33,6 +34,33 @@ namespace MediaBrowser.Providers.Playlists
|
|||
}
|
||||
}
|
||||
|
||||
protected override ItemUpdateType BeforeSave(Playlist item, bool isFullRefresh, ItemUpdateType currentUpdateType)
|
||||
{
|
||||
var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType);
|
||||
|
||||
if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
|
||||
{
|
||||
if (!item.IsLocked && !item.LockedFields.Contains(MetadataFields.Genres))
|
||||
{
|
||||
var items = item.GetLinkedChildren()
|
||||
.ToList();
|
||||
|
||||
var currentList = item.Genres.ToList();
|
||||
|
||||
item.Genres = items.SelectMany(i => i.Genres)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
updateType = updateType | ItemUpdateType.MetadataEdit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updateType;
|
||||
}
|
||||
|
||||
public PlaylistMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||
{
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue