ReadHeader() public static method

public static ReadHeader ( Stream s ) : Element
s Stream
return Element
 public bool TryParseContentType(byte[] header, out string content_type, out string mime_type)
 {
     try {
         using (var stream = new MemoryStream(header)) {
             var elt = Element.ReadHeader(stream);
             if (4 < elt.ID.Length || 8 < elt.Size.Length ||
                 !elt.ID.BinaryEquals(Elements.EBML))
             {
                 content_type = null;
                 mime_type    = null;
                 return(false);
             }
             elt.ReadBody(stream);
             var ebml = new EBML(elt);
             if (ebml.DocType == "webm")
             {
                 content_type = "WEBM";
                 mime_type    = "video/webm";
             }
             else
             {
                 content_type = "MKV";
                 mime_type    = "video/x-matroska";
             }
             return(true);
         }
     }
     catch (EndOfStreamException) {
         content_type = null;
         mime_type    = null;
         return(false);
     }
 }
 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) {
                }
            }
        }