示例#1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BroadcastStream"/> class.
 /// </summary>
 /// <param name="name">The stream name.</param>
 /// <param name="scope">The stream scope.</param>
 public BroadcastStream(String name, IScope scope)
 {
     _name     = name;
     _scope    = scope;
     _livePipe = null;
     // We want to create a video codec when we get our first video packet.
     _codecInfo    = new StreamCodecInfo();
     _creationTime = -1;
 }
示例#2
0
        public void DispatchEvent(IEvent evt)
        {
            if (!(evt is IRtmpEvent) &&
                (evt.EventType != EventType.STREAM_CONTROL) &&
                (evt.EventType != EventType.STREAM_DATA) || _closed)
            {
                // ignored event
                if (log.IsDebugEnabled)
                {
                    log.Debug("DispatchEvent: " + evt.EventType);
                }
                return;
            }

            // Get stream codec
            IStreamCodecInfo codecInfo = this.CodecInfo;
            StreamCodecInfo  info      = null;

            if (codecInfo is StreamCodecInfo)
            {
                info = codecInfo as StreamCodecInfo;
            }

            IRtmpEvent rtmpEvent = evt as IRtmpEvent;

            if (rtmpEvent == null)
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("IRtmpEvent expected in event dispatch");
                }
                return;
            }
            int eventTime = -1;

            // If this is first packet save it's timestamp
            if (_firstPacketTime == -1)
            {
                _firstPacketTime = rtmpEvent.Timestamp;
                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("CBS: {0} firstPacketTime={1} {2}", this.Name, _firstPacketTime, rtmpEvent.Header.IsTimerRelative ? "(rel)" : "(abs)"));
                }
            }
            if (rtmpEvent is IStreamData && (rtmpEvent as IStreamData).Data != null)
            {
                _bytesReceived += (rtmpEvent as IStreamData).Data.Limit;
            }

            if (rtmpEvent is AudioData)
            {
                if (info != null)
                {
                    info.HasAudio = true;
                }
                if (rtmpEvent.Header.IsTimerRelative)
                {
                    if (_audioTime == 0)
                    {
                        log.Warn(string.Format("First Audio timestamp is relative! {0}", rtmpEvent.Timestamp));
                    }
                    _audioTime += rtmpEvent.Timestamp;
                }
                else
                {
                    _audioTime = rtmpEvent.Timestamp;
                }
                eventTime = _audioTime;
            }
            else if (rtmpEvent is VideoData)
            {
                IVideoStreamCodec videoStreamCodec = null;
                if (_videoCodecFactory != null && _checkVideoCodec)
                {
                    videoStreamCodec = _videoCodecFactory.GetVideoCodec((rtmpEvent as VideoData).Data);
                    if (codecInfo is StreamCodecInfo)
                    {
                        (codecInfo as StreamCodecInfo).VideoCodec = videoStreamCodec;
                    }
                    _checkVideoCodec = false;
                }
                else if (codecInfo != null)
                {
                    videoStreamCodec = codecInfo.VideoCodec;
                }

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

                if (info != null)
                {
                    info.HasVideo = true;
                }
                if (rtmpEvent.Header.IsTimerRelative)
                {
                    if (_videoTime == 0)
                    {
                        log.Warn(string.Format("First Video timestamp is relative! {0}", rtmpEvent.Timestamp));
                    }
                    _videoTime += rtmpEvent.Timestamp;
                }
                else
                {
                    _videoTime = rtmpEvent.Timestamp;
                    // Flash player may send first VideoData with old-absolute timestamp.
                    // This ruins the stream's timebase in FileConsumer.
                    // We don't want to discard the packet, as it may be a video keyframe.
                    // Generally a Data or Audio packet has set the timebase to a reasonable value,
                    // Eventually a new/correct absolute time will come on the video channel.
                    // We could put this logic between livePipe and filePipe;
                    // This would work for Audio Data as well, but have not seen the need.
                    int cts = Math.Max(_audioTime, _dataTime);
                    cts = Math.Max(cts, _minStreamTime);
                    int fudge = 20;
                    // Accept some slightly (20ms) retro timestamps [this may not be needed,
                    // the publish Data should strictly precede the video data]
                    if (_videoTime + fudge < cts)
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug(string.Format("DispatchEvent: adjust archaic videoTime, from: {0} to {1}", _videoTime, cts));
                        }
                        _videoTime = cts;
                    }
                }
                eventTime = _videoTime;
            }
            else if (rtmpEvent is Invoke)
            {
                if (rtmpEvent.Header.IsTimerRelative)
                {
                    if (_dataTime == 0)
                    {
                        log.Warn(string.Format("First data [Invoke] timestamp is relative! {0}", rtmpEvent.Timestamp));
                    }
                    _dataTime += rtmpEvent.Timestamp;
                }
                else
                {
                    _dataTime = rtmpEvent.Timestamp;
                }
                return;
            }
            else if (rtmpEvent is Notify)
            {
                if (rtmpEvent.Header.IsTimerRelative)
                {
                    if (_dataTime == 0)
                    {
                        log.Warn(string.Format("First data [Notify] timestamp is relative! {0}", rtmpEvent.Timestamp));
                    }
                    _dataTime += rtmpEvent.Timestamp;
                }
                else
                {
                    _dataTime = rtmpEvent.Timestamp;
                }
                eventTime = _dataTime;
            }

            // Notify event listeners
            CheckSendNotifications(evt);

            // Create new RTMP message, initialize it and push through pipe
            FluorineFx.Messaging.Rtmp.Stream.Messages.RtmpMessage msg = new FluorineFx.Messaging.Rtmp.Stream.Messages.RtmpMessage();
            msg.body           = rtmpEvent;
            msg.body.Timestamp = eventTime;
            try
            {
                if (_livePipe != null)
                {
                    _livePipe.PushMessage(msg);
                }
                if (_recordPipe != null)
                {
                    _recordPipe.PushMessage(msg);
                }
            }
            catch (System.IO.IOException ex)
            {
                SendRecordFailedNotify(ex.Message);
                Stop();
            }

            // 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(string.Format("Error while notifying listener {0}", listener), ex);
                    }
                }
            }
        }
 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();
         }
     }
 }