예제 #1
0
        public async Task Play(
            [FromOptionalArgument] string streamName,
            [FromOptionalArgument] double start    = -1,
            [FromOptionalArgument] double duration = -1,
            [FromOptionalArgument] bool reset      = false)
        {
            _recordFile = new FileStream(_recordService.GetRecordFilename(streamName) + ".flv", FileMode.Open, FileAccess.Read);
            await FlvDemuxer.AttachStream(_recordFile);

            var resetData = new AmfObject
            {
                { "level", "status" },
                { "code", "NetStream.Play.Reset" },
                { "description", "Resetting and playing stream." },
                { "details", streamName }
            };
            var resetStatus = RtmpSession.CreateCommandMessage <OnStatusCommandMessage>();

            resetStatus.InfoObject = resetData;
            await MessageStream.SendMessageAsync(ChunkStream, resetStatus);

            var startData = new AmfObject
            {
                { "level", "status" },
                { "code", "NetStream.Play.Start" },
                { "description", "Started playing." },
                { "details", streamName }
            };

            var startStatus = RtmpSession.CreateCommandMessage <OnStatusCommandMessage>();

            startStatus.InfoObject = startData;
            await MessageStream.SendMessageAsync(ChunkStream, startStatus);

            var bandwidthLimit = new WindowAcknowledgementSizeMessage()
            {
                WindowSize = 500 * 1024
            };
            await RtmpSession.ControlMessageStream.SendMessageAsync(RtmpSession.ControlChunkStream, bandwidthLimit);

            VideoChunkStream = RtmpSession.CreateChunkStream();
            AudioChunkStream = RtmpSession.CreateChunkStream();

            var cts = new CancellationTokenSource();

            _playCts?.Dispose();
            _playCts = cts;
            start    = Math.Max(start, 0);
            await SeekAndPlay(start / 1000, cts.Token);
        }
예제 #2
0
        private async Task SeekAndPlay(double milliSeconds, CancellationToken ct)
        {
            await _playLock.WaitAsync();

            Interlocked.Exchange(ref _playing, 1);
            try
            {
                _recordFile.Seek(9, SeekOrigin.Begin);
                FlvDemuxer.SeekNoLock(milliSeconds, _metaData == null ? null : _metaData.Data[2] as Dictionary <string, object>, ct);
                await StartPlayNoLock(ct);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                Interlocked.Exchange(ref _playing, 0);
                _playLock.Release();
            }
        }
예제 #3
0
        private async void HandleVideoMessage(VideoMessage message)
        {
            try
            {
                _currentTimestamp = Math.Max(_currentTimestamp, message.MessageHeader.Timestamp);

                var head = message.Data.Span[0];

                var data = FlvDemuxer.DemultiplexVideoData(message);
                if (data.FrameType == FrameType.KeyFrame)
                {
                    _keyframeTimes.Add((double)message.MessageHeader.Timestamp / 1000);
                    _keyframeFilePositions.Add((double)_recordFileData.Position);
                }

                await SaveMessage(message);
            }
            catch
            {
                RtmpSession.Close();
            }
        }
예제 #4
0
 private Task <Message> ReadMessage(CancellationToken ct)
 {
     return(FlvDemuxer.DemultiplexFlvAsync(ct));
 }