private string GetDlnaHeaders(PlaylistItem item) { var profile = item.Profile; var streamInfo = item.StreamInfo; if (streamInfo.MediaType == DlnaProfileType.Audio) { return(new ContentFeatureBuilder(profile) .BuildAudioHeader( streamInfo.Container, streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioBitrate, streamInfo.TargetAudioSampleRate, streamInfo.TargetAudioChannels, streamInfo.TargetAudioBitDepth, streamInfo.IsDirectStream, streamInfo.RunTimeTicks ?? 0, streamInfo.TranscodeSeekInfo)); } if (streamInfo.MediaType == DlnaProfileType.Video) { var list = new ContentFeatureBuilder(profile) .BuildVideoHeader( streamInfo.Container, streamInfo.TargetVideoCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetWidth, streamInfo.TargetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, streamInfo.TargetTimestamp, streamInfo.IsDirectStream, streamInfo.RunTimeTicks ?? 0, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate ?? 0, streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, streamInfo.IsTargetInterlaced, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, streamInfo.TargetVideoCodecTag, streamInfo.IsTargetAVC); return(list.Count == 0 ? null : list[0]); } return(null); }
private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null) { if (streamInfo == null) { var sources = _user == null?video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList(); streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions { ItemId = GetClientId(video), MediaSources = sources, Profile = _profile, DeviceId = deviceId, MaxBitrate = _profile.MaxStreamingBitrate }); } var targetWidth = streamInfo.TargetWidth; var targetHeight = streamInfo.TargetHeight; var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, streamInfo.VideoCodec, streamInfo.AudioCodec, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, streamInfo.TargetAudioChannels, streamInfo.TargetAudioBitrate, streamInfo.TargetTimestamp, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, streamInfo.IsTargetCabac, streamInfo.TargetRefFrames); foreach (var contentFeature in contentFeatureList) { AddVideoResource(container, video, deviceId, filter, contentFeature, streamInfo); } foreach (var subtitle in streamInfo.GetExternalSubtitles(_serverAddress, false)) { AddSubtitleElement(container, subtitle); } }
private void AddImageResElement( BaseItem item, XmlWriter writer, int maxWidth, int maxHeight, string format, string org_Pn) { var imageInfo = GetImageInfo(item); if (imageInfo == null) { return; } var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, format); writer.WriteStartElement(string.Empty, "res", NsDidl); // Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail // rather than using a larger one when available var width = albumartUrlInfo.width ?? maxWidth; var height = albumartUrlInfo.height ?? maxHeight; var contentFeatures = new ContentFeatureBuilder(_profile) .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn); writer.WriteAttributeString( "protocolInfo", string.Format( CultureInfo.InvariantCulture, "http-get:*:{0}:{1}", MimeTypes.GetMimeType("file." + format), contentFeatures)); writer.WriteAttributeString( "resolution", string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height)); writer.WriteString(albumartUrlInfo.url); writer.WriteFullEndElement(); }
private void AddImageResElement(BaseItem item, XmlElement element, int maxWidth, int maxHeight, int playbackPercentage, int unplayedCount, string format, string org_Pn) { var imageInfo = GetImageInfo(item); if (imageInfo == null) { return; } var result = element.OwnerDocument; var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, playbackPercentage, unplayedCount, format); var res = result.CreateElement(string.Empty, "res", NS_DIDL); res.InnerText = albumartUrlInfo.Url; var width = albumartUrlInfo.Width; var height = albumartUrlInfo.Height; var contentFeatures = new ContentFeatureBuilder(_profile) .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn); res.SetAttribute("protocolInfo", String.Format( "http-get:*:{0}:{1}", MimeTypes.GetMimeType("file." + format), contentFeatures )); if (width.HasValue && height.HasValue) { res.SetAttribute("resolution", string.Format("{0}x{1}", width.Value, height.Value)); } element.AppendChild(res); }
private void AddImageResElement(BaseItem item, XmlWriter writer, int maxWidth, int maxHeight, int playbackPercentage, int unplayedCount, string format, string org_Pn) { var imageInfo = GetImageInfo(item); if (imageInfo == null) { return; } var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, playbackPercentage, unplayedCount, format); writer.WriteStartElement(string.Empty, "res", NS_DIDL); var width = albumartUrlInfo.Width; var height = albumartUrlInfo.Height; var contentFeatures = new ContentFeatureBuilder(_profile) .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn); writer.WriteAttributeString("protocolInfo", String.Format( "http-get:*:{0}:{1}", GetMimeType("file." + format), contentFeatures )); if (width.HasValue && height.HasValue) { writer.WriteAttributeString("resolution", string.Format("{0}x{1}", width.Value, height.Value)); } writer.WriteString(albumartUrlInfo.Url); writer.WriteFullEndElement(); }
private void AddAudioResource(DlnaOptions options, XmlWriter writer, IHasMediaSources audio, string deviceId, Filter filter, StreamInfo streamInfo = null) { writer.WriteStartElement(string.Empty, "res", NS_DIDL); if (streamInfo == null) { var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user); streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions { ItemId = GetClientId(audio), MediaSources = sources.ToArray(sources.Count), Profile = _profile, DeviceId = deviceId }); } var url = streamInfo.ToDlnaUrl(_serverAddress, _accessToken); var mediaSource = streamInfo.MediaSource; if (mediaSource.RunTimeTicks.HasValue) { writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); } if (filter.Contains("res@size")) { if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength) { var size = streamInfo.TargetSize; if (size.HasValue) { writer.WriteAttributeString("size", size.Value.ToString(_usCulture)); } } } var targetAudioBitrate = streamInfo.TargetAudioBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; var targetAudioBitDepth = streamInfo.TargetAudioBitDepth; if (targetChannels.HasValue) { writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); } if (targetSampleRate.HasValue) { writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); } if (targetAudioBitrate.HasValue) { writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(_usCulture)); } var mediaProfile = _profile.GetAudioMediaProfile(streamInfo.Container, streamInfo.TargetAudioCodec, targetChannels, targetAudioBitrate, targetSampleRate, targetAudioBitDepth); var filename = url.Substring(0, url.IndexOf('?')); var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) ? GetMimeType(filename) : mediaProfile.MimeType; var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container, streamInfo.TargetAudioCodec, targetAudioBitrate, targetSampleRate, targetChannels, targetAudioBitDepth, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TranscodeSeekInfo); writer.WriteAttributeString("protocolInfo", String.Format( "http-get:*:{0}:{1}", mimeType, contentFeatures )); writer.WriteString(url); writer.WriteFullEndElement(); }
private void AddVideoResource(DlnaOptions options, XmlWriter writer, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null) { if (streamInfo == null) { var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user); streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions { ItemId = GetClientId(video), MediaSources = sources.ToArray(sources.Count), Profile = _profile, DeviceId = deviceId, MaxBitrate = _profile.MaxStreamingBitrate }); } var targetWidth = streamInfo.TargetWidth; var targetHeight = streamInfo.TargetHeight; var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, streamInfo.TargetVideoCodec, streamInfo.TargetAudioCodec, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, streamInfo.TargetTimestamp, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, streamInfo.IsTargetInterlaced, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, streamInfo.TargetVideoCodecTag, streamInfo.IsTargetAVC); foreach (var contentFeature in contentFeatureList) { AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo); } var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken) .Where(subtitle => subtitle.DeliveryMethod == SubtitleDeliveryMethod.External) .ToList(); foreach (var subtitle in subtitleProfiles) { var subtitleAdded = AddSubtitleElement(writer, subtitle); if (subtitleAdded && _profile.EnableSingleSubtitleLimit) { break; } } }
/// <summary> /// Adds the dlna headers. /// </summary> /// <param name="state">The state.</param> /// <param name="responseHeaders">The response headers.</param> /// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param> /// <param name="startTimeTicks">The start time in ticks.</param> /// <param name="request">The <see cref="HttpRequest"/>.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> public static void AddDlnaHeaders( StreamState state, IHeaderDictionary responseHeaders, bool isStaticallyStreamed, long?startTimeTicks, HttpRequest request, IDlnaManager dlnaManager) { if (!state.EnableDlnaHeaders) { return; } var profile = state.DeviceProfile; StringValues transferMode = request.Headers["transferMode.dlna.org"]; responseHeaders.Add("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode.ToString()); responseHeaders.Add("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"); if (state.RunTimeTicks.HasValue) { if (string.Equals(request.Headers["getMediaInfo.sec"], "1", StringComparison.OrdinalIgnoreCase)) { var ms = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds; responseHeaders.Add("MediaInfo.sec", string.Format( CultureInfo.InvariantCulture, "SEC_Duration={0};", Convert.ToInt32(ms))); } if (!isStaticallyStreamed && profile != null) { AddTimeSeekResponseHeaders(state, responseHeaders, startTimeTicks); } } profile ??= dlnaManager.GetDefaultProfile(); var audioCodec = state.ActualOutputAudioCodec; if (!state.IsVideoRequest) { responseHeaders.Add("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader( profile, state.OutputContainer, audioCodec, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioChannels, state.OutputAudioBitDepth, isStaticallyStreamed, state.RunTimeTicks, state.TranscodeSeekInfo)); } else { var videoCodec = state.ActualOutputVideoCodec; responseHeaders.Add( "contentFeatures.dlna.org", ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty); } }
private void AddAudioResource(XmlElement container, Audio audio, string deviceId, Filter filter) { var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL); var sources = _dtoService.GetMediaSources(audio); var streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions { ItemId = audio.Id.ToString("N"), MediaSources = sources, Profile = _profile, DeviceId = deviceId }); var url = streamInfo.ToDlnaUrl(_serverAddress); //res.AppendChild(container.OwnerDocument.CreateCDataSection(url)); res.InnerText = url; var mediaSource = sources.First(i => string.Equals(i.Id, streamInfo.MediaSourceId)); if (mediaSource.RunTimeTicks.HasValue) { res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); } if (filter.Contains("res@size")) { if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength) { var size = streamInfo.TargetSize; if (size.HasValue) { res.SetAttribute("size", size.Value.ToString(_usCulture)); } } } var targetAudioBitrate = streamInfo.TargetAudioBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; if (targetChannels.HasValue) { res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); } if (targetSampleRate.HasValue) { res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); } if (targetAudioBitrate.HasValue) { res.SetAttribute("bitrate", targetAudioBitrate.Value.ToString(_usCulture)); } var mediaProfile = _profile.GetAudioMediaProfile(streamInfo.Container, streamInfo.AudioCodec, targetChannels, targetAudioBitrate); var filename = url.Substring(0, url.IndexOf('?')); var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) ? MimeTypes.GetMimeType(filename) : mediaProfile.MimeType; var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container, streamInfo.TargetAudioCodec, targetAudioBitrate, targetSampleRate, targetChannels, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, streamInfo.TranscodeSeekInfo); res.SetAttribute("protocolInfo", String.Format( "http-get:*:{0}:{1}", mimeType, contentFeatures )); container.AppendChild(res); }
private void AddAudioResource(XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null) { writer.WriteStartElement(string.Empty, "res", NsDidl); if (streamInfo == null) { var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user); streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildAudioItem(new AudioOptions { ItemId = audio.Id, MediaSources = sources.ToArray(), Profile = _profile, DeviceId = deviceId }); } var url = NormalizeDlnaMediaUrl(streamInfo.ToUrl(_serverAddress, _accessToken)); var mediaSource = streamInfo.MediaSource; if (mediaSource.RunTimeTicks.HasValue) { writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); } if (filter.Contains("res@size")) { if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength) { var size = streamInfo.TargetSize; if (size.HasValue) { writer.WriteAttributeString("size", size.Value.ToString(_usCulture)); } } } var targetAudioBitrate = streamInfo.TargetAudioBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; var targetAudioBitDepth = streamInfo.TargetAudioBitDepth; if (targetChannels.HasValue) { writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); } if (targetSampleRate.HasValue) { writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); } if (targetAudioBitrate.HasValue) { writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(_usCulture)); } var mediaProfile = _profile.GetAudioMediaProfile( streamInfo.Container, streamInfo.TargetAudioCodec.FirstOrDefault(), targetChannels, targetAudioBitrate, targetSampleRate, targetAudioBitDepth); var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal)); var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) ? MimeTypes.GetMimeType(filename) : mediaProfile.MimeType; var contentFeatures = ContentFeatureBuilder.BuildAudioHeader( _profile, streamInfo.Container, streamInfo.TargetAudioCodec.FirstOrDefault(), targetAudioBitrate, targetSampleRate, targetChannels, targetAudioBitDepth, streamInfo.IsDirectStream, streamInfo.RunTimeTicks ?? 0, streamInfo.TranscodeSeekInfo); writer.WriteAttributeString( "protocolInfo", string.Format( CultureInfo.InvariantCulture, "http-get:*:{0}:{1}", mimeType, contentFeatures)); writer.WriteString(url); writer.WriteFullEndElement(); }
/// <summary> /// Adds the dlna headers. /// </summary> /// <param name="state">The state.</param> /// <param name="responseHeaders">The response headers.</param> /// <param name="profileManager">The <see cref="IDeviceProfileManager"/> instance.</param> /// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param> /// <param name="startTimeTicks">The start time in ticks.</param> /// <param name="request">The <see cref="HttpRequest"/>.</param> private static void AddDlnaHeaders( StreamState state, IHeaderDictionary responseHeaders, IDeviceProfileManager profileManager, bool isStaticallyStreamed, long?startTimeTicks, HttpRequest request) { if (state == null) { throw new ArgumentNullException(nameof(state)); } if (responseHeaders == null) { throw new ArgumentNullException(nameof(responseHeaders)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } var enableDlnaHeaders = request.Query.TryGetValue("dlna", out _) || !string.Equals(request.Headers["GetContentFeatures.DLNA.ORG"], "1", StringComparison.Ordinal); if (!enableDlnaHeaders) { return; } var profile = state.DeviceProfile; StringValues transferMode = request.Headers["transferMode.dlna.org"]; responseHeaders.Add("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode.ToString()); responseHeaders.Add("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"); if (state.RunTimeTicks.HasValue) { if (string.Equals(request.Headers["getMediaInfo.sec"], "1", StringComparison.OrdinalIgnoreCase)) { var ms = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds; responseHeaders.Add("MediaInfo.sec", string.Format( CultureInfo.InvariantCulture, "SEC_Duration={0};", Convert.ToInt32(ms))); } if (!isStaticallyStreamed && profile != null) { AddTimeSeekResponseHeaders(state, responseHeaders, startTimeTicks); } } // if the profile hasn't been assigned see if there is one that matches. profile ??= profileManager.GetProfile( request.Headers, request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback, null); var audioCodec = state.ActualOutputAudioCodec; if (!state.IsVideoRequest) { responseHeaders.Add("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader( profile, state.OutputContainer, audioCodec, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioChannels, state.OutputAudioBitDepth, isStaticallyStreamed, state.RunTimeTicks, state.TranscodeSeekInfo)); } else { var videoCodec = state.ActualOutputVideoCodec; responseHeaders.Add( "contentFeatures.dlna.org", ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty); } }