public ParsedContent Read(Stream stream) { var chunks = 0; var res = new ParsedContent(); var pos = Channel.ContentPosition; try { while (chunks<8) { var chunk = ASFChunk.Read(stream); chunks++; switch (chunk.KnownType) { case ASFChunk.ChunkType.Header: { var header = ASFHeader.Read(chunk); var info = new AtomCollection(Channel.ChannelInfo.Extra); info.SetChanInfoBitrate(header.Bitrate); if (header.Streams.Any(type => type==ASFHeader.StreamType.Video)) { info.SetChanInfoType("WMV"); info.SetChanInfoStreamType("video/x-ms-wmv"); info.SetChanInfoStreamExt(".wmv"); } else if (header.Streams.Any(type => type==ASFHeader.StreamType.Audio)) { info.SetChanInfoType("WMA"); info.SetChanInfoStreamType("audio/x-ms-wma"); info.SetChanInfoStreamExt(".wma"); } else { info.SetChanInfoType("ASF"); info.SetChanInfoStreamType("video/x-ms-asf"); info.SetChanInfoStreamExt(".asf"); } res.ChannelInfo = new ChannelInfo(info); streamIndex = Channel.GenerateStreamID(); streamOrigin = DateTime.Now; res.ContentHeader = new Content(streamIndex, TimeSpan.Zero, pos, chunk.ToByteArray()); pos += chunk.TotalLength; } break; case ASFChunk.ChunkType.Data: if (res.Contents==null) res.Contents = new System.Collections.Generic.List<Content>(); res.Contents.Add(new Content(streamIndex, DateTime.Now-streamOrigin, pos, chunk.ToByteArray())); pos += chunk.TotalLength; break; case ASFChunk.ChunkType.Unknown: break; } } } catch (EndOfStreamException) { if (chunks==0) throw; } return res; }
public void OnChannelInfo(ChannelInfo channel_info) { if (String.IsNullOrEmpty(this.Description.OutputContentType)) { Sink.OnChannelInfo(channel_info); } else { var newinfo = new AtomCollection(channel_info.Extra); newinfo.SetChanInfoType(this.Description.OutputContentType); if (!String.IsNullOrEmpty(this.Description.OutputMIMEType)) { newinfo.SetChanInfoStreamType(this.Description.OutputMIMEType); } else { newinfo.RemoveByName(Atom.PCP_CHAN_INFO_STREAMTYPE); } if (!String.IsNullOrEmpty(this.Description.OutputContentExt)) { newinfo.SetChanInfoStreamExt(this.Description.OutputContentExt); } else { newinfo.RemoveByName(Atom.PCP_CHAN_INFO_STREAMEXT); } Sink.OnChannelInfo(new ChannelInfo(newinfo)); } }
private void OnMetaData(DataMessage msg) { this.metadata = msg; var info = new AtomCollection(); info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); if (metadata.Arguments[0].Type == AMF.AMFValueType.ECMAArray || metadata.Arguments[0].Type == AMF.AMFValueType.Object) { var bitrate = 0.0; var val = metadata.Arguments[0]["maxBitrate"]; if (!AMF.AMFValue.IsNull(val)) { double maxBitrate; string maxBitrateStr = System.Text.RegularExpressions.Regex.Replace((string)val, @"([\d]+)k", "$1"); if (double.TryParse(maxBitrateStr, out maxBitrate)) { bitrate += maxBitrate; } } else if (!AMF.AMFValue.IsNull(val = metadata.Arguments[0]["videodatarate"])) { bitrate += (double)val; } if (!AMF.AMFValue.IsNull(val = metadata.Arguments[0]["audiodatarate"])) { bitrate += (double)val; } info.SetChanInfoBitrate((int)bitrate); } OnChannelInfoChanged(info); OnHeaderChanged(msg); OnContentChanged(msg); }
private void OnMetaData(DataMessage msg) { this.metadata = msg; var info = new AtomCollection(); info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); if (metadata.Arguments[0].Type==AMF.AMFValueType.ECMAArray || metadata.Arguments[0].Type==AMF.AMFValueType.Object){ var bitrate = 0.0; var val = metadata.Arguments[0]["maxBitrate"]; if (!AMF.AMFValue.IsNull(val)) { double maxBitrate; string maxBitrateStr = System.Text.RegularExpressions.Regex.Replace((string)val, @"([\d]+)k", "$1"); if (double.TryParse(maxBitrateStr, out maxBitrate)) { bitrate += maxBitrate; } } else if (!AMF.AMFValue.IsNull(val = metadata.Arguments[0]["videodatarate"])) { bitrate += (double)val; } if (!AMF.AMFValue.IsNull(val = metadata.Arguments[0]["audiodatarate"])) { bitrate += (double)val; } info.SetChanInfoBitrate((int)bitrate); } OnChannelInfoChanged(info); OnHeaderChanged(msg); OnContentChanged(msg); }
public ParsedContent Read(Stream stream) { if (stream.Length-stream.Position<=0) throw new EndOfStreamException(); var res = new ParsedContent(); var pos = Channel.ContentPosition; if (Channel.ContentHeader==null) { streamIndex = Channel.GenerateStreamID(); streamOrigin = DateTime.Now; res.ContentHeader = new Content(streamIndex, TimeSpan.Zero, pos, new byte[] { }); var channel_info = new AtomCollection(Channel.ChannelInfo.Extra); channel_info.SetChanInfoType("RAW"); channel_info.SetChanInfoStreamType("application/octet-stream"); channel_info.SetChanInfoStreamExt(""); res.ChannelInfo = new ChannelInfo(channel_info); } res.Contents = new List<Content>(); while (stream.Length-stream.Position>0) { var bytes = new byte[Math.Min(8192, stream.Length-stream.Position)]; var sz = stream.Read(bytes, 0, bytes.Length); if (sz>0) { Array.Resize(ref bytes, sz); res.Contents.Add(new Content(streamIndex, DateTime.Now-streamOrigin, pos, bytes)); pos += sz; } } return res; }
public void OnFLVHeader() { var info = new AtomCollection(); info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); OnChannelInfoChanged(info); }
static HTTPOutputStream() { var chaninfo = new AtomCollection(); chaninfo.SetChanInfoBitrate(0); chaninfo.SetChanInfoType("RAW"); chaninfo.SetChanInfoStreamType("application/octet-stream"); chaninfo.SetChanInfoStreamExt(""); }
public void OnStart() { var info = new AtomCollection(); info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); OnChannelInfoChanged(info); }
public void OnFLVHeader(FLVFileHeader header) { var info = new AtomCollection(); info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); OnChannelInfoChanged(info); }
public void OnChannelInfo(ChannelInfo channel_info) { var info = new AtomCollection(channel_info.Extra); info.SetChanInfoType("TS"); info.SetChanInfoStreamType("video/mp2t"); info.SetChanInfoStreamExt(".ts"); msgQueue.Enqueue(new ContentMessage { Type = ContentMessage.MessageType.ChannelInfo, ChannelInfo = new ChannelInfo(info) }); }
private void UpdateRecvRate(IContentSink sink, double bitrate) { if (recvRate == 0.0 || (recvRate * 1.2 < bitrate && bitrate < recvRate * 10.0)) { recvRate = bitrate; var info = new AtomCollection(Channel.ChannelInfo.Extra); info.SetChanInfoType("TS"); info.SetChanInfoStreamType("video/mp2t"); info.SetChanInfoStreamExt(".ts"); info.SetChanInfoBitrate((int)bitrate / 1000); sink.OnChannelInfo(new ChannelInfo(info)); } }
private ChannelInfo ResetContentType(ChannelInfo channel_info, Content content_header) { if (channel_info == null) { throw new ArgumentNullException("channel_info"); } var content_type = channel_info.ContentType; if (content_type == null || content_type == "UNKNOWN") { string mime_type = null; if (content_header != null && PeerCast.ContentReaderFactories.Any( factory => factory.TryParseContentType(content_header.Data, out content_type, out mime_type))) { var new_info = new AtomCollection(channel_info.Extra); new_info.SetChanInfoType(content_type); new_info.SetChanInfoStreamType(mime_type); channel_info = new ChannelInfo(new_info); } } return(channel_info); }
public ParsedContent Read(Stream stream) { var chunks = 0; var res = new ParsedContent(); var pos = Channel.ContentPosition; try { while (chunks < 8) { var chunk = ASFChunk.Read(stream); chunks++; switch (chunk.KnownType) { case ASFChunk.ChunkType.Header: { var header = ASFHeader.Read(chunk); var info = new AtomCollection(Channel.ChannelInfo.Extra); info.SetChanInfoBitrate(header.Bitrate); if (header.Streams.Any(type => type == ASFHeader.StreamType.Video)) { info.SetChanInfoType("WMV"); info.SetChanInfoStreamType("video/x-ms-wmv"); info.SetChanInfoStreamExt(".wmv"); } else if (header.Streams.Any(type => type == ASFHeader.StreamType.Audio)) { info.SetChanInfoType("WMA"); info.SetChanInfoStreamType("audio/x-ms-wma"); info.SetChanInfoStreamExt(".wma"); } else { info.SetChanInfoType("ASF"); info.SetChanInfoStreamType("video/x-ms-asf"); info.SetChanInfoStreamExt(".asf"); } res.ChannelInfo = new ChannelInfo(info); res.ContentHeader = new Content(pos, chunk.ToByteArray()); pos += chunk.TotalLength; } break; case ASFChunk.ChunkType.Data: if (res.Contents == null) { res.Contents = new System.Collections.Generic.List <Content>(); } res.Contents.Add(new Content(pos, chunk.ToByteArray())); pos += chunk.TotalLength; break; case ASFChunk.ChunkType.Unknown: break; } } } catch (EndOfStreamException) { if (chunks == 0) { throw; } } return(res); }
protected void OnPCPChanInfo(Atom atom) { var channel_info = new ChannelInfo(atom.Children); var content_type = channel_info.ContentType; if (content_type==null || content_type=="UNKNOWN") { var header = Channel.ContentHeader; string mime_type = null; if (header!=null && PeerCast.ContentReaderFactories.Any( factory => factory.TryParseContentType(header.Data, out content_type, out mime_type))) { var new_info = new AtomCollection(atom.Children); new_info.SetChanInfoType(content_type); new_info.SetChanInfoStreamType(mime_type); channel_info = new ChannelInfo(new_info); } } Channel.ChannelInfo = channel_info; BroadcastHostInfo(); }
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); 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); 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); 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()) ); 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); 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); 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()) ); position += elt.ByteSize; state = ReaderState.Timecode; } else if (elt.ID.BinaryEquals(Elements.Void) || elt.ID.BinaryEquals(Elements.CRC32)) { await elt.ReadBodyAsync(stream, cancel_token); sink.OnContent( new Content(stream_index, DateTime.Now-stream_origin, position, elt.ToArray()) ); 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); 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()) ); position += elt.ByteSize; state = ReaderState.Block; } else { await elt.ReadBodyAsync(stream, cancel_token); sink.OnContent( new Content(stream_index, DateTime.Now-stream_origin, position, elt.ToArray()) ); 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); 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()) ); position += elt.ByteSize; } else if (clusters.Last.Value.BlockID==null) { await elt.ReadBodyAsync(stream, cancel_token); sink.OnContent( new Content(stream_index, DateTime.Now-stream_origin, position, elt.ToArray()) ); position += elt.ByteSize; } else { state = ReaderState.Cluster; goto parse_retry; } break; } } catch (EndOfStreamException) { eos = true; } catch (BadDataException) { } } }
private ChannelInfo ResetContentType(ChannelInfo channel_info, Content content_header) { if (channel_info==null) throw new ArgumentNullException("channel_info"); var content_type = channel_info.ContentType; if (content_type==null || content_type=="UNKNOWN") { string mime_type = null; if (content_header!=null && PeerCast.ContentReaderFactories.Any( factory => factory.TryParseContentType(content_header.Data, out content_type, out mime_type))) { var new_info = new AtomCollection(channel_info.Extra); new_info.SetChanInfoType(content_type); new_info.SetChanInfoStreamType(mime_type); channel_info = new ChannelInfo(new_info); } } return channel_info; }
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) { } } }
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); } } streamIndex = Channel.GenerateStreamID(); streamOrigin = DateTime.Now; res.ContentHeader = new Content(streamIndex, TimeSpan.Zero, 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(streamIndex, DateTime.Now-streamOrigin, position, data)); position += data.Length; } } return res; }
public async Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token) { int streamIndex = -1; DateTime streamOrigin = DateTime.Now; long contentPosition = 0; bool eof = false; do { ASFChunk chunk = null; try { chunk = await ASFChunk.ReadAsync(stream, cancel_token).ConfigureAwait(false); } catch (EndOfStreamException) { eof = true; continue; } switch (chunk.KnownType) { case ASFChunk.ChunkType.Header: { var header = ASFHeader.Read(chunk); var info = new AtomCollection(Channel.ChannelInfo.Extra); info.SetChanInfoBitrate(header.Bitrate); if (header.Streams.Any(type => type == ASFHeader.StreamType.Video)) { info.SetChanInfoType("WMV"); info.SetChanInfoStreamType("video/x-ms-wmv"); info.SetChanInfoStreamExt(".wmv"); } else if (header.Streams.Any(type => type == ASFHeader.StreamType.Audio)) { info.SetChanInfoType("WMA"); info.SetChanInfoStreamType("audio/x-ms-wma"); info.SetChanInfoStreamExt(".wma"); } else { info.SetChanInfoType("ASF"); info.SetChanInfoStreamType("video/x-ms-asf"); info.SetChanInfoStreamExt(".asf"); } sink.OnChannelInfo(new ChannelInfo(info)); streamIndex = Channel.GenerateStreamID(); streamOrigin = DateTime.Now; contentPosition = 0; var data = chunk.ToByteArray(); sink.OnContentHeader(new Content(streamIndex, TimeSpan.Zero, contentPosition, data, PCPChanPacketContinuation.None)); contentPosition += data.Length; break; } case ASFChunk.ChunkType.Data: { var data = chunk.ToByteArray(); sink.OnContent( new Content(streamIndex, DateTime.Now - streamOrigin, contentPosition, chunk.ToByteArray(), PCPChanPacketContinuation.None) ); contentPosition += data.Length; } break; case ASFChunk.ChunkType.Unknown: break; } } while (!eof); }
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 ParsedContent Read(Stream stream) { var res = new ParsedContent(); var info = new AtomCollection(Channel.ChannelInfo.Extra); var processed = false; var eos = false; while (!eos) { var start_pos = stream.Position; try { switch (state) { case ReaderState.Header: { var bin = ReadBytes(stream, 13); var header = new FileHeader(bin); if (header.IsValid) { Logger.Info("FLV Header found"); fileHeader = header; bin = header.Binary; res.ContentHeader = new Content(position, bin); res.Contents = null; info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); res.ChannelInfo = new ChannelInfo(info); position = bin.Length; tags.Clear(); state = ReaderState.Body; } else { throw new BadDataException(); } } break; case ReaderState.Body: { var bin = ReadBytes(stream, 11); var read_valid = false; var body = new FLVTag(bin); if (body.IsValidHeader) { body.ReadBody(stream); body.ReadFooter(stream); if (body.IsValidFooter) { read_valid = true; bin = body.Binary; if (res.Contents == null) { res.Contents = new List <Content>(); } res.Contents.Add(new Content(position, bin)); tags.AddLast(new TagDesc { Timestamp = body.Timestamp / 1000.0, DataSize = body.DataSize }); var timespan = tags.Last.Value.Timestamp - tags.First.Value.Timestamp; if (timespan >= 30.0) { var sz = tags.Take(tags.Count - 1).Sum(t => t.DataSize); info.SetChanInfoBitrate((int)(sz * 8 / timespan + 900) / 1000); res.ChannelInfo = new ChannelInfo(info); while (tags.Count > 1) { tags.RemoveFirst(); } } position += bin.Length; } } if (!read_valid) { stream.Position = start_pos; var header = new FileHeader(ReadBytes(stream, 13)); if (header.IsValid) { Logger.Info("New FLV Header found"); read_valid = true; fileHeader = header; bin = header.Binary; res.ContentHeader = new Content(0, bin); res.Contents = null; info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); res.ChannelInfo = new ChannelInfo(info); tags.Clear(); position = bin.Length; } } if (!read_valid) { throw new BadDataException(); } } break; } processed = true; } catch (EndOfStreamException) { if (!processed) { throw; } stream.Position = start_pos; eos = true; } catch (BadDataException) { stream.Position = start_pos + 1; } } return(res); }
public ParsedContent Read(Stream stream) { var res = new ParsedContent(); var info = new AtomCollection(Channel.ChannelInfo.Extra); var processed = false; var eos = false; while (!eos) { var start_pos = stream.Position; try { switch (state) { case ReaderState.Header: { var bin = ReadBytes(stream, 13); var header = new FileHeader(bin); if (header.IsValid) { Logger.Info("FLV Header found"); fileHeader = header; bin = header.Binary; res.ContentHeader = new Content(position, bin); res.Contents = null; info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); res.ChannelInfo = new ChannelInfo(info); position = bin.Length; tags.Clear(); state = ReaderState.Body; } else { throw new BadDataException(); } } break; case ReaderState.Body: { var bin = ReadBytes(stream, 11); var read_valid = false; var body = new FLVTag(bin); if (body.IsValidHeader) { body.ReadBody(stream); body.ReadFooter(stream); if (body.IsValidFooter) { read_valid = true; bin = body.Binary; if (res.Contents==null) res.Contents = new List<Content>(); res.Contents.Add(new Content(position, bin)); tags.AddLast(new TagDesc { Timestamp=body.Timestamp/1000.0, DataSize=body.DataSize }); var timespan = tags.Last.Value.Timestamp-tags.First.Value.Timestamp; if (timespan>=30.0) { var sz = tags.Take(tags.Count-1).Sum(t => t.DataSize); info.SetChanInfoBitrate((int)(sz*8/timespan+900)/1000); res.ChannelInfo = new ChannelInfo(info); while (tags.Count>1) tags.RemoveFirst(); } position += bin.Length; } } if (!read_valid) { stream.Position = start_pos; var header = new FileHeader(ReadBytes(stream, 13)); if (header.IsValid) { Logger.Info("New FLV Header found"); read_valid = true; fileHeader = header; bin = header.Binary; res.ContentHeader = new Content(0, bin); res.Contents = null; info.SetChanInfoType("FLV"); info.SetChanInfoStreamType("video/x-flv"); info.SetChanInfoStreamExt(".flv"); res.ChannelInfo = new ChannelInfo(info); tags.Clear(); position = bin.Length; } } if (!read_valid) throw new BadDataException(); } break; } processed = true; } catch (EndOfStreamException) { if (!processed) throw; stream.Position = start_pos; eos = true; } catch (BadDataException) { stream.Position = start_pos+1; } } return res; }