| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 | 
							- using System;
 
- using System.Globalization;
 
- using System.Security;
 
- using System.Text;
 
- namespace MediaBrowser.Api.Playback.Dash
 
- {
 
-     public class ManifestBuilder
 
-     {
 
-         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-         public string GetManifestText(StreamState state, string playlistUrl)
 
-         {
 
-             var builder = new StringBuilder();
 
-             var time = TimeSpan.FromTicks(state.RunTimeTicks.Value);
 
-             var duration = "PT" + time.Hours.ToString("00", UsCulture) + "H" + time.Minutes.ToString("00", UsCulture) + "M" + time.Seconds.ToString("00", UsCulture) + ".00S";
 
-             builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
 
-             builder.AppendFormat(
 
-                 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:mpeg:dash:schema:mpd:2011\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\" profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" type=\"static\" mediaPresentationDuration=\"{0}\" minBufferTime=\"PT5.0S\">",
 
-                 duration);
 
-             builder.Append("<ProgramInformation>");
 
-             builder.Append("</ProgramInformation>");
 
-             builder.Append("<Period start=\"PT0S\">");
 
-             builder.Append(GetVideoAdaptationSet(state, playlistUrl));
 
-             builder.Append(GetAudioAdaptationSet(state, playlistUrl));
 
-             builder.Append("</Period>");
 
-             builder.Append("</MPD>");
 
-             return builder.ToString();
 
-         }
 
-         private string GetVideoAdaptationSet(StreamState state, string playlistUrl)
 
-         {
 
-             var builder = new StringBuilder();
 
-             builder.Append("<AdaptationSet id=\"video\" segmentAlignment=\"true\" bitstreamSwitching=\"true\">");
 
-             builder.Append(GetVideoRepresentationOpenElement(state));
 
-             AppendSegmentList(state, builder, "0", playlistUrl);
 
-             builder.Append("</Representation>");
 
-             builder.Append("</AdaptationSet>");
 
-             return builder.ToString();
 
-         }
 
-         private string GetAudioAdaptationSet(StreamState state, string playlistUrl)
 
-         {
 
-             var builder = new StringBuilder();
 
-             builder.Append("<AdaptationSet id=\"audio\" segmentAlignment=\"true\" bitstreamSwitching=\"true\">");
 
-             builder.Append(GetAudioRepresentationOpenElement(state));
 
-             builder.Append("<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"6\" />");
 
-             AppendSegmentList(state, builder, "1", playlistUrl);
 
-             builder.Append("</Representation>");
 
-             builder.Append("</AdaptationSet>");
 
-             return builder.ToString();
 
-         }
 
-         private string GetVideoRepresentationOpenElement(StreamState state)
 
-         {
 
-             var codecs = GetVideoCodecDescriptor(state);
 
-             var mime = "video/mp4";
 
-             var xml = "<Representation id=\"0\" mimeType=\"" + mime + "\" codecs=\"" + codecs + "\"";
 
-             if (state.OutputWidth.HasValue)
 
-             {
 
-                 xml += " width=\"" + state.OutputWidth.Value.ToString(UsCulture) + "\"";
 
-             }
 
-             if (state.OutputHeight.HasValue)
 
-             {
 
-                 xml += " height=\"" + state.OutputHeight.Value.ToString(UsCulture) + "\"";
 
-             }
 
-             if (state.OutputVideoBitrate.HasValue)
 
-             {
 
-                 xml += " bandwidth=\"" + state.OutputVideoBitrate.Value.ToString(UsCulture) + "\"";
 
-             }
 
-             xml += ">";
 
-             return xml;
 
-         }
 
-         private string GetAudioRepresentationOpenElement(StreamState state)
 
-         {
 
-             var codecs = GetAudioCodecDescriptor(state);
 
-             var mime = "audio/mp4";
 
-             var xml = "<Representation id=\"1\" mimeType=\"" + mime + "\" codecs=\"" + codecs + "\"";
 
-             if (state.OutputAudioSampleRate.HasValue)
 
-             {
 
-                 xml += " audioSamplingRate=\"" + state.OutputAudioSampleRate.Value.ToString(UsCulture) + "\"";
 
-             }
 
-             if (state.OutputAudioBitrate.HasValue)
 
-             {
 
-                 xml += " bandwidth=\"" + state.OutputAudioBitrate.Value.ToString(UsCulture) + "\"";
 
-             }
 
-             xml += ">";
 
-             return xml;
 
-         }
 
-         private string GetVideoCodecDescriptor(StreamState state)
 
-         {
 
-             // https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html
 
-             // http://www.chipwreck.de/blog/2010/02/25/html-5-video-tag-and-attributes/
 
-             var level = state.TargetVideoLevel ?? 0;
 
-             var profile = state.TargetVideoProfile ?? string.Empty;
 
-             if (profile.IndexOf("high", StringComparison.OrdinalIgnoreCase) != -1)
 
-             {
 
-                 if (level >= 4.1)
 
-                 {
 
-                     return "avc1.640028";
 
-                 }
 
-                 if (level >= 4)
 
-                 {
 
-                     return "avc1.640028";
 
-                 }
 
-                 return "avc1.64001f";
 
-             }
 
-             if (profile.IndexOf("main", StringComparison.OrdinalIgnoreCase) != -1)
 
-             {
 
-                 if (level >= 4)
 
-                 {
 
-                     return "avc1.4d0028";
 
-                 }
 
-                 if (level >= 3.1)
 
-                 {
 
-                     return "avc1.4d001f";
 
-                 }
 
-                 return "avc1.4d001e";
 
-             }
 
-             if (level >= 3.1)
 
-             {
 
-                 return "avc1.42001f";
 
-             }
 
-             return "avc1.42E01E";
 
-         }
 
-         private string GetAudioCodecDescriptor(StreamState state)
 
-         {
 
-             // https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html
 
-             if (string.Equals(state.OutputAudioCodec, "mp3", StringComparison.OrdinalIgnoreCase))
 
-             {
 
-                 return "mp4a.40.34";
 
-             }
 
-             // AAC 5ch
 
-             if (state.OutputAudioChannels.HasValue && state.OutputAudioChannels.Value >= 5)
 
-             {
 
-                 return "mp4a.40.5";
 
-             }
 
-             // AAC 2ch
 
-             return "mp4a.40.2";
 
-         }
 
-         private void AppendSegmentList(StreamState state, StringBuilder builder, string type, string playlistUrl)
 
-         {
 
-             var extension = ".m4s";
 
-             var seconds = TimeSpan.FromTicks(state.RunTimeTicks ?? 0).TotalSeconds;
 
-             var queryStringIndex = playlistUrl.IndexOf('?');
 
-             var queryString = queryStringIndex == -1 ? string.Empty : playlistUrl.Substring(queryStringIndex);
 
-             var index = 0;
 
-             var duration = 1000000 * state.SegmentLength;
 
-             builder.AppendFormat("<SegmentList timescale=\"1000000\" duration=\"{0}\" startNumber=\"1\">", duration.ToString(CultureInfo.InvariantCulture));
 
-             while (seconds > 0)
 
-             {
 
-                 var filename = index == 0
 
-                     ? "init"
 
-                     : (index - 1).ToString(UsCulture);
 
-                 var segmentUrl = string.Format("dash/{3}/{0}{1}{2}",
 
-                     filename,
 
-                     extension,
 
-                     SecurityElement.Escape(queryString),
 
-                     type);
 
-                 if (index == 0)
 
-                 {
 
-                     builder.AppendFormat("<Initialization sourceURL=\"{0}\"/>", segmentUrl);
 
-                 }
 
-                 else
 
-                 {
 
-                     builder.AppendFormat("<SegmentURL media=\"{0}\"/>", segmentUrl);
 
-                 }
 
-                 seconds -= state.SegmentLength;
 
-                 index++;
 
-             }
 
-             builder.Append("</SegmentList>");
 
-         }
 
-     }
 
- }
 
 
  |