byte[] GetMessageBytes(RtmpMessage message, Action <AmfWriter, RtmpMessage> handler) { using (var stream = new MemoryStream()) using (var messageWriter = new AmfWriter(stream, writer.SerializationContext, objectEncoding)) { handler(messageWriter, message); return(stream.ToArray()); } }
void WriteData(AmfWriter writer, RtmpMessage o, ObjectEncoding encoding) { if (o is Command) { WriteCommandOrData(writer, o, encoding); } else if (o is ByteData) { writer.WriteBytes(((ByteData)o).Data); } }
public void Queue(RtmpMessage 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); }
/// <summary> /// 写入命令或数据 /// </summary> /// <param name="writer"></param> /// <param name="o"></param> /// <param name="encoding"></param> void WriteCommandOrData(AmfWriter writer, RtmpMessage 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 (methodCall.Name == "@setDataFrame") { writer.WriteAmfItem(encoding, command.ConnectionParameters); } if (isInvoke) { writer.WriteAmfItem(encoding, command.InvokeId); writer.WriteAmfItem(encoding, command.ConnectionParameters); if (!methodCall.IsSuccess) { methodCall.Parameters = new object[] { new StatusAsObject(StatusCode.CallFailed, "error", "Call failed.") } } ; } // write arguments foreach (var arg in methodCall.Parameters) { writer.WriteAmfItem(encoding, arg); } } }
public RtmpPacket(RtmpHeader header, RtmpMessage body) : this(header) { Body = body; Length = header.PacketLength; }
public RtmpPacket(RtmpMessage body) { Body = body; }
void WriteProtocolControlMessage(RtmpMessage @event) { Writer.Queue(@event, CONTROL_CSID, 0); }
public void SendAmf0Data(RtmpMessage e) { //var timestamp = (int)(DateTime.UtcNow - connectTime).TotalMilliseconds; //e.Timestamp = timestamp; Writer.Queue(e, StreamID, _random.Next()); }
byte[] GetMessageBytes(RtmpHeader header, RtmpMessage 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); } }