public async Task SendProtocolControlMessageAsync(RtmpMessageType messageType, int data)
 {
     var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Protocol);
     var messageHeader = new RtmpMessageHeader(0, 4, messageType, 0);
     var body          = BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(data));
     var message       = new RtmpMessage(header, messageHeader, body);
     await _session.SendMessageAsync(message);
 }
示例#2
0
 public RtmpMessageHeader(RtmpMessageHeader other)
 {
     Timestamp         = other.Timestamp;
     Length            = other.Length;
     MessageType       = other.MessageType;
     StreamId          = other.StreamId;
     ExtendedTimestamp = other.ExtendedTimestamp;
 }
示例#3
0
        public async Task SendDataCommandAsync(AmfDataMessage data)
        {
            var body = new byte[data.GetLength()];

            data.Encode(body.AsSpan());
            var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Data);
            var messageHeader = new RtmpMessageHeader(0, body.Length, RtmpMessageType.DataAMF0, 0);
            var message       = new RtmpMessage(header, messageHeader, body);
            await _session.SendMessageAsync(message);
        }
        public async Task SendCommandMessageAsync(int streamId, AmfCommandMessage command)
        {
            var body = new byte[command.GetLength()];

            command.Encode(body.AsSpan());
            var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Invoke);
            var messageHeader = new RtmpMessageHeader(0, body.Length, RtmpMessageType.CommandAMF0, streamId);
            var message       = new RtmpMessage(header, messageHeader, body);
            await _session.SendMessageAsync(message);
        }
示例#5
0
        public void Write(Span <byte> buffer)
        {
            Header.Write(buffer);
            buffer = buffer.Slice(Header.Length);
            Message.Write(buffer, Header.HeaderType);
            buffer = buffer.Slice(RtmpMessageHeader.GetHeaderLength(Header.HeaderType));
            var reader = new SequenceReader <byte>(Payload);

            reader.TryCopyTo(buffer);
        }
        private async Task SendUserControlMessageAsync(UserControlMessageType type, int data)
        {
            var header        = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Protocol);
            var messageHeader = new RtmpMessageHeader(0, 6, RtmpMessageType.UserCtrlMessage, 0);
            var payload       = new byte[6];

            BinaryPrimitives.WriteInt16BigEndian(payload.AsSpan(), (short)type);
            BinaryPrimitives.WriteInt32BigEndian(payload.AsSpan().Slice(2), data);
            var message = new RtmpMessage(header, messageHeader, payload);
            await _session.SendMessageAsync(message);
        }
        public async Task SendResultAsync(object data)
        {
            var chunkHeader = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Invoke);
            var response    = new AmfCommandMessage
            {
                Name          = "_result",
                CommandObject = data
            };
            var length = response.GetLength();
            var memory = new byte[length];

            response.Encode(memory);
            var messageHeader = new RtmpMessageHeader(0, length, RtmpMessageType.CommandAMF0, 0);
            var message       = new RtmpMessage(chunkHeader, messageHeader, memory);
            await _session.SendMessageAsync(message);
        }
        private bool TryParseChunk(ref SequenceReader <byte> reader, out RtmpChunk chunk, out RtmpMessageEntry messageEntry)
        {
            messageEntry = null;
            chunk        = null;
            _logger.LogDebug($"Before parsing chunk: Sequence Reader Length:{reader.Length}: Consumed:{reader.Consumed}  Remaining:{reader.Remaining}");
            var header = new RtmpChunkHeader();

            if (!header.TryParse(ref reader))
            {
                return(false);
            }

            if (!_messageCache.TryGetValue(header.StreamId, out messageEntry))
            {
                messageEntry = new RtmpMessageEntry();
                _messageCache.Add(header.StreamId, messageEntry);
            }

            var message = new RtmpMessageHeader();

            if (!message.TryParse(ref reader, header.HeaderType, messageEntry.LastChunk?.Message))
            {
                return(false);
            }

            chunk = new RtmpChunk(header, message);
            if (header.HeaderType != RtmpChunkHeaderType.Type3)
            {
                messageEntry.Length    = chunk.Message.Length;
                messageEntry.BytesRead = 0;
            }
            else
            {
            }

            var chunkLength = Math.Min(messageEntry.BytesRemaining, _session.IncomingChunkLength);

            if (!chunk.TryParseBody(ref reader, chunkLength))
            {
                return(false);
            }
            _logger.LogDebug($"After parsing chunk: Sequence Reader Length:{reader.Length}: Consumed:{reader.Consumed}  Remaining:{reader.Remaining}");
            _logger.LogDebug($"Parsed chunk Header :{chunk.Header}: Message: {chunk.Message}");
            messageEntry.LastChunk = chunk;
            return(true);
        }
        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 HandleSetDataFrame(AmfDataMessage command)
        {
            _logger.LogInformation("Metadata found {0}", command.AdditionalArguments);
            var dataObj  = (dynamic)command.AdditionalArguments[1];
            var metadata = new AmfDataMessage
            {
                Name = "onMetaData",
                AdditionalArguments =
                {
                    dataObj
                }
            };

            _session.MetaData = new byte[metadata.GetLength()];
            metadata.Encode(_session.MetaData.Span);
            if (((IDictionary <string, object>)dataObj).ContainsKey("audiocodecid"))
            {
                _session.AudioCodec = new AudioCodecInfo
                {
                    CodecId    = dataObj.audiocodecid is double?(int)dataObj.audiocodecid : 0,
                    Channels   = dataObj.stereo ? 2                                       : 1,
                    Samplerate = (int)dataObj.audiosamplerate,
                    Bitrate    = (int)dataObj.audiodatarate
                };
            }
            if (((IDictionary <string, object>)dataObj).ContainsKey("videocodecid"))
            {
                _session.VideoCodec = new VideoCodecInfo
                {
                    CodecId   = dataObj.videocodecid is double?(int)dataObj.videocodecid : 0,
                    Width     = (int)dataObj.width,
                    Height    = (int)dataObj.height,
                    Framerate = (int)dataObj.framerate,
                    Bitrate   = (int)dataObj.videodatarate
                };
            }

            var header         = new RtmpChunkHeader(RtmpChunkHeaderType.Type0, RtmpConstants.RtmpChannel_Data);
            var messsageHeader = new RtmpMessageHeader(0, _session.MetaData.Length, RtmpMessageType.DataAMF0, 0);
            var message        = new RtmpMessage(header, messsageHeader, _session.MetaData);
            await _session.SendToAllPalyersAsync(message);
        }
