public ResponseProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, int?audioBitrate, int?audioChannels, int?width, int?height, int?bitDepth, int?videoBitrate, string videoProfile, double?videoLevel, double?videoFramerate, int?packetLength, TransportStreamTimestamp timestamp) { container = (container ?? string.Empty).TrimStart('.'); return(ResponseProfiles.FirstOrDefault(i => { if (i.Type != DlnaProfileType.Video) { return false; } var containers = i.GetContainers().ToList(); if (containers.Count > 0 && !containers.Contains(container)) { return false; } var audioCodecs = i.GetAudioCodecs().ToList(); if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty)) { return false; } var videoCodecs = i.GetVideoCodecs().ToList(); if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty)) { return false; } var conditionProcessor = new ConditionProcessor(); return i.Conditions.All(c => conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp)); })); }
private PlayMethod?GetVideoDirectPlayProfile(DeviceProfile profile, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream, bool isEligibleForDirectPlay, bool isEligibleForDirectStream) { if (videoStream == null) { _logger.Info("Profile: {0}, Cannot direct stream with no known video stream. Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return(null); } // See if it can be direct played DirectPlayProfile directPlay = null; foreach (DirectPlayProfile i in profile.DirectPlayProfiles) { if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)) { directPlay = i; break; } } if (directPlay == null) { _logger.Info("Profile: {0}, No direct play profiles found for Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return(null); } string container = mediaSource.Container; List <ProfileCondition> conditions = new List <ProfileCondition>(); foreach (ContainerProfile i in profile.ContainerProfiles) { if (i.Type == DlnaProfileType.Video && ListHelper.ContainsIgnoreCase(i.GetContainers(), container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } ConditionProcessor conditionProcessor = new ConditionProcessor(); int? width = videoStream == null ? null : videoStream.Width; int? height = videoStream == null ? null : videoStream.Height; int? bitDepth = videoStream == null ? null : videoStream.BitDepth; int? videoBitrate = videoStream == null ? null : videoStream.BitRate; double?videoLevel = videoStream == null ? null : videoStream.Level; string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; string videoCodecTag = videoStream == null ? null : videoStream.CodecTag; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; TransportStreamTimestamp?timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; int?packetLength = videoStream == null ? null : videoStream.PacketLength; int?refFrames = videoStream == null ? null : videoStream.RefFrames; int?numAudioStreams = mediaSource.GetStreamCount(MediaStreamType.Audio); int?numVideoStreams = mediaSource.GetStreamCount(MediaStreamType.Video); // Check container conditions foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(profile, "VideoContainerProfile", i, mediaSource); return(null); } } string videoCodec = videoStream == null ? null : videoStream.Codec; if (string.IsNullOrEmpty(videoCodec)) { _logger.Info("Profile: {0}, DirectPlay=false. Reason=Unknown video codec. Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return(null); } conditions = new List <ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec, container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); return(null); } } if (audioStream != null) { string audioCodec = audioStream.Codec; if (string.IsNullOrEmpty(audioCodec)) { _logger.Info("Profile: {0}, DirectPlay=false. Reason=Unknown audio codec. Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return(null); } conditions = new List <ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec, container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { bool?isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream); if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile, isSecondaryAudio)) { LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource); return(null); } } } if (isEligibleForDirectPlay && mediaSource.SupportsDirectPlay) { if (mediaSource.Protocol == MediaProtocol.Http) { if (_localPlayer.CanAccessUrl(mediaSource.Path, mediaSource.RequiredHttpHeaders.Count > 0)) { return(PlayMethod.DirectPlay); } } else if (mediaSource.Protocol == MediaProtocol.File) { if (_localPlayer.CanAccessFile(mediaSource.Path)) { return(PlayMethod.DirectPlay); } } } if (isEligibleForDirectStream && mediaSource.SupportsDirectStream) { return(PlayMethod.DirectStream); } return(null); }
public ResponseProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, int? audioBitrate, int? audioChannels, int? width, int? height, int? bitDepth, int? videoBitrate, string videoProfile, double? videoLevel, float? videoFramerate, int? packetLength, TransportStreamTimestamp timestamp, bool? isAnamorphic, bool? isCabac, int? refFrames) { container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in ResponseProfiles) { if (i.Type != DlnaProfileType.Video) { continue; } List<string> containers = i.GetContainers(); if (containers.Count > 0 && !ListHelper.ContainsIgnoreCase(containers, container ?? string.Empty)) { continue; } List<string> audioCodecs = i.GetAudioCodecs(); if (audioCodecs.Count > 0 && !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec ?? string.Empty)) { continue; } List<string> videoCodecs = i.GetVideoCodecs(); if (videoCodecs.Count > 0 && !ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec ?? string.Empty)) { continue; } ConditionProcessor conditionProcessor = new ConditionProcessor(); var anyOff = false; foreach (ProfileCondition c in i.Conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames)) { anyOff = true; break; } } if (anyOff) { continue; } return i; } return null; }
public ResponseProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, int?width, int?height, int?bitDepth, int?videoBitrate, string videoProfile, double?videoLevel, float?videoFramerate, int?packetLength, TransportStreamTimestamp timestamp, bool?isAnamorphic, bool?isInterlaced, int?refFrames, int?numVideoStreams, int?numAudioStreams, string videoCodecTag, bool?isAvc) { foreach (var i in ResponseProfiles) { if (i.Type != DlnaProfileType.Video) { continue; } if (!ContainerProfile.ContainsContainer(i.GetContainers(), container)) { continue; } var audioCodecs = i.GetAudioCodecs(); if (audioCodecs.Length > 0 && !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec ?? string.Empty)) { continue; } var videoCodecs = i.GetVideoCodecs(); if (videoCodecs.Length > 0 && !ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec ?? string.Empty)) { continue; } var anyOff = false; foreach (ProfileCondition c in i.Conditions) { if (!ConditionProcessor.IsVideoConditionSatisfied(GetModelProfileCondition(c), width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)) { anyOff = true; break; } } if (anyOff) { continue; } return(i); } return(null); }
private PlayMethod? GetVideoDirectPlayProfile(DeviceProfile profile, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream, bool isEligibleForDirectPlay, bool isEligibleForDirectStream) { // See if it can be direct played DirectPlayProfile directPlay = null; foreach (DirectPlayProfile i in profile.DirectPlayProfiles) { if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)) { directPlay = i; break; } } if (directPlay == null) { _logger.Debug("Profile: {0}, No direct play profiles found for Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return null; } string container = mediaSource.Container; List<ProfileCondition> conditions = new List<ProfileCondition>(); foreach (ContainerProfile i in profile.ContainerProfiles) { if (i.Type == DlnaProfileType.Video && ListHelper.ContainsIgnoreCase(i.GetContainers(), container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } ConditionProcessor conditionProcessor = new ConditionProcessor(); int? width = videoStream == null ? null : videoStream.Width; int? height = videoStream == null ? null : videoStream.Height; int? bitDepth = videoStream == null ? null : videoStream.BitDepth; int? videoBitrate = videoStream == null ? null : videoStream.BitRate; double? videoLevel = videoStream == null ? null : videoStream.Level; string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; bool? isCabac = videoStream == null ? null : videoStream.IsCabac; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; int? packetLength = videoStream == null ? null : videoStream.PacketLength; int? refFrames = videoStream == null ? null : videoStream.RefFrames; int? numAudioStreams = mediaSource.GetStreamCount(MediaStreamType.Audio); int? numVideoStreams = mediaSource.GetStreamCount(MediaStreamType.Video); // Check container conditions foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) { LogConditionFailure(profile, "VideoContainerProfile", i, mediaSource); return null; } } string videoCodec = videoStream == null ? null : videoStream.Codec; if (string.IsNullOrEmpty(videoCodec)) { _logger.Debug("Profile: {0}, DirectPlay=false. Reason=Unknown video codec. Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return null; } conditions = new List<ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec, container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) { LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); return null; } } if (audioStream != null) { string audioCodec = audioStream.Codec; if (string.IsNullOrEmpty(audioCodec)) { _logger.Debug("Profile: {0}, DirectPlay=false. Reason=Unknown audio codec. Path: {1}", profile.Name ?? "Unknown Profile", mediaSource.Path ?? "Unknown path"); return null; } conditions = new List<ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec, container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { bool? isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream); if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile, isSecondaryAudio)) { LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource); return null; } } } if (isEligibleForDirectPlay && mediaSource.SupportsDirectPlay) { if (mediaSource.Protocol == MediaProtocol.Http) { if (_localPlayer.CanAccessUrl(mediaSource.Path, mediaSource.RequiredHttpHeaders.Count > 0)) { return PlayMethod.DirectPlay; } } else if (mediaSource.Protocol == MediaProtocol.File) { if (_localPlayer.CanAccessFile(mediaSource.Path)) { return PlayMethod.DirectPlay; } } } if (isEligibleForDirectStream && mediaSource.SupportsDirectStream) { return PlayMethod.DirectStream; } return null; }
private PlayMethod?GetVideoDirectPlayProfile(VideoOptions options, DeviceProfile profile, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream) { // See if it can be direct played DirectPlayProfile directPlay = null; foreach (DirectPlayProfile i in profile.DirectPlayProfiles) { if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)) { directPlay = i; break; } } if (directPlay == null) { return(null); } string container = mediaSource.Container; List <ProfileCondition> conditions = new List <ProfileCondition>(); foreach (ContainerProfile i in profile.ContainerProfiles) { if (i.Type == DlnaProfileType.Video && ListHelper.ContainsIgnoreCase(i.GetContainers(), container)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } ConditionProcessor conditionProcessor = new ConditionProcessor(); int? width = videoStream == null ? null : videoStream.Width; int? height = videoStream == null ? null : videoStream.Height; int? bitDepth = videoStream == null ? null : videoStream.BitDepth; int? videoBitrate = videoStream == null ? null : videoStream.BitRate; double?videoLevel = videoStream == null ? null : videoStream.Level; string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; bool? isCabac = videoStream == null ? null : videoStream.IsCabac; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; TransportStreamTimestamp?timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; int?packetLength = videoStream == null ? null : videoStream.PacketLength; int?refFrames = videoStream == null ? null : videoStream.RefFrames; // Check container conditions foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames)) { return(null); } } string videoCodec = videoStream == null ? null : videoStream.Codec; if (string.IsNullOrEmpty(videoCodec)) { return(null); } conditions = new List <ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames)) { return(null); } } if (audioStream != null) { string audioCodec = audioStream.Codec; if (string.IsNullOrEmpty(audioCodec)) { return(null); } conditions = new List <ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec)) { foreach (ProfileCondition c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile)) { return(null); } } } if (mediaSource.Protocol == MediaProtocol.Http) { if (_localPlayer.CanAccessUrl(mediaSource.Path, mediaSource.RequiredHttpHeaders.Count > 0)) { return(PlayMethod.DirectPlay); } } else if (mediaSource.Protocol == MediaProtocol.File) { if (_localPlayer.CanAccessFile(mediaSource.Path)) { return(PlayMethod.DirectPlay); } } if (!mediaSource.SupportsDirectStream) { return(null); } return(PlayMethod.DirectStream); }
public ResponseProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, int?width, int?height, int?bitDepth, int?videoBitrate, string videoProfile, double?videoLevel, float?videoFramerate, int?packetLength, TransportStreamTimestamp timestamp, bool?isAnamorphic, bool?isCabac, int?refFrames, int?numVideoStreams, int?numAudioStreams) { container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in ResponseProfiles) { if (i.Type != DlnaProfileType.Video) { continue; } List <string> containers = i.GetContainers(); if (containers.Count > 0 && !ListHelper.ContainsIgnoreCase(containers, container ?? string.Empty)) { continue; } List <string> audioCodecs = i.GetAudioCodecs(); if (audioCodecs.Count > 0 && !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec ?? string.Empty)) { continue; } List <string> videoCodecs = i.GetVideoCodecs(); if (videoCodecs.Count > 0 && !ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec ?? string.Empty)) { continue; } ConditionProcessor conditionProcessor = new ConditionProcessor(); var anyOff = false; foreach (ProfileCondition c in i.Conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(c, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) { anyOff = true; break; } } if (anyOff) { continue; } return(i); } return(null); }
private DirectPlayProfile GetVideoDirectPlayProfile(DeviceProfile profile, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream) { // See if it can be direct played DirectPlayProfile directPlay = null; foreach (DirectPlayProfile i in profile.DirectPlayProfiles) { if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)) { directPlay = i; break; } } if (directPlay == null) { return null; } string container = mediaSource.Container; List<ProfileCondition> conditions = new List<ProfileCondition>(); foreach (ContainerProfile i in profile.ContainerProfiles) { if (i.Type == DlnaProfileType.Video && ListHelper.ContainsIgnoreCase(i.GetContainers(), container)) { foreach (var c in i.Conditions) { conditions.Add(c); } } } ConditionProcessor conditionProcessor = new ConditionProcessor(); int? width = videoStream == null ? null : videoStream.Width; int? height = videoStream == null ? null : videoStream.Height; int? bitDepth = videoStream == null ? null : videoStream.BitDepth; int? videoBitrate = videoStream == null ? null : videoStream.BitRate; double? videoLevel = videoStream == null ? null : videoStream.Level; string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; int? packetLength = videoStream == null ? null : videoStream.PacketLength; // Check container conditions foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic)) { return null; } } string videoCodec = videoStream == null ? null : videoStream.Codec; if (string.IsNullOrEmpty(videoCodec)) { return null; } conditions = new List<ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec)) { foreach (var c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic)) { return null; } } if (audioStream != null) { string audioCodec = audioStream.Codec; if (string.IsNullOrEmpty(audioCodec)) { return null; } conditions = new List<ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec)) { foreach (var c in i.Conditions) { conditions.Add(c); } } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile)) { return null; } } } return directPlay; }
private DirectPlayProfile GetVideoDirectPlayProfile(DeviceProfile profile, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream) { // See if it can be direct played DirectPlayProfile directPlay = null; foreach (DirectPlayProfile i in profile.DirectPlayProfiles) { if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)) { directPlay = i; break; } } if (directPlay == null) { return(null); } string container = mediaSource.Container; List <ProfileCondition> conditions = new List <ProfileCondition>(); foreach (ContainerProfile i in profile.ContainerProfiles) { if (i.Type == DlnaProfileType.Video && ListHelper.ContainsIgnoreCase(i.GetContainers(), container)) { conditions.AddRange(i.Conditions); } } ConditionProcessor conditionProcessor = new ConditionProcessor(); int? width = videoStream == null ? null : videoStream.Width; int? height = videoStream == null ? null : videoStream.Height; int? bitDepth = videoStream == null ? null : videoStream.BitDepth; int? videoBitrate = videoStream == null ? null : videoStream.BitRate; double?videoLevel = videoStream == null ? null : videoStream.Level; string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; TransportStreamTimestamp?timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; int?packetLength = videoStream == null ? null : videoStream.PacketLength; // Check container conditions foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp)) { return(null); } } string videoCodec = videoStream == null ? null : videoStream.Codec; if (string.IsNullOrEmpty(videoCodec)) { return(null); } conditions = new List <ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec)) { conditions.AddRange(i.Conditions); } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp)) { return(null); } } if (audioStream != null) { string audioCodec = audioStream.Codec; if (string.IsNullOrEmpty(audioCodec)) { return(null); } conditions = new List <ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec)) { conditions.AddRange(i.Conditions); } } foreach (ProfileCondition i in conditions) { if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile)) { return(null); } } } return(directPlay); }
private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options) { StreamInfo playlistItem = new StreamInfo { ItemId = options.ItemId, MediaType = DlnaProfileType.Video, MediaSource = item, RunTimeTicks = item.RunTimeTicks, Context = options.Context, DeviceProfile = options.Profile }; playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? GetDefaultSubtitleStreamIndex(item, options.Profile.SubtitleProfiles); MediaStream subtitleStream = playlistItem.SubtitleStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Subtitle, playlistItem.SubtitleStreamIndex.Value) : null; MediaStream audioStream = item.GetDefaultAudioStream(options.AudioStreamIndex ?? item.DefaultAudioStreamIndex); int? audioStreamIndex = null; if (audioStream != null) { audioStreamIndex = audioStream.Index; } 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)); _logger.Info("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}", options.Profile.Name ?? "Unknown Profile", item.Path ?? "Unknown path", isEligibleForDirectPlay, isEligibleForDirectStream); if (isEligibleForDirectPlay || isEligibleForDirectStream) { // See if it can be direct played PlayMethod? directPlay = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); if (directPlay != null) { playlistItem.PlayMethod = directPlay.Value; playlistItem.Container = item.Container; if (subtitleStream != null) { SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value); playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleFormat = subtitleProfile.Format; } return playlistItem; } } // Can't direct play, find the transcoding profile TranscodingProfile transcodingProfile = null; foreach (TranscodingProfile i in options.Profile.TranscodingProfiles) { if (i.Type == playlistItem.MediaType && i.Context == options.Context) { transcodingProfile = i; break; } } if (transcodingProfile != null) { if (!item.SupportsTranscoding) { return null; } if (subtitleStream != null) { SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode); playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleFormat = subtitleProfile.Format; } playlistItem.PlayMethod = PlayMethod.Transcode; playlistItem.Container = transcodingProfile.Container; playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength; playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(','); playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; if (!string.IsNullOrEmpty(transcodingProfile.MaxAudioChannels)) { int transcodingMaxAudioChannels; if (IntHelper.TryParseCultureInvariant(transcodingProfile.MaxAudioChannels, out transcodingMaxAudioChannels)) { playlistItem.TranscodingMaxAudioChannels = transcodingMaxAudioChannels; } } playlistItem.SubProtocol = transcodingProfile.Protocol; playlistItem.AudioStreamIndex = audioStreamIndex; ConditionProcessor conditionProcessor = new ConditionProcessor(); List<ProfileCondition> videoTranscodingConditions = new List<ProfileCondition>(); foreach (CodecProfile i in options.Profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec, transcodingProfile.Container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { bool? isSecondaryAudio = audioStream == null ? null : item.IsSecondaryAudio(audioStream); int? inputAudioBitrate = audioStream == null ? null : audioStream.BitRate; int? audioChannels = audioStream == null ? null : audioStream.Channels; string audioProfile = audioStream == null ? null : audioStream.Profile; if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, audioProfile, isSecondaryAudio)) { LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item); applyConditions = false; break; } } if (applyConditions) { foreach (ProfileCondition c in i.Conditions) { videoTranscodingConditions.Add(c); } break; } } } ApplyTranscodingConditions(playlistItem, videoTranscodingConditions); List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>(); foreach (CodecProfile i in options.Profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(playlistItem.TargetAudioCodec, transcodingProfile.Container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { int? width = videoStream == null ? null : videoStream.Width; int? height = videoStream == null ? null : videoStream.Height; int? bitDepth = videoStream == null ? null : videoStream.BitDepth; int? videoBitrate = videoStream == null ? null : videoStream.BitRate; double? videoLevel = videoStream == null ? null : videoStream.Level; string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; string videoCodecTag = videoStream == null ? null : videoStream.CodecTag; TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : item.Timestamp; int? packetLength = videoStream == null ? null : videoStream.PacketLength; int? refFrames = videoStream == null ? null : videoStream.RefFrames; int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio); int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video); if (!conditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(options.Profile, "VideoCodecProfile", applyCondition, item); applyConditions = false; break; } } if (applyConditions) { foreach (ProfileCondition c in i.Conditions) { audioTranscodingConditions.Add(c); } break; } } } ApplyTranscodingConditions(playlistItem, audioTranscodingConditions); // Honor requested max channels if (options.MaxAudioChannels.HasValue) { int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value; playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } 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); // Honor max rate if (maxBitrateSetting.HasValue) { int videoBitrate = maxBitrateSetting.Value; if (playlistItem.AudioBitrate.HasValue) { videoBitrate -= playlistItem.AudioBitrate.Value; } // 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); } } return playlistItem; }
private DirectPlayProfile GetVideoDirectPlayProfile(DeviceProfile profile, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream) { // See if it can be direct played var directPlay = profile.DirectPlayProfiles .FirstOrDefault(i => i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)); if (directPlay == null) { return(null); } var container = mediaSource.Container; var conditions = profile.ContainerProfiles .Where(i => i.Type == DlnaProfileType.Video && i.GetContainers().Contains(container, StringComparer.OrdinalIgnoreCase)) .SelectMany(i => i.Conditions); var conditionProcessor = new ConditionProcessor(); var width = videoStream == null ? null : videoStream.Width; var height = videoStream == null ? null : videoStream.Height; var bitDepth = videoStream == null ? null : videoStream.BitDepth; var videoBitrate = videoStream == null ? null : videoStream.BitRate; var videoLevel = videoStream == null ? null : videoStream.Level; var videoProfile = videoStream == null ? null : videoStream.Profile; var videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; var audioBitrate = audioStream == null ? null : audioStream.BitRate; var audioChannels = audioStream == null ? null : audioStream.Channels; var timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp; var packetLength = videoStream == null ? null : videoStream.PacketLength; // Check container conditions if (!conditions.All(i => conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))) { return(null); } var videoCodec = videoStream == null ? null : videoStream.Codec; if (string.IsNullOrEmpty(videoCodec)) { return(null); } conditions = profile.CodecProfiles .Where(i => i.Type == CodecType.Video && i.ContainsCodec(videoCodec)) .SelectMany(i => i.Conditions); if (!conditions.All(i => conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))) { return(null); } if (audioStream != null) { var audioCodec = audioStream.Codec; if (string.IsNullOrEmpty(audioCodec)) { return(null); } conditions = profile.CodecProfiles .Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec)) .SelectMany(i => i.Conditions); if (!conditions.All(i => conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate))) { return(null); } } return(directPlay); }