Esempio n. 1
0
        public void SendAmf0Data(RtmpMessage e)
        {
            var timestamp = (int)(DateTime.UtcNow - connectTime).TotalMilliseconds;

            e.Timestamp = timestamp;
            writer.Queue(e, e.Header.StreamId, e.Header.MessageStreamId);
        }
Esempio n. 2
0
 /// <summary>
 /// Stops the server-side stream.
 /// </summary>
 public override void Stop()
 {
     lock (this.SyncRoot)
     {
         if (_state != State.PLAYING && _state != State.PAUSED)
         {
             return;
         }
         if (_liveJobName != null)
         {
             _schedulingService.RemoveScheduledJob(_liveJobName);
             _liveJobName = null;
         }
         if (_vodJobName != null)
         {
             _schedulingService.RemoveScheduledJob(_vodJobName);
             _vodJobName = null;
         }
         if (_msgIn != null)
         {
             _msgIn.Unsubscribe(this);
             _msgIn = null;
         }
         if (_nextRTMPMessage != null)
         {
             _nextRTMPMessage = null;
         }
         _state = State.STOPPED;
     }
 }
Esempio n. 3
0
        protected override Task ProcessDataMessageAsync(RtmpMessage message)
        {
            AmfDataMessage command = new AmfDataMessage();

            command.Decode(message.Payload.Span);
            _logger.LogInformation($"Data command received {command.Name} {command.AdditionalArguments[0]}");
            return(Task.CompletedTask);
        }
        private void HandleResponse(AmfCommandMessage command, RtmpMessage message)
        {
            var result = new CommandArgs
            {
                Command = command
            };

            ResponseReceived?.Invoke(this, result);
        }
 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());
         }
 }
Esempio n. 6
0
        public IMessage PullMessage(IPipe pipe)
        {
            lock (_syncLock)
            {
                if (_pipe != pipe)
                {
                    return(null);
                }
                if (_reader == null)
                {
                    Init();
                }
                if (!_reader.HasMoreTags())
                {
                    // TODO send OOBCM to notify EOF
                    // Do not unsubscribe as this kills VOD seek while in buffer
                    // this.pipe.unsubscribe(this);
                    return(null);
                }
                ITag       tag       = _reader.ReadTag();
                IRtmpEvent msg       = null;
                int        timestamp = tag.Timestamp;
                switch (tag.DataType)
                {
                case Constants.TypeAudioData:
                    msg = new AudioData(tag.Body);
                    break;

                case Constants.TypeVideoData:
                    msg = new VideoData(tag.Body);
                    break;

                case Constants.TypeInvoke:
                    msg = new Invoke(tag.Body);
                    break;

                case Constants.TypeNotify:
                    msg = new Notify(tag.Body);
                    break;

                case Constants.TypeFlexStreamEnd:
                    msg = new FlexStreamSend(tag.Body);
                    break;

                default:
                    log.Warn("Unexpected type " + tag.DataType);
                    msg = new Unknown(tag.DataType, tag.Body);
                    break;
                }
                msg.Timestamp = timestamp;
                RtmpMessage rtmpMsg = new RtmpMessage();
                rtmpMsg.body = msg;
                return(rtmpMsg);
            }
        }
Esempio n. 7
0
            public void QueueWrite(RtmpMessage message, int chunkStreamId, bool external = true)
            {
                // we save ourselves from synchronizing on chunk length because we never modify it post-initialization
                if (external && message is ChunkLength)
                {
                    throw new InvalidOperationException("cannot modify chunk length after stream has begun");
                }

                queue.Enqueue(new Packet(chunkStreamId, message.ContentType, Serialize(message)));
                reset.Set();
            }
        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();
        }
