public static ReadUInt ( Stream s, long len ) : long | ||
s | Stream | |
len | long | |
Résultat | long |
public EBML(Element element) : this() { this.Element = element; using (var s = new MemoryStream(this.Element.Data)) { while (s.Position < s.Length) { var elt = Element.ReadHeader(s); if (elt.ID.BinaryEquals(Elements.EBMLVersion)) { this.Version = (int)Element.ReadUInt(s, elt.Size.Value); } else if (elt.ID.BinaryEquals(Elements.EBMLReadVersion)) { this.ReadVersion = (int)Element.ReadUInt(s, elt.Size.Value); } else if (elt.ID.BinaryEquals(Elements.EBMLMaxIDLength)) { this.MaxIDLength = (int)Element.ReadUInt(s, elt.Size.Value); } else if (elt.ID.BinaryEquals(Elements.EBMLMaxSizeLength)) { this.MaxSizeLength = (int)Element.ReadUInt(s, elt.Size.Value); } else if (elt.ID.BinaryEquals(Elements.DocType)) { this.DocType = Element.ReadString(s, elt.Size.Value); } else if (elt.ID.BinaryEquals(Elements.DocTypeVersion)) { this.DocTypeVersion = (int)Element.ReadUInt(s, elt.Size.Value); } else if (elt.ID.BinaryEquals(Elements.DocTypeReadVersion)) { this.DocTypeReadVersion = (int)Element.ReadUInt(s, elt.Size.Value); } else { elt.ReadBody(s); } } } }
public void AddHeader(Element elt) { if (elt.ID.BinaryEquals(Elements.Info)) { var s = new MemoryStream(elt.Data); while (s.Position < s.Length) { var child = Element.ReadHeader(s); if (child.ID.BinaryEquals(Elements.TimecodeScale)) { this.TimecodeScale = Element.ReadUInt(s, child.Size.Value) * 1.0; } else { child.ReadBody(s); } } } HeaderElements.Add(elt); }
public ParsedContent Read(Stream stream) { var res = new ParsedContent(); var bodies = new List <Element>(); var info = new AtomCollection(Channel.ChannelInfo.Extra); var processed = false; var eos = false; while (!eos) { var start_pos = stream.Position; try { var elt = Element.ReadHeader(stream); if (ebml.MaxIDLength < elt.ID.Length || ebml.MaxSizeLength < elt.Size.Length) { throw new BadDataException(); } switch (state) { case ReaderState.EBML: if (elt.ID.BinaryEquals(Elements.EBML)) { elt.ReadBody(stream); ebml = new EBML(elt); state = ReaderState.Segment; } else { throw new BadDataException(); } break; case ReaderState.Segment: if (elt.ID.BinaryEquals(Elements.Segment)) { segment = new Segment(elt); state = ReaderState.EndOfHeader; } else if (elt.ID.BinaryEquals(Elements.EBML)) { stream.Position = elt.Position; state = ReaderState.EBML; continue; } else if (elt.ID.BinaryEquals(Elements.Void) || elt.ID.BinaryEquals(Elements.CRC32)) { elt.ReadBody(stream); } else { throw new BadDataException(); } break; case ReaderState.EndOfHeader: if (elt.ID.BinaryEquals(Elements.Segment)) { stream.Position = elt.Position; state = ReaderState.Segment; continue; } else if (elt.ID.BinaryEquals(Elements.EBML)) { stream.Position = elt.Position; state = ReaderState.EBML; continue; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { stream.Position = elt.Position; state = ReaderState.Cluster; clusters.Clear(); MemoryStream header; using (header = new MemoryStream()) { ebml.Element.Write(header); segment.Element.Write(header); foreach (var c in segment.HeaderElements) { c.Write(header); } } res.ContentHeader = new Content(0, header.ToArray()); if (ebml.DocType == "webm") { info.SetChanInfoType("WEBM"); info.SetChanInfoStreamType("video/webm"); info.SetChanInfoStreamExt(".webm"); } else { info.SetChanInfoType("MKV"); info.SetChanInfoStreamType("video/x-matroska"); info.SetChanInfoStreamExt(".mkv"); } res.ChannelInfo = new ChannelInfo(info); } else { elt.ReadBody(stream); segment.AddHeader(elt); } break; case ReaderState.Cluster: if (elt.ID.BinaryEquals(Elements.Segment)) { stream.Position = elt.Position; state = ReaderState.Segment; continue; } else if (elt.ID.BinaryEquals(Elements.EBML)) { stream.Position = elt.Position; state = ReaderState.EBML; continue; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { if (clusters.Count > 0) { var timespan = clusters.Sum(c => c.Timespan); if (timespan >= 30.0) { var sz = clusters.Sum(c => c.Timespan > 0 ? c.BlockSize : 0); var kbps = (int)((sz * 8 / timespan + 900) / 1000.0); info.SetChanInfoBitrate(kbps); res.ChannelInfo = new ChannelInfo(info); while (clusters.Count > 1) { clusters.RemoveFirst(); } } } var cluster = new Cluster(elt); clusters.AddLast(cluster); bodies.Add(elt); state = ReaderState.Timecode; } else if (elt.ID.BinaryEquals(Elements.Void) || elt.ID.BinaryEquals(Elements.CRC32)) { elt.ReadBody(stream); bodies.Add(elt); } else { throw new BadDataException(); } break; case ReaderState.Timecode: if (elt.ID.BinaryEquals(Elements.Segment)) { stream.Position = elt.Position; state = ReaderState.Segment; continue; } else if (elt.ID.BinaryEquals(Elements.EBML)) { stream.Position = elt.Position; state = ReaderState.EBML; continue; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { stream.Position = elt.Position; state = ReaderState.Cluster; continue; } else if (elt.ID.BinaryEquals(Elements.Timecode)) { elt.ReadBody(stream); if (clusters.Last != null) { clusters.Last.Value.Timecode = Element.ReadUInt(new MemoryStream(elt.Data), elt.Data.Length) * (segment.TimecodeScale / 1000000000.0); if (clusters.Count > 1) { clusters.Last.Previous.Value.Timespan = clusters.Last.Value.Timecode - clusters.Last.Previous.Value.Timecode; } } bodies.Add(elt); state = ReaderState.Block; } else if (elt.ID.BinaryEquals(Elements.SimpleBlock) || elt.ID.BinaryEquals(Elements.BlockGroup)) { stream.Position = elt.Position; state = ReaderState.Block; continue; } else { elt.ReadBody(stream); bodies.Add(elt); } break; case ReaderState.Block: if (elt.ID.BinaryEquals(Elements.Segment)) { stream.Position = elt.Position; state = ReaderState.Segment; continue; } else if (elt.ID.BinaryEquals(Elements.EBML)) { stream.Position = elt.Position; state = ReaderState.EBML; continue; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { stream.Position = elt.Position; state = ReaderState.Cluster; continue; } else if ((elt.ID.BinaryEquals(Elements.SimpleBlock) || elt.ID.BinaryEquals(Elements.BlockGroup)) && (clusters.Last.Value.BlockID == null || elt.ID.BinaryEquals(clusters.Last.Value.BlockID))) { elt.ReadBody(stream); clusters.Last.Value.BlockSize += elt.Size.Value; clusters.Last.Value.BlockID = elt.ID.Binary; bodies.Add(elt); } else if (clusters.Last.Value.BlockID == null) { elt.ReadBody(stream); bodies.Add(elt); } else { stream.Position = elt.Position; state = ReaderState.Cluster; continue; } break; } processed = true; } catch (EndOfStreamException) { if (!processed) { throw; } stream.Position = start_pos; eos = true; } catch (BadDataException) { stream.Position = start_pos + 1; } } if (res.ContentHeader != null) { position = res.ContentHeader.Position + res.ContentHeader.Data.Length; } if (bodies.Count > 0) { res.Contents = new List <Content>(); foreach (var body in bodies) { MemoryStream s; using (s = new MemoryStream()) { body.Write(s); } var data = s.ToArray(); res.Contents.Add(new Content(position, data)); position += data.Length; } } return(res); }
public async Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token) { var state = ReaderState.EBML; var position = 0L; var stream_index = -1; var stream_origin = DateTime.Now; var timecode_scale = 1000000.0; var ebml = new EBML(); var clusters = new LinkedList <Cluster>(); var headers = new List <Element>(); var eos = false; while (!eos) { try { var elt = await Element.ReadHeaderAsync(stream, cancel_token).ConfigureAwait(false); if (ebml.MaxIDLength < elt.ID.Length || ebml.MaxSizeLength < elt.Size.Length) { throw new BadDataException(); } parse_retry: switch (state) { case ReaderState.EBML: if (elt.ID.BinaryEquals(Elements.EBML)) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); headers.Clear(); headers.Add(elt); ebml = new EBML(elt); state = ReaderState.Segment; } else { throw new BadDataException(); } break; case ReaderState.Segment: if (elt.ID.BinaryEquals(Elements.Segment)) { headers.Add(elt); state = ReaderState.EndOfHeader; } else if (elt.ID.BinaryEquals(Elements.EBML)) { state = ReaderState.EBML; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Void) || elt.ID.BinaryEquals(Elements.CRC32)) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); headers.Add(elt); } else { throw new BadDataException(); } break; case ReaderState.EndOfHeader: if (elt.ID.BinaryEquals(Elements.Segment)) { state = ReaderState.Segment; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.EBML)) { state = ReaderState.EBML; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { clusters.Clear(); MemoryStream header; using (header = new MemoryStream()) { foreach (var c in headers) { c.Write(header); } } headers.Clear(); stream_index = Channel.GenerateStreamID(); stream_origin = DateTime.Now; position = 0; sink.OnContentHeader( new Content(stream_index, TimeSpan.Zero, 0, header.ToArray(), PCPChanPacketContinuation.None) ); position += header.ToArray().LongLength; var info = new AtomCollection(); if (ebml.DocType == "webm") { info.SetChanInfoType("WEBM"); info.SetChanInfoStreamType("video/webm"); info.SetChanInfoStreamExt(".webm"); } else { info.SetChanInfoType("MKV"); info.SetChanInfoStreamType("video/x-matroska"); info.SetChanInfoStreamExt(".mkv"); } sink.OnChannelInfo(new ChannelInfo(info)); state = ReaderState.Cluster; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Info)) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); var s = new MemoryStream(elt.Data); while (s.Position < s.Length) { var child = Element.ReadHeader(s); if (child.ID.BinaryEquals(Elements.TimecodeScale)) { timecode_scale = Element.ReadUInt(s, child.Size.Value) * 1.0; } else { child.ReadBody(s); } } headers.Add(elt); } else { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); headers.Add(elt); } break; case ReaderState.Cluster: if (elt.ID.BinaryEquals(Elements.Segment)) { state = ReaderState.Segment; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.EBML)) { state = ReaderState.EBML; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { if (clusters.Count > 0) { var timespan = clusters.Sum(c => c.Timespan); if (timespan >= 30.0) { var sz = clusters.Sum(c => c.Timespan > 0 ? c.BlockSize : 0); var kbps = (int)((sz * 8 / timespan + 900) / 1000.0); var info = new AtomCollection(); info.SetChanInfoBitrate(kbps); sink.OnChannelInfo(new ChannelInfo(info)); while (clusters.Count > 1) { clusters.RemoveFirst(); } } } var cluster = new Cluster(elt); clusters.AddLast(cluster); sink.OnContent( new Content(stream_index, DateTime.Now - stream_origin, position, elt.ToArray(), PCPChanPacketContinuation.None) ); position += elt.ByteSize; state = ReaderState.Timecode; } else if (elt.ID.BinaryEquals(Elements.Void) || elt.ID.BinaryEquals(Elements.CRC32)) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); sink.OnContent( new Content(stream_index, DateTime.Now - stream_origin, position, elt.ToArray(), PCPChanPacketContinuation.None) ); position += elt.ByteSize; } else { throw new BadDataException(); } break; case ReaderState.Timecode: if (elt.ID.BinaryEquals(Elements.Segment)) { state = ReaderState.Segment; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.EBML)) { state = ReaderState.EBML; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { state = ReaderState.Cluster; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.SimpleBlock) || elt.ID.BinaryEquals(Elements.BlockGroup)) { state = ReaderState.Block; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Timecode)) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); if (clusters.Last != null) { clusters.Last.Value.Timecode = Element.ReadUInt(new MemoryStream(elt.Data), elt.Data.Length) * (timecode_scale / 1000000000.0); if (clusters.Count > 1) { clusters.Last.Previous.Value.Timespan = clusters.Last.Value.Timecode - clusters.Last.Previous.Value.Timecode; } } sink.OnContent( new Content(stream_index, DateTime.Now - stream_origin, position, elt.ToArray(), PCPChanPacketContinuation.None) ); position += elt.ByteSize; state = ReaderState.Block; } else { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); sink.OnContent( new Content(stream_index, DateTime.Now - stream_origin, position, elt.ToArray(), PCPChanPacketContinuation.None) ); position += elt.ByteSize; } break; case ReaderState.Block: if (elt.ID.BinaryEquals(Elements.Segment)) { state = ReaderState.Segment; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.EBML)) { state = ReaderState.EBML; goto parse_retry; } else if (elt.ID.BinaryEquals(Elements.Cluster)) { state = ReaderState.Cluster; goto parse_retry; } else if ((elt.ID.BinaryEquals(Elements.SimpleBlock) || elt.ID.BinaryEquals(Elements.BlockGroup)) && (clusters.Last.Value.BlockID == null || elt.ID.BinaryEquals(clusters.Last.Value.BlockID))) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); clusters.Last.Value.BlockSize += elt.Size.Value; clusters.Last.Value.BlockID = elt.ID.Binary; sink.OnContent( new Content(stream_index, DateTime.Now - stream_origin, position, elt.ToArray(), PCPChanPacketContinuation.None) ); position += elt.ByteSize; } else if (clusters.Last.Value.BlockID == null) { await elt.ReadBodyAsync(stream, cancel_token).ConfigureAwait(false); sink.OnContent( new Content(stream_index, DateTime.Now - stream_origin, position, elt.ToArray(), PCPChanPacketContinuation.None) ); position += elt.ByteSize; } else { state = ReaderState.Cluster; goto parse_retry; } break; } } catch (EndOfStreamException) { eos = true; } catch (BadDataException) { } } }