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); }
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); }
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} "); }
public IEnumerable <RtmpChunk> ChunkMessage(RtmpMessage message) { var length = message.Message.Length; var memory = message.Payload; var offset = 0; while (length != 0) { var chunkHeader = new RtmpChunkHeader( offset == 0 ? RtmpChunkHeaderType.Type0 : RtmpChunkHeaderType.Type2, message.Header.StreamId); var chunkLength = Math.Min(_session.OutgoingChunkLength, length); var chunk = new RtmpChunk(chunkHeader, message.Message, memory.Slice(offset, chunkLength)); yield return(chunk); length -= chunkLength; offset += chunkLength; } }
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); }
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); }
public RtmpChunk(RtmpChunkHeader header, RtmpMessageHeader message, ReadOnlySequence <byte> payload) : this(header, message) { Payload = payload; }
public RtmpChunk(RtmpChunkHeader header, RtmpMessageHeader message, Memory <byte> payload) : this(header, message) { Payload = new ReadOnlySequence <byte>(payload); }
public RtmpChunk(RtmpChunkHeader header, RtmpMessageHeader message) { Header = header; Message = message; }
public RtmpMessage(RtmpChunkHeader header, RtmpMessageHeader message, Memory <byte> payload) { Header = header; Message = message; Payload = payload.Slice(0, Message.Length); }
public RtmpMessage(RtmpChunkHeader header, RtmpMessageHeader message, IMemoryOwner <byte> memoryOwner) : this(header, message, memoryOwner.Memory) { _memoryOwner = memoryOwner; }