Esempio n. 9
0
        /// <summary>
        /// Pull the next message from IMessageInput and schedule it for push according to the timestamp.
        /// </summary>
        protected void ScheduleNextMessage()
        {
            bool first = _nextRTMPMessage == null;
            long delta;

            while (true)
            {
                _nextRTMPMessage = GetNextRTMPMessage();
                if (_nextRTMPMessage == null)
                {
                    OnItemEnd();
                    return;
                }

                IRtmpEvent rtmpEvent = _nextRTMPMessage.body;
                // filter all non-AV messages
                if (!(rtmpEvent is VideoData) &&
                    !(rtmpEvent is AudioData))
                {
                    continue;
                }
                rtmpEvent = _nextRTMPMessage.body;
                _nextTS   = rtmpEvent.Timestamp;
                if (first)
                {
                    _vodStartTS = _nextTS;
                    first       = false;
                }

                delta = _nextTS - _vodStartTS - (System.Environment.TickCount - _serverStartTS);
                if (delta < WAIT_THRESHOLD)
                {
                    if (!DoPushMessage())
                    {
                        return;
                    }
                    if (_state != State.PLAYING)
                    {
                        // Stream is paused, don't load more messages
                        _nextRTMPMessage = null;
                        return;
                    }
                }
                else
                {
                    break;
                }
            }
            VODScheduledJob job = new VODScheduledJob(this);

            _vodJobName = _schedulingService.AddScheduledOnceJob(delta, job);
        }
Esempio n. 10
0
        void WriteData(AmfWriter writer, RtmpMessage o, ObjectEncoding encoding)
        {
            var command = o as Command;

            if (command.MethodCall == null)
            {
                WriteCommandOrData(writer, o, encoding);
            }
            else
            {
                writer.WriteBytes(command.Buffer);
            }
        }
        protected override Task ProcessCommandAsync(AmfCommandMessage command, RtmpMessage message)
        {
            switch (command.Name)
            {
            case "_result":
            case "onStatus":
                HandleResponse(command, message);
                break;

            default:
                throw new InvalidOperationException($"Unknown command {command.Name} {command.CommandObject} ");
            }
            return(Task.CompletedTask);
        }
Esempio n. 12
0
        public bool CanSendPacket(RtmpMessage message, long pending)
        {
            IRtmpEvent body = message.body;

            if (!(body is VideoData))
            {
                return(true);
            }
            VideoData data      = body as VideoData;
            FrameType frameType = data.FrameType;
            bool      flag      = false;

            switch (this._state)
            {
            case FrameDropperState.SEND_ALL:
                return(true);

            case FrameDropperState.SEND_INTERFRAMES:
                if (frameType != FrameType.KEYFRAME)
                {
                    if (frameType == FrameType.INTERFRAME)
                    {
                        flag = true;
                    }
                    return(flag);
                }
                if (pending == 0L)
                {
                    this._state = FrameDropperState.SEND_ALL;
                }
                return(true);

            case FrameDropperState.SEND_KEYFRAMES:
                flag = frameType == FrameType.KEYFRAME;
                if (flag && (pending == 0L))
                {
                    this._state = FrameDropperState.SEND_KEYFRAMES_CHECK;
                }
                return(flag);

            case FrameDropperState.SEND_KEYFRAMES_CHECK:
                flag = frameType == FrameType.KEYFRAME;
                if (flag && (pending == 0L))
                {
                    this._state = FrameDropperState.SEND_INTERFRAMES;
                }
                return(flag);
            }
            return(flag);
        }
Esempio n. 13
0
 public void PushMessage(IPipe pipe, IMessage message)
 {
     lock (this.SyncRoot)
     {
         if (message is ResetMessage)
         {
             this._startTimestamp = -1;
             this._offset        += this._lastTimestamp;
         }
         else if (!(message is StatusMessage) && (message is RtmpMessage))
         {
             if (this._writer == null)
             {
                 this.Init();
             }
             RtmpMessage message2 = message as RtmpMessage;
             IRtmpEvent  body     = message2.body;
             if (this._startTimestamp == -1)
             {
                 this._startTimestamp = body.Timestamp;
             }
             int num = body.Timestamp - this._startTimestamp;
             if (num < 0)
             {
                 log.Warn("Skipping message with negative timestamp.");
             }
             else
             {
                 this._lastTimestamp = num;
                 ITag tag = new Tag {
                     DataType  = body.DataType,
                     Timestamp = num + this._offset
                 };
                 if (body is IStreamData)
                 {
                     tag.Body = (body as IStreamData).Data.ToArray();
                 }
                 try
                 {
                     this._writer.WriteTag(tag);
                 }
                 catch (IOException exception)
                 {
                     log.Error("Error writing tag", exception);
                 }
             }
         }
     }
 }
