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(); }
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; if (isRequest) writer.WriteAmfItem(encoding, methodCall.Name); else writer.WriteAmfItem(encoding, methodCall.IsSuccess ? "_result" : "_error"); if (isInvoke) { writer.WriteAmfItem(encoding, command.InvokeId); writer.WriteAmfItem(encoding, command.ConnectionParameters); } if (isRequest) { // 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); } }
void WriteData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding) { var command = o as Command; if (command.MethodCall == null) WriteCommandOrData(writer, o, encoding); else writer.WriteBytes(command.Buffer); }
byte[] GetMessageBytes(RtmpEvent message, Action<AmfWriter, RtmpEvent> handler) { using (var stream = new MemoryStream()) using (var messageWriter = new AmfWriter(stream, writer.SerializationContext, objectEncoding)) { handler(messageWriter, message); return stream.ToArray(); } }
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 = (PeerBandwith)o; w.WriteInt32(m.AcknowledgementWindowSize); w.WriteByte((byte)m.LimitType); }); case MessageType.Audio: case MessageType.Video: return GetMessageBytes(message, (w, o) => w.WriteBytes(((ByteData)o).Data)); case MessageType.DataAmf0: return GetMessageBytes(message, (w, o) => WriteData(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 RtmpPacket(RtmpHeader header, RtmpEvent body) : this(header) { Body = body; Length = header.PacketLength; }
public RtmpPacket(RtmpEvent body) { Body = body; }
public ChannelDataReceivedEventArgs(ChannelType t, RtmpEvent e) { this.type = t; this.e = e; }
void WriteProtocolControlMessage(RtmpEvent @event) { writer.Queue(@event, 2, 0); }
public EventReceivedEventArgs(RtmpEvent @event) { this.Event = @event; }