예제 #1
0
 public FLVContentBuffer(
     Channel target_channel,
     IContentSink content_sink)
 {
     this.TargetChannel = target_channel;
     this.ContentSink   = new BufferedContentSink(content_sink);
 }
예제 #2
0
        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);
                }
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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));
        }
예제 #5
0
        public bool RemoveContentSink(IContentSink sink)
        {
            var sinks = contentSinks;

            ReplaceCollection(ref contentSinks, orig => orig.Remove(sink));
            return(sinks.Length != contentSinks.Length);
        }
예제 #6
0
 public FLVContentBuffer(
     Channel target_channel,
     IContentSink content_sink)
 {
     this.TargetChannel = target_channel;
     this.ContentSink   = content_sink;
     this.flushTimer.Start();
 }
예제 #7
0
 public FLVContentBuffer(
   Channel target_channel,
   IContentSink content_sink)
 {
   this.TargetChannel = target_channel;
   this.ContentSink   = content_sink;
   this.flushTimer.Start();
 }
예제 #8
0
 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));
 }
예제 #9
0
        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);
        }
예제 #10
0
        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));
            }
        }
예제 #11
0
 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));
 }
예제 #12
0
 public IContentSink Activate(IContentSink sink)
 {
     return(new DummyContentFilterSink(sink));
 }
예제 #13
0
        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)
            { }
        }
예제 #14
0
 public ContentSinkSubscription(Channel channel, IContentSink sink)
 {
     this.channel = channel;
     this.sink    = sink;
 }
예제 #15
0
    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) {
        }
      }

    }
예제 #16
0
 public IDisposable AddContentSink(IContentSink sink)
 {
     return(AddContentSink(sink, -1));
 }
예제 #17
0
        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;
 }
예제 #19
0
        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);
        }
예제 #20
0
 public FLVToTSContentFilterSink(IContentSink sink)
 {
     processorTask = ProcessMessagesAsync(sink, CancellationToken.None);
 }
예제 #21
0
 public BufferedContentSink(IContentSink base_sink)
 {
     this.BaseSink    = base_sink;
     this.LastContent = null;
 }
예제 #22
0
 public IContentSink Activate(IContentSink sink)
 {
     return(new FLVToTSContentFilterSink(sink));
 }
예제 #23
0
 public DummyContentFilterSink(IContentSink sink)
 {
     targetSink = sink;
 }
예제 #24
0
            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);
            }
예제 #25
0
 public IContentSink Activate(IContentSink sink)
 {
     return(new CustomFilterContentSink(this.Description, sink));
 }
예제 #26
0
        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));
        }
예제 #27
0
 public BufferedContentSink(IContentSink base_sink)
 {
   this.BaseSink = base_sink;
   this.LastContent = null;
 }
예제 #28
0
 public CustomFilterContentSink(CustomFilterDescription desc, IContentSink sink)
 {
     this.Description = desc;
     this.Sink        = sink;
 }
예제 #29
0
 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);
 }