Esempio n. 14
0
        byte[] GetMessageBytes(FlvTagHeader header, RtmpMessage 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);
            }
        }
Esempio n. 15
0
 private void StartBroadcastVOD()
 {
     _nextRTMPMessage = null;
     _vodStartTS = 0;
     _serverStartTS = System.Environment.TickCount;
     IStreamAwareScopeHandler handler = GetStreamAwareHandler();
     if (handler != null)
     {
         if (_recordingFilename != null)
             handler.StreamRecordStart(this);
         else
             handler.StreamPublishStart(this);
     }
     NotifyBroadcastStart();
     ScheduleNextMessage();
 }
Esempio n. 16
0
        public void DropPacket(RtmpMessage message)
        {
            IRtmpEvent body = message.body;

            if (body is VideoData)
            {
                VideoData data      = body as VideoData;
                FrameType frameType = data.FrameType;
                switch (this._state)
                {
                case FrameDropperState.SEND_ALL:
                    if (frameType != FrameType.DISPOSABLE_INTERFRAME)
                    {
                        if (frameType == FrameType.INTERFRAME)
                        {
                            this._state = FrameDropperState.SEND_KEYFRAMES;
                        }
                        else if (frameType == FrameType.KEYFRAME)
                        {
                            this._state = FrameDropperState.SEND_KEYFRAMES;
                        }
                        break;
                    }
                    break;

                case FrameDropperState.SEND_INTERFRAMES:
                    if (frameType != FrameType.INTERFRAME)
                    {
                        if (frameType == FrameType.KEYFRAME)
                        {
                            this._state = FrameDropperState.SEND_KEYFRAMES;
                        }
                        break;
                    }
                    this._state = FrameDropperState.SEND_KEYFRAMES_CHECK;
                    break;

                case FrameDropperState.SEND_KEYFRAMES_CHECK:
                    if (frameType == FrameType.KEYFRAME)
                    {
                        this._state = FrameDropperState.SEND_KEYFRAMES;
                    }
                    break;
                }
            }
        }
