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); }
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(); } }
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(); } }
private Task <Message> ReadMessage(CancellationToken ct) { return(FlvDemuxer.DemultiplexFlvAsync(ct)); }