private async Task HandlePublishStreamAsync(RtmpMessage message, AmfCommandMessage command)
        {
            var    streamName = command.AdditionalArguments[0] as string;
            var    streamPath = $"/{_application}/{streamName}";
            var    streamId = (int)message.Message.StreamId;
            var    stream = new RtmpStream(streamId, streamName, streamPath);
            string code, level, description;

            if (!_context.TryAddPublishser(streamPath, _session.Id))
            {
                _logger.LogError($@"[rtmp publish] Already has a stream. id ={_session.Id} streamPath ={streamPath} streamId ={streamId}");
                level       = "error";
                code        = "NetStream.Publish.BadName";
                description = "Stream already publishing";
            }
            else if (_session.PublishStream != null)
            {
                level       = "error";
                description = $"{streamPath} is already published.";
                code        = "NetStream.Publish.BadConnection";
            }
            else
            {
                _session.PublishStream = stream;
                level       = "status";
                description = $"{streamPath} is now published.";
                code        = "NetStream.Publish.Start";
            }
            await SendStatusMessageAsync(stream.Id, level, code, description);

            await _session.SendStartToAllPlayersAsync();
        }
        public async Task OnStopPlayAsync(object publishser, RtmpStream stream)
        {
            var description = $"{stream.Path} is now unpublished.";
            var code        = "NetStream.Play.UnpublishNotify";

            await SendStatusMessageAsync(stream.Id, "status", code, description);
        }
 private async Task RespondPlayAsync(RtmpStream stream)
 {
     await SendUserControlMessageAsync(UserControlMessageType.StreamBegin, stream.Id);
     await SendStatusMessageAsync(stream.Id, "status", "NetStream.Play.Reset", "Playing and resetting stream.");
     await SendStatusMessageAsync(stream.Id, "status", "NetStream.Play.Start", "Started playing stream.");
     await SendRtmpSampleAccess();
 }
        public async Task  OnStartPlayAsync(ServerSession publisher, RtmpStream stream)
        {
            if (publisher.MetaData.Length != 0)
            {
                var payload       = publisher.MetaData;
                var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Data);
                var messageHeader = new RtmpMessageHeader(0, payload.Length, RtmpMessageType.DataAMF0, stream.Id);
                var message       = new RtmpMessage(header, messageHeader, payload);
                await _session.SendMessageAsync(message);
            }

            if (publisher.AudioCodec?.CodecId == RtmpConstants.AacAudio)
            {
                var payload       = publisher.AudioCodec.AacSequenceHeader;
                var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Audio);
                var messageHeader = new RtmpMessageHeader(0, payload.Length, RtmpMessageType.Audio, stream.Id);
                var message       = new RtmpMessage(header, messageHeader, payload);
                await _session.SendMessageAsync(message);
            }

            if (publisher.VideoCodec?.CodecId == RtmpConstants.H264Video || publisher.VideoCodec?.CodecId == RtmpConstants.H265Video)
            {
                var payload       = publisher.VideoCodec.AvcSequenceHeader;
                var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Video);
                var messageHeader = new RtmpMessageHeader(0, payload.Length, RtmpMessageType.Video, stream.Id);
                var message       = new RtmpMessage(header, messageHeader, payload);
                await _session.SendMessageAsync(message);
            }

            if (publisher.RtmpGopCacheQueue != null)
            {
                foreach (var message in publisher.RtmpGopCacheQueue)
                {
                    var modifiedMessage = new RtmpMessage(
                        message.Header,
                        message.Message.Translate(stream.Id),
                        message.Payload);
                    await _session.SendMessageAsync(modifiedMessage);
                }
            }

            _logger.LogInformation($@"[rtmp play] Join stream. id ={_session.Id} streamPath ={stream.Path} streamId ={stream.Id} ");
        }
        private async Task HandlePlayAsync(RtmpMessage message, AmfCommandMessage command)
        {
            var streamName = command.AdditionalArguments[0] as string;
            var streamPath = $"/{_application}/{streamName.Split("?")[0]}";
            var streamId   = message.Message.StreamId;
            var stream     = new RtmpStream(streamId, streamName, streamPath);

            if (_session.IsPlaying)
            {
                _logger.LogInformation($@"[rtmp play] NetConnection is playing.id ={_session.Id}
                streamPath ={streamPath}
                streamId ={streamId} ");
                await SendStatusMessageAsync(streamId, "error", "NetStream.Play.BadConnection", "Connection already playing");

                return;
            }
            else
            {
                _session.PlayStream = stream;
                await RespondPlayAsync(stream);
            }

            if (_context.TryGetPublishser(streamPath, out var publisher))
            {
                await OnStartPlayAsync(publisher, stream);

                _context.AddPlayer(streamPath, _session.Id);
            }
            else
            {
                _logger.LogInformation($@"[rtmp play] Stream not found.id ={_session.Id}
                streamPath ={streamPath}
                streamId ={streamId}");
                _context.AddIdlePlayer(streamPath, _session.Id);
            }
        }