Esempio n. 17
0
        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)
            if (methodCall.Name == "@setDataFrame")
            {
                writer.WriteAmfItem(encoding, command.ConnectionParameters);
            }

            // write arguments
            foreach (var arg in methodCall.Parameters)
            {
                writer.WriteAmfItem(encoding, arg);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Send VOD seek control message
        /// </summary>
        /// <param name="msgIn">Message input</param>
        /// <param name="position">New timestamp to play from</param>
        private void SendVODSeekCM(IMessageInput msgIn, int position)
        {
            OOBControlMessage oobCtrlMsg = new OOBControlMessage();

            oobCtrlMsg.Target      = typeof(ISeekableProvider).Name;
            oobCtrlMsg.ServiceName = "seek";
            oobCtrlMsg.ServiceParameterMap.Add("position", position);
            msgIn.SendOOBControlMessage(this, oobCtrlMsg);

            lock (this.SyncRoot)
            {
                // Reset properties
                _vodStartTS    = 0;
                _serverStartTS = System.Environment.TickCount;
                if (_nextRTMPMessage != null)
                {
                    try
                    {
                        PushMessage(_nextRTMPMessage);
                    }
                    catch (IOException ex)
                    {
                        log.Error("Error while sending message.", ex);
                    }
                    _nextRTMPMessage = null;
                }
                ResetMessage reset = new ResetMessage();
                try
                {
                    PushMessage(reset);
                }
                catch (IOException ex)
                {
                    log.Error("Error while sending message.", ex);
                }
                ScheduleNextMessage();
            }
        }
Esempio n. 19
0
            // most rtmp servers we are interested in only support amf3 via an amf0 envelope
            static void WriteCommand(ObjectEncoding encoding, AmfWriter w, RtmpMessage message)
            {
                switch (message)
                {
                case Notify notify:
                    w.WriteBoxedAmf0Object(encoding, notify.Data);
                    break;

                case Invoke request:
                    w.WriteBoxedAmf0Object(encoding, request.MethodName);
                    w.WriteBoxedAmf0Object(encoding, request.InvokeId);
                    w.WriteBoxedAmf0Object(encoding, request.Headers);

                    foreach (var arg in request.Arguments ?? EmptyArray <object> .Instance)
                    {
                        w.WriteBoxedAmf0Object(encoding, arg);
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
Esempio n. 20
0
 protected override Task ProcessMediaMessageAsync(RtmpMessage message)
 {
     MediaReceived?.Invoke(this, new EventArgs <RtmpMessage>(message));
     return(Task.CompletedTask);
 }
Esempio n. 21
0
        public bool CanSendPacket(RtmpMessage message, long pending)
        {
            IRtmpEvent packet = message.body;

            if (!(packet is VideoData))
            {
                // We currently only drop video packets.
                return(true);
            }

            VideoData video  = packet as VideoData;
            FrameType type   = video.FrameType;
            bool      result = false;

            switch (_state)
            {
            case FrameDropperState.SEND_ALL:
                // All packets will be sent.
                result = true;
                break;

            case FrameDropperState.SEND_INTERFRAMES:
                // Only keyframes and interframes will be sent.
                if (type == FrameType.Keyframe)
                {
                    if (pending == 0)
                    {
                        // Send all frames from now on.
                        _state = FrameDropperState.SEND_ALL;
                    }
                    result = true;
                }
                else if (type == FrameType.Interframe)
                {
                    result = true;
                }
                break;

            case FrameDropperState.SEND_KEYFRAMES:
                // Only keyframes will be sent.
                result = (type == FrameType.Keyframe);
                if (result && pending == 0)
                {
                    // Maybe switch back to SEND_INTERFRAMES after the next keyframe
                    _state = FrameDropperState.SEND_KEYFRAMES_CHECK;
                }
                break;

            case FrameDropperState.SEND_KEYFRAMES_CHECK:
                // Only keyframes will be sent.
                result = (type == FrameType.Keyframe);
                if (result && pending == 0)
                {
                    // Continue with sending interframes as well
                    _state = FrameDropperState.SEND_INTERFRAMES;
                }
                break;

            default:
                break;
            }
            return(result);
        }
Esempio n. 22
0
 public void SendPacket(RtmpMessage message)
 {
 }
Esempio n. 23
0
        public void DropPacket(RtmpMessage message)
        {
            IRtmpEvent packet = message.body;

            if (!(packet is VideoData))
            {
                // Only check video packets.
                return;
            }

            VideoData video = packet as VideoData;
            FrameType type  = video.FrameType;

            switch (_state)
            {
            case FrameDropperState.SEND_ALL:
                if (type == FrameType.DisposableInterframe)
                {
                    // Remain in state, packet is safe to drop.
                    return;
                }
                else if (type == FrameType.Interframe)
                {
                    // Drop all frames until the next keyframe.
                    _state = FrameDropperState.SEND_KEYFRAMES;
                    return;
                }
                else if (type == FrameType.Keyframe)
                {
                    // Drop all frames until the next keyframe.
                    _state = FrameDropperState.SEND_KEYFRAMES;
                    return;
                }
                break;

            case FrameDropperState.SEND_INTERFRAMES:
                if (type == FrameType.Interframe)
                {
                    // Drop all frames until the next keyframe.
                    _state = FrameDropperState.SEND_KEYFRAMES_CHECK;
                    return;
                }
                else if (type == FrameType.Keyframe)
                {
                    // Drop all frames until the next keyframe.
                    _state = FrameDropperState.SEND_KEYFRAMES;
                    return;
                }
                break;

            case FrameDropperState.SEND_KEYFRAMES:
                // Remain in state.
                break;

            case FrameDropperState.SEND_KEYFRAMES_CHECK:
                if (type == FrameType.Keyframe)
                {
                    // Switch back to sending keyframes, but don't move to SEND_INTERFRAMES afterwards.
                    _state = FrameDropperState.SEND_KEYFRAMES;
                    return;
                }
                break;

            default:
                break;
            }
        }
 public EventReceivedEventArgs(RtmpMessage @event)
 {
     this.Event = @event;
 }
 public void DispatchEvent(IEvent evt)
 {
     if (((!(evt is IRtmpEvent) && (evt.EventType != EventType.STREAM_CONTROL)) && (evt.EventType != EventType.STREAM_DATA)) || this._closed)
     {
         if (log.get_IsDebugEnabled())
         {
             log.Debug("DispatchEvent: " + evt.EventType);
         }
     }
     else
     {
         IStreamCodecInfo codecInfo = base.CodecInfo;
         StreamCodecInfo  info2     = null;
         if (codecInfo is StreamCodecInfo)
         {
             info2 = codecInfo as StreamCodecInfo;
         }
         IRtmpEvent event2 = evt as IRtmpEvent;
         int        num    = -1;
         if (this._firstPacketTime == -1)
         {
             this._firstPacketTime = event2.Timestamp;
         }
         if (event2 is AudioData)
         {
             if (info2 != null)
             {
                 info2.HasAudio = true;
             }
             if (event2.Header.IsTimerRelative)
             {
                 this._audioTime += event2.Timestamp;
             }
             else
             {
                 this._audioTime = event2.Timestamp;
             }
             num = this._audioTime;
         }
         else if (event2 is VideoData)
         {
             IVideoStreamCodec videoCodec = null;
             if ((this._videoCodecFactory != null) && this._checkVideoCodec)
             {
                 videoCodec = this._videoCodecFactory.GetVideoCodec((event2 as VideoData).Data);
                 if (codecInfo is StreamCodecInfo)
                 {
                     (codecInfo as StreamCodecInfo).VideoCodec = videoCodec;
                 }
                 this._checkVideoCodec = false;
             }
             else if (codecInfo != null)
             {
                 videoCodec = codecInfo.VideoCodec;
             }
             if (videoCodec != null)
             {
                 videoCodec.AddData((event2 as VideoData).Data);
             }
             if (info2 != null)
             {
                 info2.HasVideo = true;
             }
             if (event2.Header.IsTimerRelative)
             {
                 this._videoTime += event2.Timestamp;
             }
             else
             {
                 this._videoTime = event2.Timestamp;
             }
             num = this._videoTime;
         }
         else
         {
             if (event2 is Invoke)
             {
                 if (event2.Header.IsTimerRelative)
                 {
                     this._dataTime += event2.Timestamp;
                 }
                 else
                 {
                     this._dataTime = event2.Timestamp;
                 }
                 return;
             }
             if (event2 is Notify)
             {
                 if (event2.Header.IsTimerRelative)
                 {
                     this._dataTime += event2.Timestamp;
                 }
                 else
                 {
                     this._dataTime = event2.Timestamp;
                 }
                 num = this._dataTime;
             }
         }
         if ((event2 is IStreamData) && ((event2 as IStreamData).Data != null))
         {
             this._bytesReceived += (event2 as IStreamData).Data.Limit;
         }
         this.CheckSendNotifications(evt);
         RtmpMessage message = new RtmpMessage {
             body = event2
         };
         message.body.Timestamp = num;
         try
         {
             if (this._livePipe != null)
             {
                 this._livePipe.PushMessage(message);
             }
             if (this._recordPipe != null)
             {
                 this._recordPipe.PushMessage(message);
             }
         }
         catch (IOException exception)
         {
             this.SendRecordFailedNotify(exception.Message);
             this.Stop();
         }
     }
 }
Esempio n. 26
0
        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;
                }
            }
        }
Esempio n. 27
0
        public void DispatchEvent(IEvent @event)
        {
            try
            {
                if (@event is IRtmpEvent)
                {
                    IRtmpEvent rtmpEvent = @event as IRtmpEvent;
                    if (_livePipe != null)
                    {
                        RtmpMessage msg = new RtmpMessage();
                        msg.body = rtmpEvent;
                        if (_creationTime == -1)
                        {
                            _creationTime = rtmpEvent.Timestamp;
                        }
                        try
                        {
                            if (@event is AudioData)
                            {
                                (_codecInfo as StreamCodecInfo).HasAudio = true;
                            }
                            else if (@event is VideoData)
                            {
                                IVideoStreamCodec videoStreamCodec = null;
                                if (_codecInfo.VideoCodec == null)
                                {
                                    videoStreamCodec = _videoCodecFactory.GetVideoCodec((@event as VideoData).Data);
                                    (_codecInfo as StreamCodecInfo).VideoCodec = videoStreamCodec;
                                }
                                else if (_codecInfo != null)
                                {
                                    videoStreamCodec = _codecInfo.VideoCodec;
                                }

                                if (videoStreamCodec != null)
                                {
                                    videoStreamCodec.AddData((rtmpEvent as VideoData).Data);
                                }

                                if (_codecInfo != null)
                                {
                                    (_codecInfo as StreamCodecInfo).HasVideo = true;
                                }
                            }
                            _livePipe.PushMessage(msg);

                            // Notify listeners about received packet
                            if (rtmpEvent is IStreamPacket)
                            {
                                foreach (IStreamListener listener in GetStreamListeners())
                                {
                                    try
                                    {
                                        listener.PacketReceived(this, rtmpEvent as IStreamPacket);
                                    }
                                    catch (Exception ex)
                                    {
                                        log.Error("Error while notifying listener " + listener, ex);
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            // ignore
                            log.Error("DispatchEvent exception", ex);
                        }
                    }
                }
            }
            finally
            {
            }
        }
Esempio n. 28
0
 protected override async Task ProcessCommandMessageAsync(RtmpMessage message)
 {
     await _commandProcessor.ProcessMessageAsync(message);
 }
Esempio n. 29
0
        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);
                }
            }
        }
