private void AddVideoResource(XmlWriter writer, IHasMediaSources video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo) { writer.WriteStartElement(string.Empty, "res", NS_DIDL); 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 totalBitrate = streamInfo.TargetTotalBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; var targetWidth = streamInfo.TargetWidth; var targetHeight = streamInfo.TargetHeight; if (targetChannels.HasValue) { writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); } if (filter.Contains("res@resolution")) { if (targetWidth.HasValue && targetHeight.HasValue) { writer.WriteAttributeString("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value)); } } if (targetSampleRate.HasValue) { writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); } if (totalBitrate.HasValue) { writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(_usCulture)); } var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container, streamInfo.TargetAudioCodec, streamInfo.TargetVideoCodec, streamInfo.TargetAudioBitrate, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, streamInfo.TargetPacketLength, streamInfo.TargetTimestamp, streamInfo.IsTargetAnamorphic, streamInfo.IsTargetInterlaced, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, streamInfo.TargetVideoCodecTag, streamInfo.IsTargetAVC); var filename = url.Substring(0, url.IndexOf('?')); var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) ? GetMimeType(filename) : mediaProfile.MimeType; writer.WriteAttributeString("protocolInfo", String.Format( "http-get:*:{0}:{1}", mimeType, contentFeatures )); writer.WriteString(url); writer.WriteFullEndElement(); }
private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo) { var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL); var url = streamInfo.ToDlnaUrl(_serverAddress); res.InnerText = url; var mediaSource = streamInfo.MediaSource; 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 totalBitrate = streamInfo.TargetTotalBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; var targetWidth = streamInfo.TargetWidth; var targetHeight = streamInfo.TargetHeight; if (targetChannels.HasValue) { res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); } if (filter.Contains("res@resolution")) { if (targetWidth.HasValue && targetHeight.HasValue) { res.SetAttribute("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value)); } } if (targetSampleRate.HasValue) { res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); } if (totalBitrate.HasValue) { res.SetAttribute("bitrate", totalBitrate.Value.ToString(_usCulture)); } var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container, streamInfo.AudioCodec, streamInfo.VideoCodec, streamInfo.TargetAudioBitrate, targetChannels, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, streamInfo.TargetPacketLength, streamInfo.TargetTimestamp, streamInfo.IsTargetAnamorphic); var filename = url.Substring(0, url.IndexOf('?')); var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) ? MimeTypes.GetMimeType(filename) : mediaProfile.MimeType; res.SetAttribute("protocolInfo", String.Format( "http-get:*:{0}:{1}", mimeType, contentFeatures )); container.AppendChild(res); }
private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter) { var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL); var sources = _dtoService.GetMediaSources(video); int?maxBitrateSetting = null; var streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions { ItemId = video.Id.ToString("N"), MediaSources = sources, Profile = _profile, DeviceId = deviceId, MaxBitrate = maxBitrateSetting }); 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 totalBitrate = streamInfo.TargetTotalBitrate; var targetSampleRate = streamInfo.TargetAudioSampleRate; var targetChannels = streamInfo.TargetAudioChannels; var targetWidth = streamInfo.TargetWidth; var targetHeight = streamInfo.TargetHeight; if (targetChannels.HasValue) { res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); } if (filter.Contains("res@resolution")) { if (targetWidth.HasValue && targetHeight.HasValue) { res.SetAttribute("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value)); } } if (targetSampleRate.HasValue) { res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); } if (totalBitrate.HasValue) { res.SetAttribute("bitrate", totalBitrate.Value.ToString(_usCulture)); } var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container, streamInfo.AudioCodec, streamInfo.VideoCodec, streamInfo.TargetAudioBitrate, targetChannels, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, streamInfo.TargetPacketLength, streamInfo.TargetTimestamp); 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).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); res.SetAttribute("protocolInfo", String.Format( "http-get:*:{0}:{1}", mimeType, contentFeatures )); container.AppendChild(res); }
/// <summary> /// Builds a video header. /// </summary> /// <param name="profile">A <see cref="DeviceProfile"/>.</param> /// <param name="container">The container.</param> /// <param name="videoCodec">The video codec.</param> /// <param name="audioCodec">The audio codec.</param> /// <param name="width">Optional. The width.</param> /// <param name="height">Optional. The height.</param> /// <param name="bitDepth">Optional. The bit depth.</param> /// <param name="videoBitrate">Optional. The video bitrate.</param> /// <param name="timestamp">Optional. A <see cref="TransportStreamTimestamp"/>.</param> /// <param name="isDirectStream">True if the stream is playable by directStream.</param> /// <param name="runtimeTicks">Optional. Runtime ticks.</param> /// <param name="videoProfile">The video profile.</param> /// <param name="videoLevel">Optional. The video level.</param> /// <param name="videoFramerate">Optional. The video framerate.</param> /// <param name="packetLength">Optional. The packet length.</param> /// <param name="transcodeSeekInfo">The <see cref="TranscodeSeekInfo"/>.</param> /// <param name="isAnamorphic">Optional. True, if anamorphic.</param> /// <param name="isInterlaced">Optional. True, if interlaced.</param> /// <param name="refFrames">Optional. The number of reference frames.</param> /// <param name="numVideoStreams">Optional. The number of video streams.</param> /// <param name="numAudioStreams">Optional. The number of audio streams.</param> /// <param name="videoCodecTag">The video codec tag.</param> /// <param name="isAvc">True is AVC.</param> /// <returns>A list containing the video information.</returns> public static List <string> BuildVideoHeader( DeviceProfile profile, string container, string?videoCodec, string?audioCodec, int?width, int?height, int?bitDepth, int?videoBitrate, TransportStreamTimestamp timestamp, bool isDirectStream, long?runtimeTicks, string?videoProfile, double?videoLevel, float?videoFramerate, int?packetLength, TranscodeSeekInfo transcodeSeekInfo, bool?isAnamorphic, bool?isInterlaced, int?refFrames, int?numVideoStreams, int?numAudioStreams, string?videoCodecTag, bool?isAvc) { if (profile == null) { throw new ArgumentNullException(nameof(profile)); } // first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo); // 0 = native, 1 = transcoded string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1"; var flagValue = DlnaFlags.StreamingTransferMode | DlnaFlags.BackgroundTransferMode | DlnaFlags.InteractiveTransferMode | DlnaFlags.DlnaV15; if (isDirectStream) { flagValue |= DlnaFlags.ByteBasedSeek; } else if (runtimeTicks.HasValue) { flagValue |= DlnaFlags.TimeBasedSeek; } string dlnaflags = string.Format(CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}", DlnaMaps.FlagsToString(flagValue)); var mediaProfile = profile.GetVideoMediaProfile( container, audioCodec, videoCodec, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc); var orgPnValues = new List <string>(); if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn)) { orgPnValues.AddRange(mediaProfile.OrgPn.Split(',', StringSplitOptions.RemoveEmptyEntries)); } else { foreach (var s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp)) { orgPnValues.Add(s.ToString()); break; } } var contentFeatureList = new List <string>(); foreach (string orgPn in orgPnValues) { if (string.IsNullOrEmpty(orgPn)) { contentFeatureList.Add(orgOp.TrimStart(';') + orgCi + dlnaflags); } else { contentFeatureList.Add("DLNA.ORG_PN=" + orgPn + orgCi + dlnaflags); } } if (orgPnValues.Count == 0) { contentFeatureList.Add(orgOp.TrimStart(';') + orgCi + dlnaflags); } return(contentFeatureList); }