private bool AssembleMessage(RtmpMessageEntry messageEntry, RtmpChunk chunk, out RtmpMessage message) { message = null; var currentMessage = messageEntry.Message; if (currentMessage == null) { var payload = _memoryPool.Rent(chunk.Message.Length); currentMessage = new RtmpMessage(chunk.Header, chunk.Message, payload); messageEntry.Message = currentMessage; } var memory = currentMessage.Payload.Slice(messageEntry.BytesRead, chunk.PayloadLength); var reader = new SequenceReader <byte>(chunk.Payload); reader.TryCopyTo(memory.Span); messageEntry.BytesRead += chunk.PayloadLength; // if message is complete .. return it. if (messageEntry.BytesRemaining == 0) { message = messageEntry.Message; _logger.LogInformation($"Parsed message :{message.Header}: Message: {message.Message}"); messageEntry.BytesRead = 0; messageEntry.Message = null; return(true); } return(false); }
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 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; } }
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); }
/// <summary> /// Try and parse the next RTMP chunk and advance the reader. /// </summary> /// <returns>true if chunk is available else false.</returns> private SequencePosition?TryParseChunk(PipeReader reader, ReadOnlySequence <byte> buffer, out RtmpChunk chunk, out RtmpMessageEntry messageEntry) { var sequenceReader = new SequenceReader <byte>(buffer); if (!TryParseChunk(ref sequenceReader, out chunk, out messageEntry)) { return(null); } return(sequenceReader.Position); }