public FLVContentBuffer( Channel target_channel, IContentSink content_sink) { this.TargetChannel = target_channel; this.ContentSink = new BufferedContentSink(content_sink); }
public void AddContentSink(IContentSink sink) { ReplaceCollection(ref contentSinks, orig => { var new_collection = new List <IContentSink>(orig); new_collection.Add(sink); return(new_collection); }); var header = contentHeader; if (header != null) { sink.OnContentHeader(header); var channel_info = ChannelInfo; if (channel_info != null) { sink.OnChannelInfo(channel_info); } var channel_track = ChannelTrack; if (channel_track != null) { sink.OnChannelTrack(channel_track); } var contents = Contents.GetNewerContents(header.Stream, header.Timestamp, header.Position); foreach (var content in contents) { sink.OnContent(content); } } }
public async Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token) { long pos = 0; var streamIndex = Channel.GenerateStreamID(); var streamOrigin = DateTime.Now; sink.OnContentHeader(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(""); sink.OnChannelInfo(new ChannelInfo(channel_info)); bool eof = false; do { var buf = new byte[8192]; var sz = await stream.ReadAsync(buf, 0, buf.Length, cancel_token).ConfigureAwait(false); if (sz > 0) { sink.OnContent(new Content(streamIndex, DateTime.Now - streamOrigin, pos, buf.Take(sz).ToArray())); pos += sz; } else { eof = true; } } while (!eof); }
public IDisposable AddContentSink(IContentSink sink, long requestPos) { ReplaceCollection(ref contentSinks, orig => orig.Add(sink)); var header = contentHeader; if (header != null) { var channel_info = ChannelInfo; if (channel_info != null) { sink.OnChannelInfo(channel_info); } var channel_track = ChannelTrack; if (channel_track != null) { sink.OnChannelTrack(channel_track); } sink.OnContentHeader(header); var contents = Contents.GetFirstContents(header.Stream, header.Timestamp, header.Position); foreach (var content in contents) { if (header.Position >= requestPos || content.Position >= requestPos) { sink.OnContent(content); } } } return(new ContentSinkSubscription(this, sink)); }
public bool RemoveContentSink(IContentSink sink) { var sinks = contentSinks; ReplaceCollection(ref contentSinks, orig => orig.Remove(sink)); return(sinks.Length != contentSinks.Length); }
public FLVContentBuffer( Channel target_channel, IContentSink content_sink) { this.TargetChannel = target_channel; this.ContentSink = content_sink; this.flushTimer.Start(); }
public PCPSourceConnection( PeerCast peercast, Channel channel, Uri source_uri, RemoteHostStatus remote_type) : base(peercast, channel, source_uri) { remoteType = remote_type; contentSink = new AsynchronousContentSink(new ChannelContentSink(channel, true)); }
public bool RemoveContentSink(IContentSink sink) { bool removed = false; ReplaceCollection(ref contentSinks, orig => { var new_collection = new List <IContentSink>(orig); removed = new_collection.Remove(sink); return(new_collection); }); return(removed); }
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)); } }
protected override Task OnStarted(CancellationToken cancel_token) { if (this.Channel != null) { string filters; sink = this; if (request.Parameters.TryGetValue("filters", out filters)) { sink = filters.Split(',') .Select(name => PeerCast.ContentFilters.FirstOrDefault(filter => filter.Name.ToLowerInvariant() == name.ToLowerInvariant())) .Where(filter => filter != null) .Aggregate(sink, (r, filter) => filter.Activate(r)); } this.Channel.AddContentSink(sink); } return(base.OnStarted(cancel_token)); }
public IContentSink Activate(IContentSink sink) { return(new DummyContentFilterSink(sink)); }
public async Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token) { int streamIndex = -1; long contentPosition = 0; DateTime streamOrigin = DateTime.Now; DateTime latestContentTime = DateTime.Now; byte[] bytes188 = new byte[188]; byte[] latestHead = new byte[0]; byte[] contentData = null; streamIndex = Channel.GenerateStreamID(); streamOrigin = DateTime.Now; sink.OnContentHeader(new Content(streamIndex, TimeSpan.Zero, contentPosition, new byte[] {}, PCPChanPacketContinuation.None)); try { while (!cancel_token.IsCancellationRequested) { bytes188 = await stream.ReadBytesAsync(188, cancel_token).ConfigureAwait(false); TSPacket packet = new TSPacket(bytes188); if (packet.sync_byte != 0x47) { throw new Exception(); } if (packet.payload_unit_start_indicator > 0) { if (packet.PID == patID) { pmtID = packet.PMTID; head = new MemoryStream(); if (!addHead(bytes188)) { throw new Exception(); } continue; } if (packet.PID == pmtID) { var pmt = new ProgramMapTable(packet, bytes188); pcrPID = pmt.PCRPID; if (!addHead(bytes188)) { throw new Exception(); } head.Close(); byte[] newHead = head.ToArray(); if (!Enumerable.SequenceEqual(newHead, latestHead)) { streamIndex = Channel.GenerateStreamID(); contentPosition = 0; sink.OnContentHeader(new Content(streamIndex, DateTime.Now - streamOrigin, contentPosition, newHead, PCPChanPacketContinuation.None)); contentPosition += newHead.Length; latestHead = newHead; } continue; } if (packet.PID == pcrPID && packet.program_clock_reference > 0.0) { if (packet.program_clock_reference < rateCounter.lastPCR) { rateCounter.lastPCR = packet.program_clock_reference; rateCounter.byteCount = 0; recvRate = 0.0; } else if (rateCounter.lastPCR + 10.0 < packet.program_clock_reference) { var bitrate = 8 * rateCounter.byteCount / (packet.program_clock_reference - rateCounter.lastPCR); UpdateRecvRate(sink, bitrate); rateCounter.lastPCR = packet.program_clock_reference; rateCounter.byteCount = 0; } } if ((DateTime.Now - latestContentTime).Milliseconds > 50) { TryParseContent(packet, out contentData); if (contentData != null) { sink.OnContent(new Content(streamIndex, DateTime.Now - streamOrigin, contentPosition, contentData, PCPChanPacketContinuation.None)); contentPosition += contentData.Length; latestContentTime = DateTime.Now; } } } if (!addCache(bytes188)) { throw new Exception(); } rateCounter.byteCount += 188; } } catch (EndOfStreamException) { } catch (Exception) { } }
public ContentSinkSubscription(Channel channel, IContentSink sink) { this.channel = channel; this.sink = sink; }
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) { } } }
public IDisposable AddContentSink(IContentSink sink) { return(AddContentSink(sink, -1)); }
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 AsynchronousContentSink(IContentSink target_sink) { this.TargetSink = target_sink; }
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 FLVToTSContentFilterSink(IContentSink sink) { processorTask = ProcessMessagesAsync(sink, CancellationToken.None); }
public BufferedContentSink(IContentSink base_sink) { this.BaseSink = base_sink; this.LastContent = null; }
public IContentSink Activate(IContentSink sink) { return(new FLVToTSContentFilterSink(sink)); }
public DummyContentFilterSink(IContentSink sink) { targetSink = sink; }
private async Task ProcessMessagesAsync(IContentSink targetSink, CancellationToken cancellationToken) { var bufferStream = new MemoryStream(); var context = new FLVToMPEG2TS.Context(bufferStream); var contentBuffer = new MemoryStream(); var fileParser = new FLVFileParser(); var msg = await msgQueue.DequeueAsync(cancellationToken).ConfigureAwait(false); while (msg.Type != ContentMessage.MessageType.Stop) { switch (msg.Type) { case ContentMessage.MessageType.ChannelInfo: targetSink.OnChannelInfo(msg.ChannelInfo); break; case ContentMessage.MessageType.ChannelTrack: targetSink.OnChannelTrack(msg.ChannelTrack); break; case ContentMessage.MessageType.ContentHeader: { var buffer = contentBuffer; var pos = buffer.Position; buffer.Seek(0, SeekOrigin.End); buffer.Write(msg.Content.Data.Span); buffer.Position = pos; fileParser.Read(buffer, context); if (buffer.Position != 0) { var new_buf = new MemoryStream(); var trim_pos = buffer.Position; buffer.Close(); var buf = buffer.ToArray(); new_buf.Write(buf, (int)trim_pos, (int)(buf.Length - trim_pos)); new_buf.Position = 0; contentBuffer = new_buf; } if (bufferStream.Position != 0) { targetSink.OnContentHeader( new Content( msg.Content.Stream, msg.Content.Timestamp, msg.Content.Position, bufferStream.ToArray(), msg.Content.ContFlag ) ); bufferStream.SetLength(0); } } break; case ContentMessage.MessageType.ContentBody: { var buffer = contentBuffer; var pos = buffer.Position; buffer.Seek(0, SeekOrigin.End); buffer.Write(msg.Content.Data.Span); buffer.Position = pos; fileParser.Read(buffer, context); if (buffer.Position != 0) { var new_buf = new MemoryStream(); var trim_pos = buffer.Position; buffer.Close(); var buf = buffer.ToArray(); new_buf.Write(buf, (int)trim_pos, (int)(buf.Length - trim_pos)); new_buf.Position = 0; contentBuffer = new_buf; } if (bufferStream.Position != 0) { targetSink.OnContent( new Content( msg.Content.Stream, msg.Content.Timestamp, msg.Content.Position, bufferStream.ToArray(), msg.Content.ContFlag ) ); bufferStream.SetLength(0); } } break; } msg = await msgQueue.DequeueAsync(cancellationToken).ConfigureAwait(false); } targetSink.OnStop(msg.StopReason); }
public IContentSink Activate(IContentSink sink) { return(new CustomFilterContentSink(this.Description, sink)); }
public Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token) { var buffered_sink = new FLVContentBuffer(this.Channel, sink); return(fileParser.ReadAsync(stream, buffered_sink, cancel_token)); }
public CustomFilterContentSink(CustomFilterDescription desc, IContentSink sink) { this.Description = desc; this.Sink = sink; }
public async Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token) { var buffered_sink = new FLVContentBuffer(this.Channel, sink); await fileParser.ReadAsync(stream, buffered_sink, cancel_token); }