示例#11
0
        public static bool TryParseHeader(ref SequenceReader <byte> reader, out RtmpChunk chunk)
        {
            chunk = null;
            var header = new RtmpChunkHeader();

            if (!header.TryParse(ref reader))
            {
                return(false);
            }

            var message = new RtmpMessageHeader();

            if (!message.TryParse(ref reader, header.HeaderType, previous: null))
            {
                return(false);
            }

            chunk = new RtmpChunk(header, message);
            return(true);
        }
示例#12
0
 public RtmpChunk(RtmpChunkHeader header, RtmpMessageHeader message, ReadOnlySequence <byte> payload) :
     this(header, message)
 {
     Payload = payload;
 }
示例#13
0
 public RtmpChunk(RtmpChunkHeader header, RtmpMessageHeader message, Memory <byte> payload) :
     this(header, message)
 {
     Payload = new ReadOnlySequence <byte>(payload);
 }
示例#14
0
 public RtmpChunk(RtmpChunkHeader header, RtmpMessageHeader message)
 {
     Header  = header;
     Message = message;
 }
示例#15
0
 public RtmpMessage(RtmpChunkHeader header, RtmpMessageHeader message, Memory <byte> payload)
 {
     Header  = header;
     Message = message;
     Payload = payload.Slice(0, Message.Length);
 }
示例#16
0
 public RtmpMessage(RtmpChunkHeader header, RtmpMessageHeader message, IMemoryOwner <byte> memoryOwner)
     : this(header, message, memoryOwner.Memory)
 {
     _memoryOwner = memoryOwner;
 }