public void Queue(RtmpEvent message, int streamId, int messageStreamId) { var header = new RtmpHeader(); var packet = new RtmpPacket(header, message); header.StreamId = 0; header.Timestamp = message.Timestamp; header.MessageStreamId = messageStreamId; header.MessageType = message.MessageType; queuedPackets.Enqueue(packet); packetAvailableEvent.Set(); }
private RtmpEvent ParsePacket(RtmpPacket packet, Func <AmfReader, RtmpEvent> handler) { AmfReader amfReader = new AmfReader((Stream) new MemoryStream(packet.Buffer, false), this._reader.SerializationContext); RtmpHeader header = packet.Header; RtmpEvent rtmpEvent = handler(amfReader); RtmpHeader rtmpHeader = header; rtmpEvent.Header = rtmpHeader; int timestamp = header.Timestamp; rtmpEvent.Timestamp = timestamp; return(rtmpEvent); }
private void WriteData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding) { Command command = o as Command; if (command.MethodCall == null) { this.WriteCommandOrData(writer, o, encoding); } else { writer.WriteBytes(command.Buffer); } }
byte[] GetMessageBytes(FlvTagHeader header, RtmpEvent message) { switch (header.TagType) { case MessageType.Audio: case MessageType.Video: return(GetMessageBytes(message, (w, o) => w.WriteBytes(((ByteData)o).Data))); case MessageType.DataAmf0: return(GetMessageBytes(message, (w, o) => WriteCommandOrData(w, o, ObjectEncoding.Amf0))); default: throw new ArgumentOutOfRangeException("Unknown RTMP message type: " + (int)header.TagType); } }
public void Queue(RtmpEvent message, int streamId, int messageStreamId) { RtmpHeader header = new RtmpHeader(); RtmpPacket rtmpPacket = new RtmpPacket(header, message); header.StreamId = streamId; header.Timestamp = message.Timestamp; header.MessageStreamId = messageStreamId; header.MessageType = message.MessageType; if (message.Header != null) { header.IsTimerRelative = message.Header.IsTimerRelative; } this._queuedPackets.Enqueue(rtmpPacket); this._packetAvailableEvent.Set(); }
private void WriteCommandOrData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding) { var command = o as Command; var methodCall = command.MethodCall; var isInvoke = command is Invoke; // write the method name or result type (first section) var isRequest = methodCall.CallStatus == CallStatus.Request; var isResult = methodCall.CallStatus == CallStatus.Result; if (isRequest) { writer.WriteAmfItem(ObjectEncoding.Amf0, methodCall.Name); } else { writer.WriteAmfItem(ObjectEncoding.Amf0, methodCall.IsSuccess ? "_result" : "_error"); } if (isInvoke) { writer.WriteAmfItem(ObjectEncoding.Amf0, command.InvokeId); writer.WriteAmfItem(encoding, command.ConnectionParameters); } if (isRequest || isResult) { // write arguments foreach (var arg in methodCall.Parameters) { writer.WriteAmfItem(encoding, arg); } } else if (isInvoke) { // write the result if (!methodCall.IsSuccess) { methodCall.Parameters = new object[] { new StatusAsObject(StatusCode.CallFailed, "error", "Call failed.") } } ; writer.WriteAmfItem(encoding, methodCall.Parameters); } } }
private void WriteCommandOrData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding) { Command command = o as Command; Method methodCall = command.MethodCall; bool flag1 = command is Invoke; bool flag2 = methodCall.CallStatus == CallStatus.Request; bool flag3 = methodCall.CallStatus == CallStatus.Result; if (flag2) { writer.WriteAmfItem(ObjectEncoding.Amf0, (object)methodCall.Name); } else { writer.WriteAmfItem(ObjectEncoding.Amf0, methodCall.IsSuccess ? (object)"_result" : (object)"_error"); } if (flag1) { writer.WriteAmfItem(ObjectEncoding.Amf0, (object)command.InvokeId); writer.WriteAmfItem(encoding, command.ConnectionParameters); } if (flag2 | flag3) { foreach (object parameter in methodCall.Parameters) { writer.WriteAmfItem(encoding, parameter); } } else { if (!flag1) { return; } if (!methodCall.IsSuccess) { methodCall.Parameters = new object[1] { (object)new StatusAsObject("NetConnection.Call.Failed", "error", "Call failed.") } } ; writer.WriteAmfItem(encoding, (object)methodCall.Parameters); } } }
public void Queue(RtmpEvent message, int streamId, int messageStreamId) { var header = new RtmpHeader(); var packet = new RtmpPacket(header, message); header.StreamId = streamId; header.Timestamp = message.Timestamp; header.MessageStreamId = messageStreamId; header.MessageType = message.MessageType; if (message.Header != null) { header.IsTimerRelative = message.Header.IsTimerRelative; } queuedPackets.Enqueue(packet); // packetAvailableEvent.Set(); Interlocked.Exchange(ref packetAvailable, 1); }
void WriteCommandOrData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding) { var command = o as Command; var methodCall = command.MethodCall; var isInvoke = command is Invoke; // write the method name or result type (first section) if (methodCall.Name == "@setDataFrame") { writer.WriteAmfItem(encoding, command.ConnectionParameters); } // write arguments foreach (var arg in methodCall.Parameters) { writer.WriteAmfItem(encoding, arg); } }
public void ReadLoop() { try { while (this.Continue) { RtmpHeader header = this.ReadHeader(); this._rtmpHeaders[header.StreamId] = header; RtmpPacket packet1; if (!this._rtmpPackets.TryGetValue(header.StreamId, out packet1) || packet1 == null) { packet1 = new RtmpPacket(header); this._rtmpPackets[header.StreamId] = packet1; } byte[] bytes = this._reader.ReadBytes(Math.Min(packet1.Length + (header.Timestamp >= 16777215 ? 4 : 0) - packet1.CurrentLength, this._readChunkSize)); packet1.AddBytes(bytes); if (packet1.IsComplete) { this._rtmpPackets.Remove(header.StreamId); RtmpEvent packet2 = this.ParsePacket(packet1); this.OnEventReceived(new EventReceivedEventArgs(packet2)); ChunkSize chunkSize = packet2 as ChunkSize; if (chunkSize != null) { this._readChunkSize = chunkSize.Size; } Abort abort = packet2 as Abort; if (abort != null) { this._rtmpPackets.Remove(abort.StreamId); } } } } catch (Exception ex) { this.OnDisconnected(new ExceptionalEventArgs("rtmp-packet-reader", ex)); } }
private void WritePacket(RtmpPacket packet) { RtmpHeader header = packet.Header; int streamId = header.StreamId; RtmpEvent body = packet.Body; byte[] messageBytes = this.GetMessageBytes(header, body); header.PacketLength = messageBytes.Length; RtmpHeader previousHeader; this._rtmpHeaders.TryGetValue(streamId, out previousHeader); this._rtmpHeaders[streamId] = header; this._rtmpPackets[streamId] = packet; this.WriteMessageHeader(header, previousHeader); bool flag = true; int index = 0; while (index < header.PacketLength) { if (!flag) { this.WriteBasicHeader(ChunkMessageHeaderType.Continuation, header.StreamId); } int count = index + this._writeChunkSize > header.PacketLength ? header.PacketLength - index : this._writeChunkSize; this._writer.Write(messageBytes, index, count); flag = false; index += this._writeChunkSize; } ChunkSize chunkSize = body as ChunkSize; if (chunkSize == null) { return; } this._writeChunkSize = chunkSize.Size; }
byte[] GetMessageBytes(RtmpHeader header, RtmpEvent message) { switch (header.MessageType) { case MessageType.SetChunkSize: return(GetMessageBytes(message, (w, o) => w.WriteInt32(((ChunkSize)o).Size))); case MessageType.AbortMessage: return(GetMessageBytes(message, (w, o) => w.WriteInt32(((Abort)o).StreamId))); case MessageType.Acknowledgement: return(GetMessageBytes(message, (w, o) => w.WriteInt32(((Acknowledgement)o).BytesRead))); case MessageType.UserControlMessage: return(GetMessageBytes(message, (w, o) => { var m = (UserControlMessage)o; w.WriteUInt16((ushort)m.EventType); foreach (var v in m.Values) { w.WriteInt32(v); } })); case MessageType.WindowAcknowledgementSize: return(GetMessageBytes(message, (w, o) => w.WriteInt32(((WindowAcknowledgementSize)o).Count))); case MessageType.SetPeerBandwith: return(GetMessageBytes(message, (w, o) => { var m = (PeerBandwidth)o; w.WriteInt32(m.AcknowledgementWindowSize); w.WriteByte((byte)m.LimitType); })); case MessageType.Audio: case MessageType.Video: return(GetMessageBytes(message, (w, o) => WriteData(w, o, ObjectEncoding.Amf0))); case MessageType.DataAmf0: return(GetMessageBytes(message, (w, o) => WriteCommandOrData(w, o, ObjectEncoding.Amf0))); case MessageType.SharedObjectAmf0: return(new byte[0]); // todo: `SharedObject`s case MessageType.CommandAmf0: return(GetMessageBytes(message, (w, o) => WriteCommandOrData(w, o, ObjectEncoding.Amf0))); case MessageType.DataAmf3: return(GetMessageBytes(message, (w, o) => WriteData(w, o, ObjectEncoding.Amf3))); case MessageType.SharedObjectAmf3: return(new byte[0]); // todo: `SharedObject`s case MessageType.CommandAmf3: return(GetMessageBytes(message, (w, o) => { w.WriteByte(0); WriteCommandOrData(w, o, ObjectEncoding.Amf3); })); case MessageType.Aggregate: // todo: Aggregate messages System.Diagnostics.Debugger.Break(); return(new byte[0]); // todo: `Aggregate` default: throw new ArgumentOutOfRangeException("Unknown RTMP message type: " + (int)header.MessageType); } }
public FlvPacket(FlvTagHeader header, RtmpEvent body) : this(header) { Body = body; Length = header.DataSize; }
public FlvPacket(RtmpEvent body) { Body = body; }
void WriteProtocolControlMessage(RtmpEvent @event) { writer.Queue(@event, 2, 0); }
public EventReceivedEventArgs(RtmpEvent @event) { this.Event = @event; }
public RtmpPacket(RtmpHeader header, RtmpEvent body) : this(header) { Body = body; Length = header.PacketLength; }
private void WriteProtocolControlMessage(RtmpEvent @event) { this._writer.Queue(@event, 2, 0); }
public RtmpPacket(RtmpEvent body) { Body = body; }
public void SendAmf0Data(RtmpEvent e) { //var timestamp = (int)(DateTime.UtcNow - connectTime).TotalMilliseconds; //e.Timestamp = timestamp; writer.Queue(e, StreamId, random.Next()); }
private byte[] GetMessageBytes(RtmpHeader header, RtmpEvent message) { switch (header.MessageType) { case MessageType.SetChunkSize: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((ChunkSize)o).Size)))); case MessageType.AbortMessage: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((Abort)o).StreamId)))); case MessageType.Acknowledgement: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((Acknowledgement)o).BytesRead)))); case MessageType.UserControlMessage: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => { UserControlMessage userControlMessage = (UserControlMessage)o; w.WriteUInt16((ushort)userControlMessage.EventType); foreach (int num in userControlMessage.Values) { w.WriteInt32(num); } }))); case MessageType.WindowAcknowledgementSize: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((WindowAcknowledgementSize)o).Count)))); case MessageType.SetPeerBandwidth: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => { PeerBandwidth peerBandwidth = (PeerBandwidth)o; w.WriteInt32(peerBandwidth.AcknowledgementWindowSize); w.WriteByte((byte)peerBandwidth.LimitType); }))); case MessageType.Audio: case MessageType.Video: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteBytes(((ByteData)o).Data)))); case MessageType.DataAmf3: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => this.WriteData(w, o, ObjectEncoding.Amf3)))); case MessageType.SharedObjectAmf3: return(new byte[0]); case MessageType.CommandAmf3: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => { w.WriteByte((byte)0); this.WriteCommandOrData(w, o, ObjectEncoding.Amf3); }))); case MessageType.DataAmf0: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => this.WriteData(w, o, ObjectEncoding.Amf0)))); case MessageType.SharedObjectAmf0: return(new byte[0]); case MessageType.CommandAmf0: return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => this.WriteCommandOrData(w, o, ObjectEncoding.Amf0)))); case MessageType.Aggregate: Debugger.Break(); return(new byte[0]); default: throw new ArgumentOutOfRangeException("Unknown RTMP message type: " + (object)(int)header.MessageType); } }
void WriteProtocolControlMessage(RtmpEvent @event) { writer.Queue(@event, CONTROL_CSID, 0); }
public RtmpPacket(RtmpEvent body) { this.Body = body; }