/// <summary> /// Adds custom attributes to the quality level. /// </summary> /// <param name="reader">The xml reader.</param> /// <param name="qualityLevel">The quality level.</param> private static void AddCustomAttributes(XmlReader reader, QualityLevel qualityLevel) { if (!reader.IsEmptyElement) { while (reader.Read()) { if (reader.Name == "CustomAttributes" && reader.NodeType == XmlNodeType.Element) { while (reader.Read()) { if ((reader.Name == "Attribute") && (reader.NodeType == XmlNodeType.Element)) { string attribute = reader.GetAttribute("Name"); if (!string.IsNullOrEmpty(attribute)) { qualityLevel.AddCustomAttribute(attribute, reader.GetAttribute("Value")); } } if ((reader.Name == "CustomAttributes") && (reader.NodeType == XmlNodeType.EndElement)) { return; } } } if (reader.Name == "QualityLevel" && reader.NodeType == XmlNodeType.EndElement) { return; } } } }
/// <summary> /// Adds attributes to the quality level. /// </summary> /// <param name="reader">The xml reader.</param> /// <param name="qualityLevel">The quality level.</param> private static void AddAttributes(XmlReader reader, QualityLevel qualityLevel) { if (reader.HasAttributes && reader.MoveToFirstAttribute()) { do { qualityLevel.AddAttribute(reader.Name, reader.Value); }while (reader.MoveToNextAttribute()); reader.MoveToElement(); } }
/// <summary> /// Creates a clone instance of this QualityLevel object. /// </summary> /// <returns>A copy of the QualityLevel object.</returns> public QualityLevel Clone() { QualityLevel clone = new QualityLevel(); foreach (KeyValuePair <string, string> attributeValuePair in this.Attributes) { clone.AddAttribute(attributeValuePair.Key, attributeValuePair.Value); } foreach (KeyValuePair <string, string> customAttributeValuePair in this.CustomAttributes) { clone.AddCustomAttribute(customAttributeValuePair.Key, customAttributeValuePair.Value); } return(clone); }
/// <summary> /// Creates a clone instance of this QualityLevel object. /// </summary> /// <returns>A copy of the QualityLevel object.</returns> public QualityLevel Clone() { QualityLevel clone = new QualityLevel(); foreach (KeyValuePair<string, string> attributeValuePair in this.Attributes) { clone.AddAttribute(attributeValuePair.Key, attributeValuePair.Value); } foreach (KeyValuePair<string, string> customAttributeValuePair in this.CustomAttributes) { clone.AddCustomAttribute(customAttributeValuePair.Key, customAttributeValuePair.Value); } return clone; }
/// <summary> /// Parses the manifest stream. /// </summary> /// <param name="manifestStream">The manifest stream being parsed.</param> private void ParseManifest(Stream manifestStream) { using (XmlReader reader = XmlReader.Create(manifestStream)) { if (reader.Read() && reader.IsStartElement(ManifestSmoothStreamingMediaElement)) { int majorVersion = reader.GetValueAsInt(ManifestMajorVersionAttribute).GetValueOrDefault(); int minorVersion = reader.GetValueAsInt(ManifestMinorVersionAttribute).GetValueOrDefault(); bool isLive = reader.GetValueAsBool(ManifestIsLiveAttribute).GetValueOrDefault(); int lookAheadFragmentCount = 0; int dvrWindowLength = 0; if (isLive) { lookAheadFragmentCount = reader.GetValueAsInt(ManifestLookAheadFragmentCountAttribute).GetValueOrDefault(); dvrWindowLength = reader.GetValueAsInt(ManifestDvrWindowLengthAttribute).GetValueOrDefault(); } ulong Timescale = reader.GetValueAsULong(TimeScaleAttribute).GetValueOrDefault(TicksPerSecond); ulong manifestDuration = reader.GetValueAsULong(ManifestDurationAttribute).GetValueOrDefault(); Guid protectionGuid = Guid.Empty; string protectionData = string.Empty; List <StreamInfo> streams = new List <StreamInfo>(); while (reader.Read()) { if (reader.Name == ManifestProtectionElement && reader.NodeType == XmlNodeType.Element) { reader.Read(); if (reader.Name == ManifestProtectionHeaderElement && reader.NodeType == XmlNodeType.Element) { protectionGuid = new Guid(reader.GetValue(ManifestProtectionSystemIDElement)); protectionData = reader.ReadElementContentAsString(); } } if (reader.Name == ManifestStreamIndexElement && reader.NodeType == XmlNodeType.Element) { string type = reader.GetValue(ManifestStreamIndexTypeAttribute); StreamInfo streamInfo = new StreamInfo(type); AddAttributes(reader, streamInfo); while (reader.Read()) { if (reader.Name == ManifestStreamIndexElement && reader.NodeType == XmlNodeType.EndElement) { break; } if ((reader.Name == "QualityLevel") && (reader.NodeType == XmlNodeType.Element)) { QualityLevel qualityLevel = new QualityLevel(); AddAttributes(reader, qualityLevel); AddCustomAttributes(reader, qualityLevel); streamInfo.QualityLevels.Add(qualityLevel); } if ((reader.Name == "c") && (reader.NodeType == XmlNodeType.Element)) { int? chunkId = reader.GetValueAsInt("n"); UInt64?time = reader.GetValueAsUInt64("t"); ulong? duration = reader.GetValueAsULong("d"); ulong? repetitions = reader.GetValueAsULong("r"); for (ulong i = 0; i < (repetitions.HasValue ? repetitions.Value : 1); i++) { Chunk chunk = new Chunk(chunkId, i == 0 ? time : null, duration); if (((!reader.IsEmptyElement && reader.Read()) && (reader.IsStartElement("f") && reader.Read())) && (reader.NodeType == XmlNodeType.Text)) { chunk.Value = reader.Value; } streamInfo.Chunks.Add(chunk); } } } streams.Add(streamInfo); } } streams.ToArray(); if (!isLive) { this.ManifestInfo = new ManifestInfo(majorVersion, minorVersion, manifestDuration, streams, protectionGuid, protectionData, Timescale); } else { this.ManifestInfo = new ManifestInfo(majorVersion, minorVersion, manifestDuration, isLive, lookAheadFragmentCount, dvrWindowLength, streams, protectionGuid, protectionData, Timescale); } } } }
/// <summary> /// Parses the manifest stream. /// </summary> /// <param name="manifestStream">The manifest stream being parsed.</param> private void ParseManifest(Stream manifestStream) { using (XmlReader reader = XmlReader.Create(manifestStream)) { if (reader.Read() && reader.IsStartElement(ManifestSmoothStreamingMediaElement)) { int majorVersion = reader.GetValueAsInt(ManifestMajorVersionAttribute).GetValueOrDefault(); int minorVersion = reader.GetValueAsInt(ManifestMinorVersionAttribute).GetValueOrDefault(); bool isLive = reader.GetValueAsBool(ManifestIsLiveAttribute).GetValueOrDefault(); int lookAheadFragmentCount = 0; int dvrWindowLength = 0; if (isLive) { lookAheadFragmentCount = reader.GetValueAsInt(ManifestLookAheadFragmentCountAttribute).GetValueOrDefault(); dvrWindowLength = reader.GetValueAsInt(ManifestDvrWindowLengthAttribute).GetValueOrDefault(); } ulong Timescale = reader.GetValueAsULong(TimeScaleAttribute).GetValueOrDefault(TicksPerSecond); ulong manifestDuration = reader.GetValueAsULong(ManifestDurationAttribute).GetValueOrDefault(); Guid protectionGuid = Guid.Empty; string protectionData = string.Empty; List<StreamInfo> streams = new List<StreamInfo>(); while (reader.Read()) { if (reader.Name == ManifestProtectionElement && reader.NodeType == XmlNodeType.Element) { reader.Read(); if (reader.Name == ManifestProtectionHeaderElement && reader.NodeType == XmlNodeType.Element) { protectionGuid = new Guid(reader.GetValue(ManifestProtectionSystemIDElement)); protectionData = reader.ReadElementContentAsString(); } } if (reader.Name == ManifestStreamIndexElement && reader.NodeType == XmlNodeType.Element) { string type = reader.GetValue(ManifestStreamIndexTypeAttribute); StreamInfo streamInfo = new StreamInfo(type); AddAttributes(reader, streamInfo); while (reader.Read()) { if (reader.Name == ManifestStreamIndexElement && reader.NodeType == XmlNodeType.EndElement) { break; } if ((reader.Name == "QualityLevel") && (reader.NodeType == XmlNodeType.Element)) { QualityLevel qualityLevel = new QualityLevel(); AddAttributes(reader, qualityLevel); AddCustomAttributes(reader, qualityLevel); streamInfo.QualityLevels.Add(qualityLevel); } if ((reader.Name == "c") && (reader.NodeType == XmlNodeType.Element)) { int? chunkId = reader.GetValueAsInt("n"); UInt64? time = reader.GetValueAsUInt64("t"); ulong? duration = reader.GetValueAsULong("d"); ulong? repetitions = reader.GetValueAsULong("r"); for (ulong i = 0; i < (repetitions.HasValue ? repetitions.Value : 1); i++) { Chunk chunk = new Chunk(chunkId, i == 0 ? time : null, duration); if (((!reader.IsEmptyElement && reader.Read()) && (reader.IsStartElement("f") && reader.Read())) && (reader.NodeType == XmlNodeType.Text)) { chunk.Value = reader.Value; } streamInfo.Chunks.Add(chunk); } } } streams.Add(streamInfo); } } streams.ToArray(); if (!isLive) { this.ManifestInfo = new ManifestInfo(majorVersion, minorVersion, manifestDuration, streams, protectionGuid, protectionData,Timescale); } else { this.ManifestInfo = new ManifestInfo(majorVersion, minorVersion, manifestDuration, isLive, lookAheadFragmentCount, dvrWindowLength, streams, protectionGuid, protectionData,Timescale); } } } }
/// <summary> /// Adds attributes to the quality level. /// </summary> /// <param name="reader">The xml reader.</param> /// <param name="qualityLevel">The quality level.</param> private static void AddAttributes(XmlReader reader, QualityLevel qualityLevel) { if (reader.HasAttributes && reader.MoveToFirstAttribute()) { do { qualityLevel.AddAttribute(reader.Name, reader.Value); } while (reader.MoveToNextAttribute()); reader.MoveToElement(); } }
/// <summary> /// InitializeChunks /// Initialize the chunks parameter based on the information in the manifest. /// </summary> /// <param name="stream"></param> /// <param name="selected"></param> /// <returns>true if success</returns> bool InitializeChunks(StreamInfo stream, QualityLevel selected) { ulong Bitrate = 0; string UrlTemplate = string.Empty; if ((selected != null)&&(stream!= null)) { selected.TryGetAttributeValueAsUlong("Bitrate", out Bitrate); if (Bitrate > 0) { if (stream.TryGetAttributeValueAsString("Url", out UrlTemplate)) { UrlTemplate = UrlTemplate.Replace("{bitrate}", Bitrate.ToString()); UrlTemplate = UrlTemplate.Replace("{start time}", "{start_time}"); UrlTemplate = UrlTemplate.Replace("{CustomAttributes}", "timeScale=10000000"); bool bAudio = false; bool bVideo = false; if (stream.StreamType.ToLower() == "audio") { ulong index = 0; if (SelectAudioTrackIndex < 0) { selected.TryGetAttributeValueAsUlong("Index", out index); SelectedAudioTrackIndex = (int)index; } else SelectedAudioTrackIndex = SelectAudioTrackIndex; bAudio = true; } if (stream.StreamType.ToLower() == "video") { ulong index = 0; if (SelectVideoTrackIndex < 0) { selected.TryGetAttributeValueAsUlong("Index", out index); SelectedVideoTrackIndex = (int)index; } else SelectedVideoTrackIndex = SelectVideoTrackIndex; bVideo = true; } if ((bAudio) || (bVideo)) { UInt64 time = 0; ulong duration = 0; foreach (var chunk in stream.Chunks) { if (chunk.Duration != null) duration = (ulong)chunk.Duration; else duration = 0; if (chunk.Time != null) time = (UInt64)chunk.Time; ChunkCache cc = new ChunkCache(time, duration); time += (ulong)duration; if (cc != null) { if (bAudio) this.AudioChunkList.Add(cc); if (bVideo) this.VideoChunkList.Add(cc); } } if (bAudio) { this.AudioBitrate = Bitrate; this.AudioChunks = (ulong)this.AudioChunkList.Count; this.AudioTemplateUrl = UrlTemplate; this.AudioTemplateUrlType = GetType(UrlTemplate); } if (bVideo) { this.VideoBitrate = Bitrate; this.VideoChunks = (ulong)this.VideoChunkList.Count; this.VideoTemplateUrl = UrlTemplate; this.VideoTemplateUrlType = GetType(UrlTemplate); } } return true; }; } } return false; }