mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
added media stream helpers
This commit is contained in:
parent
eb6d72a4e2
commit
b9a2af1fd5
@ -39,8 +39,6 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
TaskManager = taskManager;
|
TaskManager = taskManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _lastResponseHadTasksRunning = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data to send.
|
/// Gets the data to send.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -48,25 +46,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
|
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
|
||||||
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
|
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
|
||||||
{
|
{
|
||||||
var tasks = TaskManager.ScheduledTasks.ToList();
|
return Task.FromResult(TaskManager.ScheduledTasks
|
||||||
|
|
||||||
var anyRunning = tasks.Any(i => i.State != TaskState.Idle);
|
|
||||||
|
|
||||||
if (anyRunning)
|
|
||||||
{
|
|
||||||
_lastResponseHadTasksRunning = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!_lastResponseHadTasksRunning)
|
|
||||||
{
|
|
||||||
return Task.FromResult<IEnumerable<TaskInfo>>(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastResponseHadTasksRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.FromResult(tasks
|
|
||||||
.OrderBy(i => i.Name)
|
.OrderBy(i => i.Name)
|
||||||
.Select(ScheduledTaskHelpers.GetTaskInfo)
|
.Select(ScheduledTaskHelpers.GetTaskInfo)
|
||||||
.Where(i => !i.IsHidden));
|
.Where(i => !i.IsHidden));
|
||||||
|
@ -220,27 +220,39 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
{
|
{
|
||||||
container = (container ?? string.Empty).TrimStart('.');
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
return ResponseProfiles.FirstOrDefault(i =>
|
foreach (var i in ResponseProfiles)
|
||||||
{
|
{
|
||||||
if (i.Type != DlnaProfileType.Photo)
|
if (i.Type != DlnaProfileType.Photo)
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> containers = i.GetContainers();
|
List<string> containers = i.GetContainers();
|
||||||
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionProcessor conditionProcessor = new ConditionProcessor();
|
ConditionProcessor conditionProcessor = new ConditionProcessor();
|
||||||
|
|
||||||
|
var anyOff = false;
|
||||||
foreach (ProfileCondition c in i.Conditions)
|
foreach (ProfileCondition c in i.Conditions)
|
||||||
{
|
{
|
||||||
if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
|
if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
|
||||||
return false;
|
{
|
||||||
|
anyOff = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
});
|
if (anyOff)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseProfile GetVideoMediaProfile(string container,
|
public ResponseProfile GetVideoMediaProfile(string container,
|
||||||
@ -260,66 +272,90 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
{
|
{
|
||||||
container = (container ?? string.Empty).TrimStart('.');
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
return ResponseProfiles.FirstOrDefault(i =>
|
foreach (var i in ResponseProfiles)
|
||||||
{
|
{
|
||||||
if (i.Type != DlnaProfileType.Video)
|
if (i.Type != DlnaProfileType.Video)
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> containers = i.GetContainers();
|
List<string> containers = i.GetContainers();
|
||||||
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> audioCodecs = i.GetAudioCodecs();
|
List<string> audioCodecs = i.GetAudioCodecs();
|
||||||
if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> videoCodecs = i.GetVideoCodecs();
|
List<string> videoCodecs = i.GetVideoCodecs();
|
||||||
if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionProcessor conditionProcessor = new ConditionProcessor();
|
ConditionProcessor conditionProcessor = new ConditionProcessor();
|
||||||
|
|
||||||
|
var anyOff = false;
|
||||||
foreach (ProfileCondition c in i.Conditions)
|
foreach (ProfileCondition c in i.Conditions)
|
||||||
{
|
{
|
||||||
if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
|
if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
|
||||||
return false;
|
{
|
||||||
|
anyOff = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
});
|
if (anyOff)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseProfile GetPhotoMediaProfile(string container, int? width, int? height)
|
public ResponseProfile GetPhotoMediaProfile(string container, int? width, int? height)
|
||||||
{
|
{
|
||||||
container = (container ?? string.Empty).TrimStart('.');
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
return ResponseProfiles.FirstOrDefault(i =>
|
foreach (var i in ResponseProfiles)
|
||||||
{
|
{
|
||||||
if (i.Type != DlnaProfileType.Photo)
|
if (i.Type != DlnaProfileType.Photo)
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> containers = i.GetContainers().ToList();
|
List<string> containers = i.GetContainers().ToList();
|
||||||
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionProcessor conditionProcessor = new ConditionProcessor();
|
ConditionProcessor conditionProcessor = new ConditionProcessor();
|
||||||
|
|
||||||
|
var anyOff = false;
|
||||||
foreach (ProfileCondition c in i.Conditions)
|
foreach (ProfileCondition c in i.Conditions)
|
||||||
{
|
{
|
||||||
if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
|
if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
|
||||||
return false;
|
{
|
||||||
|
anyOff = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
});
|
if (anyOff)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,15 +109,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
|
|
||||||
int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
|
int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
|
||||||
|
|
||||||
MediaStream audioStream = null;
|
MediaStream audioStream = item.DefaultAudioStream;
|
||||||
foreach (MediaStream i in item.MediaStreams)
|
|
||||||
{
|
|
||||||
if (i.Type == MediaStreamType.Audio)
|
|
||||||
{
|
|
||||||
audioStream = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Honor the max bitrate setting
|
// Honor the max bitrate setting
|
||||||
if (IsAudioEligibleForDirectPlay(item, maxBitrateSetting))
|
if (IsAudioEligibleForDirectPlay(item, maxBitrateSetting))
|
||||||
@ -191,11 +183,20 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
|
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
|
||||||
playlistItem.Protocol = transcodingProfile.Protocol;
|
playlistItem.Protocol = transcodingProfile.Protocol;
|
||||||
|
|
||||||
List<ProfileCondition> audioTranscodingConditions = options.Profile.CodecProfiles
|
List<CodecProfile> audioCodecProfiles = new List<CodecProfile>();
|
||||||
.Where(i => i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
|
foreach (CodecProfile i in options.Profile.CodecProfiles)
|
||||||
.Take(1)
|
{
|
||||||
.SelectMany(i => i.Conditions)
|
if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
|
||||||
.ToList();
|
{
|
||||||
|
audioCodecProfiles.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audioCodecProfiles.Count >= 1) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>();
|
||||||
|
foreach (CodecProfile i in audioCodecProfiles)
|
||||||
|
audioTranscodingConditions.AddRange(i.Conditions);
|
||||||
|
|
||||||
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
|
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
|
||||||
|
|
||||||
@ -229,25 +230,8 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
RunTimeTicks = item.RunTimeTicks
|
RunTimeTicks = item.RunTimeTicks
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaStream audioStream = null;
|
MediaStream audioStream = item.DefaultAudioStream;
|
||||||
foreach (MediaStream i in item.MediaStreams)
|
MediaStream videoStream = item.VideoStream;
|
||||||
{
|
|
||||||
if (i.Type == MediaStreamType.Audio)
|
|
||||||
{
|
|
||||||
audioStream = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaStream videoStream = null;
|
|
||||||
foreach (MediaStream i in item.MediaStreams)
|
|
||||||
{
|
|
||||||
if (i.Type == MediaStreamType.Video)
|
|
||||||
{
|
|
||||||
videoStream = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
|
int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
|
||||||
|
|
||||||
@ -288,18 +272,26 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
playlistItem.AudioStreamIndex = options.AudioStreamIndex;
|
playlistItem.AudioStreamIndex = options.AudioStreamIndex;
|
||||||
playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex;
|
playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex;
|
||||||
|
|
||||||
IEnumerable<ProfileCondition> videoTranscodingConditions = options.Profile.CodecProfiles
|
List<ProfileCondition> videoTranscodingConditions = new List<ProfileCondition>();
|
||||||
.Where(i => i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
|
foreach (CodecProfile i in options.Profile.CodecProfiles)
|
||||||
.Take(1)
|
{
|
||||||
.SelectMany(i => i.Conditions);
|
if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
|
||||||
|
{
|
||||||
|
videoTranscodingConditions.AddRange(i.Conditions);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
|
ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
|
||||||
|
|
||||||
IEnumerable<ProfileCondition> audioTranscodingConditions = options.Profile.CodecProfiles
|
List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>();
|
||||||
.Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
|
foreach (CodecProfile i in options.Profile.CodecProfiles)
|
||||||
.Take(1)
|
{
|
||||||
.SelectMany(i => i.Conditions);
|
if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
|
||||||
|
{
|
||||||
|
audioTranscodingConditions.AddRange(i.Conditions);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
|
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
|
||||||
|
|
||||||
// Honor requested max channels
|
// Honor requested max channels
|
||||||
@ -453,12 +445,6 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.AudioStreamIndex.HasValue &&
|
|
||||||
item.MediaStreams.Count(i => i.Type == MediaStreamType.Audio) > 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IsAudioEligibleForDirectPlay(item, maxBitrate);
|
return IsAudioEligibleForDirectPlay(item, maxBitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,13 +143,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (MediaStream stream in MediaSource.MediaStreams)
|
return MediaSource.DefaultAudioStream;
|
||||||
{
|
|
||||||
if (stream.Type == MediaStreamType.Audio)
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -165,12 +159,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
{
|
{
|
||||||
if (MediaSource != null)
|
if (MediaSource != null)
|
||||||
{
|
{
|
||||||
foreach (MediaStream i in MediaSource.MediaStreams)
|
return MediaSource.VideoStream;
|
||||||
{
|
|
||||||
if (i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using MediaBrowser.Model.Entities;
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
@ -14,9 +16,9 @@ namespace MediaBrowser.Model.Dto
|
|||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
|
|
||||||
public LocationType LocationType { get; set; }
|
public LocationType LocationType { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public long? RunTimeTicks { get; set; }
|
public long? RunTimeTicks { get; set; }
|
||||||
|
|
||||||
public VideoType? VideoType { get; set; }
|
public VideoType? VideoType { get; set; }
|
||||||
@ -24,19 +26,61 @@ namespace MediaBrowser.Model.Dto
|
|||||||
public IsoType? IsoType { get; set; }
|
public IsoType? IsoType { get; set; }
|
||||||
|
|
||||||
public Video3DFormat? Video3DFormat { get; set; }
|
public Video3DFormat? Video3DFormat { get; set; }
|
||||||
|
|
||||||
public List<MediaStream> MediaStreams { get; set; }
|
public List<MediaStream> MediaStreams { get; set; }
|
||||||
|
|
||||||
public List<string> Formats { get; set; }
|
public List<string> Formats { get; set; }
|
||||||
|
|
||||||
public int? Bitrate { get; set; }
|
public int? Bitrate { get; set; }
|
||||||
|
|
||||||
public TransportStreamTimestamp? Timestamp { get; set; }
|
public TransportStreamTimestamp? Timestamp { get; set; }
|
||||||
|
|
||||||
public MediaSourceInfo()
|
public MediaSourceInfo()
|
||||||
{
|
{
|
||||||
Formats = new List<string>();
|
Formats = new List<string>();
|
||||||
MediaStreams = new List<MediaStream>();
|
MediaStreams = new List<MediaStream>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public MediaStream DefaultAudioStream
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (MediaStream i in MediaStreams)
|
||||||
|
{
|
||||||
|
if (i.Type == MediaStreamType.Audio && i.IsDefault)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MediaStream i in MediaStreams)
|
||||||
|
{
|
||||||
|
if (i.Type == MediaStreamType.Audio)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public MediaStream VideoStream
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (MediaStream i in MediaStreams)
|
||||||
|
{
|
||||||
|
if (i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1165,7 +1165,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
|
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
|
||||||
.ThenByDescending(i =>
|
.ThenByDescending(i =>
|
||||||
{
|
{
|
||||||
var stream = i.MediaStreams.FirstOrDefault(m => m.Type == MediaStreamType.Video);
|
var stream = i.VideoStream;
|
||||||
|
|
||||||
return stream == null || stream.Width == null ? 0 : stream.Width.Value;
|
return stream == null || stream.Width == null ? 0 : stream.Width.Value;
|
||||||
})
|
})
|
||||||
|
@ -741,6 +741,6 @@
|
|||||||
"LabelSeasonNumber": "Season number",
|
"LabelSeasonNumber": "Season number",
|
||||||
"LabelEpisodeNumber": "Episode number",
|
"LabelEpisodeNumber": "Episode number",
|
||||||
"LabelEndingEpisodeNumber": "Ending episode number",
|
"LabelEndingEpisodeNumber": "Ending episode number",
|
||||||
"HeaderTypeText": "Type Text",
|
"HeaderTypeText": "Enter Text",
|
||||||
"LabelTypeText": "Text"
|
"LabelTypeText": "Text"
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user