protected RtmpMessage ReadCommandOrData(AmfReader r, Command command, RtmpHeader header = null) { var methodName = (string)r.ReadAmf0Item(); object temp = r.ReadAmf0Item(); if (header != null && methodName == "@setDataFrame") { command.ConnectionParameters = temp; } else { command.InvokeId = Convert.ToInt32(temp); command.ConnectionParameters = r.ReadAmf0Item(); } var parameters = new List <object>(); while (r.DataAvailable) { parameters.Add(r.ReadAmf0Item()); } command.MethodCall = new Method(methodName, parameters.ToArray()); return(command); }
public RtmpPacket CreatePacket(Notify notify) { var header = new RtmpHeader { ChannelId = 3, DataType = notify.DataType, Timer = notify.Timestamp }; return(new RtmpPacket(header, notify)); }
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; _packetQueue.Enqueue(packet); _packetAvailableEvent.Set(); }
static ChunkMessageHeaderType GetMessageHeaderType(RtmpHeader header, RtmpHeader previousHeader) { if (previousHeader == null || header.MessageStreamId != previousHeader.MessageStreamId || !header.IsTimerRelative) { return(ChunkMessageHeaderType.New); } if (header.PacketLength != previousHeader.PacketLength || header.MessageType != previousHeader.MessageType) { return(ChunkMessageHeaderType.SameSource); } if (header.Timestamp != previousHeader.Timestamp) { return(ChunkMessageHeaderType.TimestampAdjustment); } return(ChunkMessageHeaderType.Continuation); }
protected override void OnServerBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ServerBW serverBw) { }
protected override void OnClientBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ClientBW clientBw) { channel.Write(new ServerBW(clientBw.Bandwidth)); }
protected override void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize) { //ChunkSize is not implemented yet }
protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping) { switch (ping.PingType) { case Ping.PingClient: case Ping.StreamBegin: case Ping.RecordedStream: case Ping.StreamPlayBufferClear: // The server wants to measure the RTT Ping pong = new Ping(); pong.PingType = Ping.PongServer; // The event data is a 4-byte timestamp, which was received with the in the Ping request pong.Value2 = ping.Value2; connection.Ping(pong); break; case Ping.StreamDry: #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug("Stream indicates there is no data available"); } #endif break; case Ping.ClientBuffer: //Set the client buffer IClientStream stream = null; //Get the stream id int streamId = ping.Value2; //Get requested buffer size in milliseconds int buffer = ping.Value3; #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Client sent a buffer size: {0} ms for stream id: {1}", buffer, streamId)); } #endif if (streamId != 0) { // The client wants to set the buffer time stream = connection.GetStreamById(streamId); if (stream != null) { stream.SetClientBufferDuration(buffer); #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Setting client buffer on stream: {0}", streamId)); } #endif } } //Catch-all to make sure buffer size is set if (stream == null) { // Remember buffer time until stream is created connection.RememberStreamBufferDuration(streamId, buffer); #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Remembering client buffer on stream: {0}", streamId)); } #endif } break; default: #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Unhandled ping: {0}", ping)); } #endif break; } }
/// <summary> /// Gets a header with the appropriate timestamp. /// </summary> /// <param name="dataType">Type of the event.</param> /// <param name="eventTime">The event time.</param> /// <returns></returns> public RtmpHeader GetTimeStamp(byte dataType, int eventTime) { RtmpHeader header = new RtmpHeader(); #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(string.Format("GetTimeStamp - event time: {0} last event: {1} audio: {2} video: {3} data: {4}", eventTime, _lastEventTime, _lastAudioTime, _lastVideoTime, _lastNotifyTime)); } #endif switch (dataType) { case Constants.TypeAudioData: if (_lastAudioTime > 0) { //set a relative value header.Timer = eventTime - _lastAudioTime; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Relative audio"); } #endif } else { //use absolute value header.Timer = eventTime; header.IsTimerRelative = false; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Absolute audio"); } #endif } _lastAudioTime = eventTime; break; case Constants.TypeVideoData: if (_lastVideoTime > 0) { //set a relative value header.Timer = eventTime - _lastVideoTime; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Relative video"); } #endif } else { //use absolute value header.Timer = eventTime; header.IsTimerRelative = false; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Absolute video"); } #endif } _lastVideoTime = eventTime; break; case Constants.TypeNotify: case Constants.TypeInvoke: case Constants.TypeFlexStreamEnd: if (_lastNotifyTime > 0) { //set a relative value header.Timer = eventTime - _lastNotifyTime; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Relative notify"); } #endif } else { //use absolute value header.Timer = eventTime; header.IsTimerRelative = false; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Absolute notify"); } #endif } _lastNotifyTime = eventTime; break; case Constants.TypeBytesRead: case Constants.TypePing: header.Timer = eventTime; header.IsTimerRelative = false; break; default: // ignore other types #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(string.Format("Unmodified type: {0} timestamp: {1}", dataType, eventTime)); } #endif break; } #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(string.Format("Event time: {0} current ts: {1}", eventTime, header.Timer)); } #endif _lastEventTime = eventTime; return(header); }
public void PushMessage(IPipe pipe, IMessage message) { if (message is ResetMessage) { _timeStamper.Reset(); } else if (message is StatusMessage) { StatusMessage statusMsg = message as StatusMessage; _data.SendStatus(statusMsg.body as StatusASO); } else if (message is RtmpMessage) { // Make sure chunk size has been sent if (!_chunkSizeSent) { SendChunkSize(); } RtmpMessage rtmpMsg = message as RtmpMessage; IRtmpEvent msg = rtmpMsg.body; int eventTime = msg.Timestamp; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(string.Format("Message timestamp: {0}", eventTime)); } #endif if (eventTime < 0) { #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(string.Format("Message has negative timestamp: {0}", eventTime)); } #endif return; } byte dataType = msg.DataType; // Create a new header for the consumer RtmpHeader header = _timeStamper.GetTimeStamp(dataType, eventTime); switch (msg.DataType) { case Constants.TypeStreamMetadata: Notify notify = new Notify((msg as Notify).Data); notify.Header = header; notify.Timestamp = header.Timer; _data.Write(notify); break; case Constants.TypeFlexStreamEnd: // TODO: okay to send this also to AMF0 clients? FlexStreamSend send = new FlexStreamSend((msg as Notify).Data); send.Header = header; send.Timestamp = header.Timer; _data.Write(send); break; case Constants.TypeVideoData: VideoData videoData = new VideoData((msg as VideoData).Data); videoData.Header = header; videoData.Timestamp = header.Timer; _video.Write(videoData); break; case Constants.TypeAudioData: AudioData audioData = new AudioData((msg as AudioData).Data); audioData.Header = header; audioData.Timestamp = header.Timer; _audio.Write(audioData); break; case Constants.TypePing: Ping ping = new Ping((msg as Ping).PingType, (msg as Ping).Value2, (msg as Ping).Value3, (msg as Ping).Value4); ping.Header = header; _connection.Ping(ping); break; case Constants.TypeBytesRead: BytesRead bytesRead = new BytesRead((msg as BytesRead).Bytes); bytesRead.Header = header; bytesRead.Timestamp = header.Timer; _connection.GetChannel((byte)2).Write(bytesRead); break; default: _data.Write(msg); break; } } }
protected override void OnFlexInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, FlexInvoke invoke) { OnInvoke(connection, channel, header, invoke); }
public void PushMessage(IPipe pipe, IMessage message) { if (message is ResetMessage) { this._streamTracker.Reset(); } else if (message is StatusMessage) { StatusMessage message2 = message as StatusMessage; this._data.SendStatus(message2.body as StatusASO); } else if (message is RtmpMessage) { RtmpMessage message3 = message as RtmpMessage; IRtmpEvent body = message3.body; RtmpHeader header = new RtmpHeader(); int num = this._streamTracker.Add(body); if (num < 0) { log.Warn("Skipping message with negative timestamp."); } else { header.IsTimerRelative = this._streamTracker.IsRelative; header.Timer = num; switch (body.DataType) { case 3: { BytesRead read = new BytesRead((body as BytesRead).Bytes); header.IsTimerRelative = false; header.Timer = 0; read.Header = header; read.Timestamp = header.Timer; this._connection.GetChannel(2).Write(read); return; } case 4: { Ping ping = new Ping((body as Ping).Value1, (body as Ping).Value2, (body as Ping).Value3, (body as Ping).Value4); header.IsTimerRelative = false; header.Timer = 0; ping.Header = header; ping.Timestamp = header.Timer; this._connection.Ping(ping); return; } case 8: { AudioData data2 = new AudioData((body as AudioData).Data) { Header = header, Timestamp = header.Timer }; this._audio.Write(data2); return; } case 9: { VideoData data = new VideoData((body as VideoData).Data) { Header = header, Timestamp = header.Timer }; this._video.Write(data); return; } case 15: { FlexStreamSend send = new FlexStreamSend((body as Notify).Data) { Header = header, Timestamp = header.Timer }; this._data.Write(send); return; } case 0x12: { Notify notify = new Notify((body as Notify).Data) { Header = header, Timestamp = header.Timer }; this._data.Write(notify); return; } } this._data.Write(body); } } }
protected override void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke) { IServiceCall call = invoke.ServiceCall; if (invoke.EventType == EventType.STREAM_DATA) { #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Ignoring stream data notify with header {0}", header)); } #endif return; } if (call.ServiceMethodName == "_result" || call.ServiceMethodName == "_error") { if (call.ServiceMethodName == "_error") { call.Status = Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION; } if (call.ServiceMethodName == "_result") { call.Status = Messaging.Rtmp.Service.Call.STATUS_SUCCESS_RESULT; } //Get the panding call, if any, as HandlePendingCallResult will remove it IPendingServiceCall pendingCall = connection.GetPendingCall(invoke.InvokeId); HandlePendingCallResult(connection, invoke); if (call.IsSuccess && invoke.InvokeId == 1) { // Should keep this as an Object to stay compatible with FMS3 etc IDictionary aso = call.Arguments[0] as IDictionary; if (aso != null) { object clientId = null; if (aso.Contains("clientid")) { clientId = aso["clientid"]; } #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Client id: {0}", clientId)); } #endif _netConnection.SetClientId(clientId != null ? clientId.ToString() : null); } } //Notify via NetConnection if no IPendingServiceCallback was defined but the call failed if (call.ServiceMethodName == "_error") { object[] args = call.Arguments; ASObject statusAso = null; if ((args != null) && (args.Length > 0)) { statusAso = args[0] as ASObject; } bool raiseError = false; if (pendingCall != null) { IPendingServiceCallback[] callbacks = pendingCall.GetCallbacks(); if (callbacks == null || callbacks.Length == 0) { raiseError = true; } } else { raiseError = true; } if (raiseError) { if (statusAso != null) { _netConnection.RaiseNetStatus(statusAso); } else { string msg = __Res.GetString(__Res.Invocation_Failed, pendingCall != null ? pendingCall.ServiceMethodName : string.Empty, "Invocation failed"); _netConnection.RaiseNetStatus(msg); } } } return; } bool onStatus = call.ServiceMethodName.Equals("onStatus") || call.ServiceMethodName.Equals("onMetaData") || call.ServiceMethodName.Equals("onPlayStatus"); if (onStatus) { /* * IDictionary aso = call.Arguments[0] as IDictionary; * // Should keep this as an Object to stay compatible with FMS3 etc * object clientId = null; * if( aso.Contains("clientid") ) * clientId = aso["clientid"]; * if (clientId == null) * clientId = header.StreamId; #if !SILVERLIGHT * if (log.IsDebugEnabled) * log.Debug(string.Format("Client id: {0}", clientId)); #endif * if (clientId != null) * { * NetStream stream = _connection.GetStreamById((int)clientId) as NetStream; * if (stream != null) * { * stream.OnStreamEvent(invoke); * } * } */ NetStream stream = _connection.GetStreamById(header.StreamId) as NetStream; if (stream != null) { stream.OnStreamEvent(invoke); } return; } if (call is IPendingServiceCall) { IPendingServiceCall psc = call as IPendingServiceCall; /* * object result = psc.Result; * object result = psc.Result; * if (result is DeferredResult) * { * DeferredResult dr = result as DeferredResult; * dr.InvokeId = invoke.InvokeId; * dr.ServiceCall = psc; * dr.Channel = channel; * connection.RegisterDeferredResult(dr); * } * else * { * Invoke reply = new Invoke(); * reply.ServiceCall = call; * reply.InvokeId = invoke.InvokeId; * channel.Write(reply); * } */ MethodInfo mi = MethodHandler.GetMethod(_netConnection.Client.GetType(), call.ServiceMethodName, call.Arguments, false, false); if (mi != null) { ParameterInfo[] parameterInfos = mi.GetParameters(); object[] args = new object[parameterInfos.Length]; call.Arguments.CopyTo(args, 0); TypeHelper.NarrowValues(args, parameterInfos); try { InvocationHandler invocationHandler = new InvocationHandler(mi); object result = invocationHandler.Invoke(_netConnection.Client, args); if (mi.ReturnType == typeof(void)) { call.Status = Messaging.Rtmp.Service.Call.STATUS_SUCCESS_VOID; } else { call.Status = result == null ? Messaging.Rtmp.Service.Call.STATUS_SUCCESS_NULL : Messaging.Rtmp.Service.Call.STATUS_SUCCESS_RESULT; psc.Result = result; } } catch (Exception exception) { call.Exception = exception; call.Status = Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION; //log.Error("Error while invoking method " + call.ServiceMethodName + " on client", exception); } } else// if (!onStatus) { string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, call.ServiceMethodName); call.Status = Messaging.Rtmp.Service.Call.STATUS_METHOD_NOT_FOUND; call.Exception = new FluorineException(msg); _netConnection.RaiseNetStatus(call.Exception); //log.Error(msg, call.Exception); } if (call.Status == Messaging.Rtmp.Service.Call.STATUS_SUCCESS_VOID || call.Status == Messaging.Rtmp.Service.Call.STATUS_SUCCESS_NULL) { #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug("Method does not have return value, do not reply"); } #endif return; } Invoke reply = new Invoke(); reply.ServiceCall = call; reply.InvokeId = invoke.InvokeId; channel.Write(reply); } else { IPendingServiceCall pendingCall = connection.RetrievePendingCall(invoke.InvokeId); Unreferenced.Parameter(pendingCall); } }
protected RtmpHeader ReadHeader() { // first byte of the chunk basic header var chunkBasicHeaderByte = reader.ReadByte(); var chunkStreamId = GetChunkStreamId(chunkBasicHeaderByte, reader); var chunkMessageHeaderType = (ChunkMessageHeaderType)(chunkBasicHeaderByte >> 6); var header = new RtmpHeader() { StreamId = chunkStreamId, IsTimerRelative = chunkMessageHeaderType != ChunkMessageHeaderType.New }; RtmpHeader previousHeader; // don't need to clone if new header, as it contains all info if (!rtmpHeaders.TryGetValue(chunkStreamId, out previousHeader) && chunkMessageHeaderType != ChunkMessageHeaderType.New) { previousHeader = header.Clone(); } switch (chunkMessageHeaderType) { // 11 bytes case ChunkMessageHeaderType.New: header.Timestamp = reader.ReadUInt24(); header.PacketLength = reader.ReadUInt24(); header.MessageType = (MessageType)reader.ReadByte(); header.MessageStreamId = reader.ReadReverseInt(); break; // 7 bytes case ChunkMessageHeaderType.SameSource: header.Timestamp = reader.ReadUInt24(); header.PacketLength = reader.ReadUInt24(); header.MessageType = (MessageType)reader.ReadByte(); header.MessageStreamId = previousHeader.MessageStreamId; break; // 3 bytes case ChunkMessageHeaderType.TimestampAdjustment: header.Timestamp = reader.ReadUInt24(); header.PacketLength = previousHeader.PacketLength; header.MessageType = previousHeader.MessageType; header.MessageStreamId = previousHeader.MessageStreamId; break; // 0 bytes case ChunkMessageHeaderType.Continuation: header.Timestamp = previousHeader.Timestamp; header.PacketLength = previousHeader.PacketLength; header.MessageType = previousHeader.MessageType; header.MessageStreamId = previousHeader.MessageStreamId; header.IsTimerRelative = previousHeader.IsTimerRelative; break; default: throw new SerializationException("Unexpected header type: " + (int)chunkMessageHeaderType); } // extended timestamp if (header.Timestamp == 0xFFFFFF) { header.Timestamp = reader.ReadInt32(); } return(header); }
protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping) { if (ping.Value1 == 6) { Ping ping2 = new Ping { Value1 = 7 }; int num = Environment.TickCount & ((int)0xffffffffL); ping2.Value2 = num; ping2.Value3 = -1; connection.Ping(ping2); } }
protected override void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke) { IServiceCall serviceCall = invoke.ServiceCall; if ((serviceCall.ServiceMethodName == "_result") || (serviceCall.ServiceMethodName == "_error")) { if (serviceCall.ServiceMethodName == "_error") { serviceCall.Status = 0x13; } if (serviceCall.ServiceMethodName == "_result") { serviceCall.Status = 2; } base.HandlePendingCallResult(connection, invoke); } else if (serviceCall is IPendingServiceCall) { IPendingServiceCall call2 = serviceCall as IPendingServiceCall; MethodInfo methodInfo = MethodHandler.GetMethod(this._netConnection.Client.GetType(), serviceCall.ServiceMethodName, serviceCall.Arguments, false, false); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; serviceCall.Arguments.CopyTo(array, 0); TypeHelper.NarrowValues(array, parameters); try { object obj2 = new InvocationHandler(methodInfo).Invoke(this._netConnection.Client, array); if (methodInfo.ReturnType == typeof(void)) { serviceCall.Status = 4; } else { serviceCall.Status = (obj2 == null) ? ((byte)3) : ((byte)2); call2.Result = obj2; } } catch (Exception exception) { serviceCall.Exception = exception; serviceCall.Status = 0x13; } } else { string message = __Res.GetString("Invocation_NoSuitableMethod", new object[] { serviceCall.ServiceMethodName }); serviceCall.Status = 0x11; serviceCall.Exception = new FluorineException(message); } if ((serviceCall.Status == 4) || (serviceCall.Status == 3)) { if (log.get_IsDebugEnabled()) { log.Debug("Method does not have return value, do not reply"); } } else { FluorineFx.Messaging.Rtmp.Event.Invoke invoke2 = new FluorineFx.Messaging.Rtmp.Event.Invoke { ServiceCall = serviceCall, InvokeId = invoke.InvokeId }; channel.Write(invoke2); } } }
protected override void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize) { }
protected override void OnSharedObject(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, SharedObjectMessage message) { _netConnection.OnSharedObject(connection, channel, header, message); }
internal void OnSharedObject(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, SharedObjectMessage message) { RemoteSharedObject.Dispatch(message); }
/// <summary> /// Gets a header with the appropriate timestamp. /// </summary> /// <param name="dataType">Type of the event.</param> /// <param name="eventTime">The event time.</param> /// <returns></returns> public RtmpHeader GetTimeStamp(byte dataType, int eventTime) { RtmpHeader header = new RtmpHeader(); #if !SILVERLIGHT if( log.IsDebugEnabled ) log.Debug(string.Format("GetTimeStamp - event time: {0} last event: {1} audio: {2} video: {3} data: {4}", eventTime, _lastEventTime, _lastAudioTime, _lastVideoTime, _lastNotifyTime)); #endif switch (dataType) { case Constants.TypeAudioData: if (_lastAudioTime > 0) { //set a relative value header.Timer = eventTime - _lastAudioTime; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Relative audio"); #endif } else { //use absolute value header.Timer = eventTime; header.IsTimerRelative = false; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Absolute audio"); #endif } _lastAudioTime = eventTime; break; case Constants.TypeVideoData: if (_lastVideoTime > 0) { //set a relative value header.Timer = eventTime - _lastVideoTime; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Relative video"); #endif } else { //use absolute value header.Timer = eventTime; header.IsTimerRelative = false; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Absolute video"); #endif } _lastVideoTime = eventTime; break; case Constants.TypeNotify: case Constants.TypeInvoke: case Constants.TypeFlexStreamEnd: if (_lastNotifyTime > 0) { //set a relative value header.Timer = eventTime - _lastNotifyTime; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Relative notify"); #endif } else { //use absolute value header.Timer = eventTime; header.IsTimerRelative = false; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Absolute notify"); #endif } _lastNotifyTime = eventTime; break; case Constants.TypeBytesRead: case Constants.TypePing: header.Timer = eventTime; header.IsTimerRelative = false; break; default: // ignore other types #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug(string.Format("Unmodified type: {0} timestamp: {1}", dataType, eventTime)); #endif break; } #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug(string.Format("Event time: {0} current ts: {1}", eventTime, header.Timer)); #endif _lastEventTime = eventTime; return header; }
public static AbstractRtmpMessage Decode(RtmpHeader header, IByteBuffer payload) { AbstractRtmpMessage result = null; short messageTypeId = header.MessageTypeId; switch (messageTypeId) { case Constants.MSG_SET_CHUNK_SIZE: { int readInt = payload.ReadInt(); SetChunkSize setChunkSize = new SetChunkSize(); setChunkSize.ChunkSize = readInt; result = setChunkSize; } break; case Constants.MSG_ABORT_MESSAGE: { int csid = payload.ReadInt(); Abort abort = new Abort(csid); result = abort; } break; case Constants.MSG_ACKNOWLEDGEMENT: { int ack = payload.ReadInt(); result = new Acknowledgement(ack); } break; case Constants.MSG_WINDOW_ACKNOWLEDGEMENT_SIZE: { int size = payload.ReadInt(); result = new WindowAcknowledgementSize(size); } break; case Constants.MSG_SET_PEER_BANDWIDTH: { int ackSize = payload.ReadInt(); int type = payload.ReadByte(); result = new SetPeerBandWidth(ackSize, type); } break; case Constants.MSG_TYPE_COMMAND_AMF0: { List <Object> decode = AMF0.DecodeAll(payload); result = new RtmpCommandMessage(decode); } break; case Constants.MSG_USER_CONTROL_MESSAGE_EVENTS: { short readShort = payload.ReadShort(); int data = payload.ReadInt(); result = new UserControlMessageEvent(readShort, data); } break; case Constants.MSG_TYPE_AUDIO_MESSAGE: { AudioMessage am = new AudioMessage(); byte[] data = ReadAll(payload); am.AudioData = data; if (header.Fmt == Constants.CHUNK_FMT_0) { am.Timestamp = header.Timestamp; } else if (header.Fmt == Constants.CHUNK_FMT_1 || header.Fmt == Constants.CHUNK_FMT_2) { am.TimestampDelta = header.TimestampDelta; } result = am; } break; case Constants.MSG_TYPE_VIDEO_MESSAGE: { VideoMessage vm = new VideoMessage(); byte[] data = ReadAll(payload); vm.VideoData = data; if (header.Fmt == Constants.CHUNK_FMT_0) { vm.Timestamp = header.Timestamp; } else if (header.Fmt == Constants.CHUNK_FMT_1 || header.Fmt == Constants.CHUNK_FMT_2) { vm.TimestampDelta = header.TimestampDelta; } result = vm; } break; case Constants.MSG_TYPE_DATA_MESSAGE_AMF0: { result = new RtmpDataMessage(AMF0.DecodeAll(payload)); } break; default: break; } if (result != null) { result.InboundBodyLength = header.MessageLength; result.InboundHeaderLength = header.HeaderLength; return(result); } else { return(null); } }