public AudioTrackInfo(XmlNode element, IDictionary <string, string> streamAttributes, uint index, StreamInfo stream) : base(element, index, stream) { WaveFormatEx waveFormatEx; if (base.Attributes.ContainsKey("WaveFormatEx")) { byte[] data = Parse.HexStringAttribute(base.Attributes, "WaveFormatEx"); waveFormatEx = new WaveFormatEx(data); } else { ushort wFormatTag = Parse.UInt16Attribute(base.Attributes, "AudioTag"); ushort nChannels = Parse.UInt16Attribute(base.Attributes, "Channels"); uint nSamplesPerSec = Parse.UInt32Attribute(base.Attributes, "SamplingRate"); uint num = Parse.UInt32Attribute(base.Attributes, "Bitrate"); ushort nBlockAlign = Parse.UInt16Attribute(base.Attributes, "PacketSize"); ushort wBitsPerSample = Parse.UInt16Attribute(base.Attributes, "BitsPerSample"); byte[] decoderSpecificData = Parse.HexStringAttribute(base.Attributes, "CodecPrivateData"); waveFormatEx = new WaveFormatEx(wFormatTag, nChannels, nSamplesPerSec, num / 8u, nBlockAlign, wBitsPerSample, decoderSpecificData); } byte[] audioInfoBytes = MkvUtils.GetAudioInfoBytes( waveFormatEx.nSamplesPerSec, (ulong)waveFormatEx.nChannels, (ulong)waveFormatEx.wBitsPerSample); switch (waveFormatEx.wFormatTag) { case 353: case 354: { base.TrackEntry = new TrackEntry(TrackType.Audio, audioInfoBytes, CodecID.A_MS, waveFormatEx.GetBytes()); break; } case 255: case 5633: { base.TrackEntry = new TrackEntry(TrackType.Audio, audioInfoBytes, CodecID.A_AAC, GetAudioSpecificConfigBytes( waveFormatEx.nSamplesPerSec, (byte)waveFormatEx.nChannels)); break; } case 1: { throw new Exception("Unsupported audio format: 'LPCM'!"); } case 65534: { throw new Exception("Unsupported audio format: 'Vendor-extensible format'!"); } default: { throw new Exception("Unsupported AudioTag: '" + waveFormatEx.wFormatTag + "'"); } } if (base.Attributes.ContainsKey("Name")) { base.TrackEntry.Name = Parse.StringAttribute(streamAttributes, "Name"); } base.TrackEntry.Language = LanguageID.Hungarian; // TODO: Make this configurable. base.Description = string.Format("{0} {1} channels {2} Hz @ {3} kbps", new object[] { GetCodecNameForAudioTag(waveFormatEx.wFormatTag), waveFormatEx.nChannels, waveFormatEx.nSamplesPerSec, base.Bitrate / 1000u }); }
public string GetChunkUrl(uint bitrate, ulong startTime) { return(this.pureUrl + "/" + Parse.StringAttribute(this.Attributes, "Url") .Replace("{bitrate}", bitrate.ToString()) .Replace("{Bitrate}", bitrate.ToString()) .Replace("{start time}", startTime.ToString()) .Replace("{start_time}", startTime.ToString())); }
public static ulong UInt64Attribute(IDictionary <string, string> attributes, string key) { string text = Parse.StringAttribute(attributes, key); ulong result; if (!ulong.TryParse(text, out result)) { throw new Exception("Cannot parse the " + key + " key!"); } return(result); }
public static bool BoolAttribute(IDictionary <string, string> attributes, string key) { string text = Parse.StringAttribute(attributes, key); bool result; if (!bool.TryParse(text, out result)) { throw new Exception("Cannot parse the " + key + " key!"); } return(result); }
public static MediaStreamType MediaStreamTypeAttribute(IDictionary <string, string> attributes, string key) { switch (Parse.StringAttribute(attributes, key)) { case "video": { return(MediaStreamType.Video); } case "audio": { return(MediaStreamType.Audio); } case "text": { return(MediaStreamType.Script); } default: { throw new Exception("Cannot parse the " + key + " key!"); } } }
public static byte[] HexStringAttribute(IDictionary <string, string> attributes, string key) { return(Utils.HexDecodeString(Parse.StringAttribute(attributes, key))); }
public VideoTrackInfo(XmlNode element, IDictionary <string, string> streamAttributes, uint index, StreamInfo stream) : base(element, index, stream) { uint pixelWidth = base.Attributes.ContainsKey("MaxWidth") ? Parse.UInt32Attribute(base.Attributes, "MaxWidth") : base.Attributes.ContainsKey("Width") ? Parse.UInt32Attribute(base.Attributes, "Width") : streamAttributes.ContainsKey("MaxWidth") ? Parse.UInt32Attribute(streamAttributes, "MaxWidth") : 0u; if (pixelWidth == 0u) { throw new Exception("Missing video width attribute!"); } uint pixelHeight = base.Attributes.ContainsKey("MaxHeight") ? Parse.UInt32Attribute(base.Attributes, "MaxHeight") : base.Attributes.ContainsKey("Height") ? Parse.UInt32Attribute(base.Attributes, "Height") : streamAttributes.ContainsKey("MaxHeight") ? Parse.UInt32Attribute(streamAttributes, "MaxHeight") : 0u; if (pixelHeight == 0u) { throw new Exception("Missing video height attribute!"); } uint displayWidth = streamAttributes.ContainsKey("DisplayWidth") ? Parse.UInt32Attribute(streamAttributes, "DisplayWidth") : 0u; if (displayWidth == 0u) { displayWidth = pixelWidth; } uint displayHeight = streamAttributes.ContainsKey("DisplayHeight") ? Parse.UInt32Attribute(streamAttributes, "DisplayHeight") : 0u; if (displayHeight == 0u) { displayHeight = pixelHeight; } byte[] videoInfoBytes = MkvUtils.GetVideoInfoBytes( (ulong)pixelWidth, (ulong)pixelHeight, (ulong)displayWidth, (ulong)displayHeight); byte[] codecPrivateData = base.Attributes.ContainsKey("CodecPrivateData") ? Parse.HexStringAttribute(base.Attributes, "CodecPrivateData") : null; if (codecPrivateData == null) { throw new Exception("Missing CodecPrivateData attribute!"); } string fourcc = base.Attributes.ContainsKey("FourCC") ? Parse.StringAttribute(base.Attributes, "FourCC") : streamAttributes.ContainsKey("FourCC") ? Parse.StringAttribute(streamAttributes, "FourCC") : null; switch (fourcc) { case "WVC1": { base.TrackEntry = new TrackEntry( TrackType.Video, videoInfoBytes, CodecID.V_MS, VideoTrackInfo.GetVfWCodecPrivate( pixelWidth, pixelHeight, fourcc, codecPrivateData)); break; } case "H264": { ushort nalUnitLengthField = 4; if (base.Attributes.ContainsKey("NALUnitLengthField")) { nalUnitLengthField = Parse.UInt16Attribute(base.Attributes, "NALUnitLengthField"); } base.TrackEntry = new TrackEntry( TrackType.Video, videoInfoBytes, CodecID.V_AVC, GetAVCCodecPrivate(codecPrivateData, nalUnitLengthField)); break; } case null: { throw new Exception("Missing FourCC attribute!"); } default: { throw new Exception("Unsupported video FourCC: '" + fourcc + "'"); } } if (base.Attributes.ContainsKey("Name")) { base.TrackEntry.Name = Parse.StringAttribute(streamAttributes, "Name"); } base.TrackEntry.Language = LanguageID.Hungarian; // TODO: Make this configurable. base.Description = string.Format("{0} {1}x{2} ({3}x{4}) @ {5} kbps", new object[] { fourcc, pixelWidth, pixelHeight, displayWidth, displayHeight, base.Bitrate / 1000u }); }
private void CheckUrlAttribute() { string text = Parse.StringAttribute(this.Attributes, "Url"); string[] array = text.Split(new char[] { '/' }); if (array.Length != 2) { throw new Exception("Invalid UrlPattern!"); } string text2 = array[0]; string text3 = array[1]; array = text2.Split(new char[] { '(', ')' }); if (array.Length != 3 || array[2].Length != 0) { throw new Exception("Invalid QualityLevelsPattern!"); } if (array[0] != "QualityLevels") { throw new Exception("Invalid QualityLevelsNoun!"); } string text4 = array[1]; array = text4.Split(new char[] { ',' }); if (array.Length > 2) { throw new Exception("Invalid QualityLevelsPredicatePattern!"); } if (array[0] != "{bitrate}" && array[0] != "{Bitrate}") { throw new Exception("Missing BitrateSubstitution!"); } if (array.Length == 2 && array[1] != "{CustomAttributes}") { throw new Exception("Missing CustomAttributesSubstitution!"); } array = text3.Split(new char[] { '(', ')' }); if (array.Length != 3 || array[2].Length != 0) { throw new Exception("Invalid FragmentsPattern!"); } if (array[0] != "Fragments") { throw new Exception("Invalid FragmentsNoun!"); } string text5 = array[1]; array = text5.Split(new char[] { '=' }); if (array.Length != 2) { throw new Exception("Invalid FragmentsPatternPredicate!"); } if (this.Attributes.ContainsKey("Name")) { if (array[0] != Parse.StringAttribute(this.Attributes, "Name")) { throw new Exception("Missing TrackName!"); } } else { if (array[0] != Parse.StringAttribute(this.Attributes, "Type")) { throw new Exception("Missing TrackName!"); } } if (array[1] != "{start time}" && array[1] != "{start_time}") { throw new Exception("Missing StartTimeSubstitution!"); } }
public StreamInfo(XmlNode element, Uri manifestUri) { if (element.Name != "StreamIndex") { throw new Exception("Source element is not a(n) StreamIndex element!"); } this.Attributes = Parse.Attributes(element); this.CustomAttributes = Parse.CustomAttributes(element); this.Type = Parse.MediaStreamTypeAttribute(this.Attributes, "Type"); this.Subtype = this.Attributes.ContainsKey("Subtype") ? Parse.StringAttribute(this.Attributes, "Subtype") : ""; if (this.Attributes.ContainsKey("Url")) { this.CheckUrlAttribute(); } this.AvailableTracks = new List <TrackInfo>(); XmlNodeList xmlNodeList = element.SelectNodes("QualityLevel"); int i; for (i = 0; i < xmlNodeList.Count; ++i) { TrackInfo trackInfo; if (this.Type == MediaStreamType.Audio) { trackInfo = new AudioTrackInfo(xmlNodeList[i], this.Attributes, (uint)i, this); } else if (this.Type == MediaStreamType.Video) { trackInfo = new VideoTrackInfo(xmlNodeList[i], this.Attributes, (uint)i, this); } else { continue; } int num = 0; while (num < this.AvailableTracks.Count && this.AvailableTracks[num].Bitrate > trackInfo.Bitrate) { num++; } this.AvailableTracks.Insert(num, trackInfo); } this.ChunkList = new List <ChunkInfo>(); XmlNodeList xmlNodeList2 = element.SelectNodes("c"); ulong num2 = 0uL; for (i = 0; i < xmlNodeList2.Count; i++) { ChunkInfo chunkInfo = new ChunkInfo(xmlNodeList2[i], (uint)i, num2); this.ChunkList.Add(chunkInfo); num2 += chunkInfo.Duration; } if (this.Attributes.ContainsKey("Chunks")) { uint chunkCount = Parse.UInt32Attribute(this.Attributes, "Chunks"); if (this.ChunkList.Count > 0 && this.ChunkList.Count != chunkCount) { throw new Exception("Chunk count mismatch: c=" + this.ChunkList.Count + " chunks=" + chunkCount); } this.ChunkCount = (int)chunkCount; } else { this.ChunkCount = this.ChunkList.Count; // Can be 0 if no `<c' tags. } this.pureUrl = manifestUri.AbsoluteUri; this.pureUrl = this.pureUrl.Substring(0, this.pureUrl.LastIndexOf('/')); this.SelectedTracks = new List <TrackInfo>(); if (this.AvailableTracks.Count > 0) { this.SelectedTracks.Add(this.AvailableTracks[0]); } }