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(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(); }
/// <summary> /// Builds an audio header. /// </summary> /// <param name="profile">A <see cref="DeviceProfile"/>.</param> /// <param name="container">The container.</param> /// <param name="audioCodec">The audio codec.</param> /// <param name="audioBitrate">Optional. The audio bitrate.</param> /// <param name="audioSampleRate">Optional. The sample audio rate.</param> /// <param name="audioChannels">Optional. The number of audio channels.</param> /// <param name="audioBitDepth">Optional. The audio bit depth.</param> /// <param name="isDirectStream">True if being accessed by audio stream.</param> /// <param name="runtimeTicks">Optional. The runtime ticks.</param> /// <param name="transcodeSeekInfo">An instance of <see cref="TranscodeSeekInfo"/>.</param> /// <returns>A string representation.</returns> public static string BuildAudioHeader( DeviceProfile profile, string container, string?audioCodec, int?audioBitrate, int?audioSampleRate, int?audioChannels, int?audioBitDepth, bool isDirectStream, long?runtimeTicks, TranscodeSeekInfo transcodeSeekInfo) { 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"; const DlnaFlags FlagValue = DlnaFlags.StreamingTransferMode | DlnaFlags.BackgroundTransferMode | DlnaFlags.InteractiveTransferMode | DlnaFlags.DlnaV15; // if (isDirectStream) // { // flagValue = flagValue | DlnaFlags.ByteBasedSeek; // } // else if (runtimeTicks.HasValue) // { // flagValue = flagValue | DlnaFlags.TimeBasedSeek; // } string dlnaflags = string.Format( CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}", DlnaMaps.FlagsToString(FlagValue)); var mediaProfile = profile.GetAudioMediaProfile( container, audioCodec, audioChannels, audioBitrate, audioSampleRate, audioBitDepth); var orgPn = mediaProfile?.OrgPn; if (string.IsNullOrEmpty(orgPn)) { orgPn = GetAudioOrgPnValue(container, audioBitrate, audioSampleRate, audioChannels); } if (string.IsNullOrEmpty(orgPn)) { return(orgOp.TrimStart(';') + orgCi + dlnaflags); } return("DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags); }