Esempio n. 30
0
            Space <byte> Serialize(RtmpMessage message)
            {
                // (this comment must be kept in sync at rtmpclient.reader.cs and rtmpclient.writer.cs)
                //
                // unsupported type summary:
                //
                // - aggregate:      we have never encountered this packet in the wild
                // - shared objects: we have not found a use case for this
                // - data commands:  we have not found a use case for this, though it should be extremely easy to
                //                       support. it's just a one-way equivalent of command (invoke). that is, we don't
                //                       generate an invoke id for it, and it does not contain headers. other than that,
                //                       they're identical. we can use existing logic and add if statements to surround
                //                       writing the invokeid + headers if needed.

                const int WriteInitialBufferLength = 4192;

                var w = new AmfWriter(WriteInitialBufferLength, context);

                switch (message.ContentType)
                {
                case PacketContentType.SetChunkSize:
                    var a = (ChunkLength)message;
                    w.WriteInt32(a.Length);
                    break;

                case PacketContentType.AbortMessage:
                    var b = (Abort)message;
                    w.WriteInt32(b.ChunkStreamId);
                    break;

                case PacketContentType.Acknowledgement:
                    var c = (Acknowledgement)message;
                    w.WriteUInt32(c.TotalRead);
                    break;

                case PacketContentType.UserControlMessage:
                    var d = (UserControlMessage)message;

                    w.WriteUInt16((ushort)d.EventType);
                    foreach (var value in d.Values)
                    {
                        w.WriteUInt32(value);
                    }

                    break;

                case PacketContentType.WindowAcknowledgementSize:
                    var e = (WindowAcknowledgementSize)message;
                    w.WriteInt32(e.Count);
                    break;

                case PacketContentType.SetPeerBandwith:
                    var f = (PeerBandwidth)message;
                    w.WriteInt32(f.AckWindowSize);
                    w.WriteByte((byte)f.LimitType);
                    break;

                case PacketContentType.Audio:
                case PacketContentType.Video:
                    var g = (ByteData)message;
                    w.WriteBytes(g.Data);
                    break;

                case PacketContentType.DataAmf0:
                    throw NotSupportedException("data-amf0");

                case PacketContentType.SharedObjectAmf0:
                    throw NotSupportedException("sharedobject-amf0");

                case PacketContentType.CommandAmf0:
                    WriteCommand(ObjectEncoding.Amf0, w, message);
                    break;

                case PacketContentType.DataAmf3:
                    throw NotSupportedException("data-amf3");

                case PacketContentType.SharedObjectAmf3:
                    throw NotSupportedException("sharedobject-amf0");

                case PacketContentType.CommandAmf3:
                    // first byte is an encoding specifier byte.
                    //     see `writecommand` comment below: specify amf0 object encoding and elevate into amf3.
                    w.WriteByte((byte)ObjectEncoding.Amf0);
                    WriteCommand(ObjectEncoding.Amf3, w, message);
                    break;

                case PacketContentType.Aggregate:
                    throw NotSupportedException("aggregate");

                default:
                    throw NotSupportedException($"unknown ({message.ContentType})");
                }

                return(w.Span);
            }