Ejemplo n.º 1
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;
     }
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Send VOD init control message
 /// </summary>
 /// <param name="msgIn"></param>
 /// <param name="start"></param>
 private void SendVODInitCM(IMessageInput msgIn, int start)
 {
     OOBControlMessage oobCtrlMsg = new OOBControlMessage();
     oobCtrlMsg.Target = typeof(IPassive).Name;
     oobCtrlMsg.ServiceName = "init";
     oobCtrlMsg.ServiceParameterMap.Add("startTS", start);
     _msgIn.SendOOBControlMessage(this, oobCtrlMsg);
 }
Ejemplo n.º 3
0
        public IMessageInput GetProviderInput(IScope scope, string name)
        {
            IMessageInput input = this.GetLiveProviderInput(scope, name, false);

            if (input == null)
            {
                return(this.GetVODProviderInput(scope, name));
            }
            return(input);
        }
Ejemplo n.º 4
0
        public IMessageInput GetProviderInput(IScope scope, string name)
        {
            IMessageInput msgIn = GetLiveProviderInput(scope, name, false);

            if (msgIn == null)
            {
                return(GetVODProviderInput(scope, name));
            }
            return(msgIn);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Play a specific IPlayItem.
        /// The strategy for now is VOD first, Live second.
        /// </summary>
        /// <param name="item">Item to play</param>
        protected void Play(IPlayItem item)
        {
            // Return if already playing
            if (_state != State.STOPPED)
            {
                return;
            }
            // Assume this is not live stream
            bool             isLive          = false;
            IProviderService providerService = ScopeUtils.GetScopeService(this.Scope, typeof(IProviderService)) as IProviderService;

            _msgIn = providerService.GetVODProviderInput(this.Scope, item.Name);
            if (_msgIn == null)
            {
                _msgIn = providerService.GetLiveProviderInput(this.Scope, item.Name, true);
                isLive = true;
            }
            if (_msgIn == null)
            {
                log.Warn("Can't get both VOD and Live input from providerService");
                return;
            }
            _state       = State.PLAYING;
            _currentItem = item;
            SendResetMessage();
            _msgIn.Subscribe(this, null);
            if (isLive)
            {
                if (item.Length >= 0)
                {
                    PlayItemScheduledJob job = new PlayItemScheduledJob(this);
                    _liveJobName = _schedulingService.AddScheduledOnceJob(item.Length, job);
                }
            }
            else
            {
                long start = item.Start;
                if (start < 0)
                {
                    start = 0;
                }
                SendVODInitCM(_msgIn, (int)start);
                StartBroadcastVOD();
            }
        }
Ejemplo n.º 6
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();
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Play stream
        /// </summary>
        /// <param name="item">Playlist item.</param>
        /// <param name="withReset">Send reset status before playing.</param>
        public void Play(IPlayItem item, bool withReset)
        {
            lock (this.SyncRoot)
            {
                // Can't play if state is not stopped
                if (_playlistSubscriberStream.State != State.STOPPED)
                    throw new IllegalStateException();
                if (_msgIn != null)
                {
                    _msgIn.Unsubscribe(this);
                    _msgIn = null;
                }
                // Play type determination
                // http://livedocs.adobe.com/flex/3/langref/flash/net/NetStream.html#play%28%29
                // The start time, in seconds. Allowed values are -2, -1, 0, or a positive number. 
                // The default value is -2, which looks for a live stream, then a recorded stream, 
                // and if it finds neither, opens a live stream. 
                // If -1, plays only a live stream. 
                // If 0 or a positive number, plays a recorded stream, beginning start seconds in.
                //
                // -2: live then recorded, -1: live, >=0: recorded
                int type = (int)(item.Start / 1000);
                // see if it's a published stream
                IScope thisScope = _playlistSubscriberStream.Scope;
                string itemName = item.Name;
                //check for input and type
                InputType sourceType = _providerService.LookupProviderInputType(thisScope, itemName);

                bool isPublishedStream = sourceType == InputType.Live;
                bool isFileStream = sourceType == InputType.Vod;
                bool sendNotifications = true;

                // decision: 0 for Live, 1 for File, 2 for Wait, 3 for N/A
                switch (type)
                {
                    case -2:
                        if (isPublishedStream)
                            _playDecision = 0;
                        else if (isFileStream)
                            _playDecision = 1;
                        else
                            _playDecision = 2;
                        break;
                    case -1:
                        if (isPublishedStream)
                            _playDecision = 0;
                        else
                            _playDecision = 2;
                        break;
                    default:
                        if (isFileStream)
                            _playDecision = 1;
                        break;
                }
                if (log.IsDebugEnabled)
                    log.Debug(string.Format("Play decision is {0} (0=Live, 1=File, 2=Wait, 3=N/A)", _playDecision));
                _currentItem = item;
                long itemLength = item.Length;
                switch (_playDecision)
                {
                    case 0:
                        //get source input without create
                        _msgIn = _providerService.GetLiveProviderInput(thisScope, itemName, false);
                        // Drop all frames up to the next keyframe
                        _videoFrameDropper.Reset(FrameDropperState.SEND_KEYFRAMES_CHECK);
                        if (_msgIn is IBroadcastScope)
                        {
                            // Send initial keyframe
                            IClientBroadcastStream stream = (_msgIn as IBroadcastScope).GetAttribute(Constants.BroadcastScopeStreamAttribute) as IClientBroadcastStream;
                            if (stream != null && stream.CodecInfo != null)
                            {
                                IVideoStreamCodec videoCodec = stream.CodecInfo.VideoCodec;
                                if (videoCodec != null)
                                {
                                    if (withReset)
                                    {
                                        SendReset();
                                        SendResetStatus(item);
                                        SendStartStatus(item);
                                    }
                                    sendNotifications = false;
                                    //send decoder configuration if it exists
                                    ByteBuffer config = videoCodec.GetDecoderConfiguration();
                                    if (config != null)
                                    {
                                        VideoData conf = new VideoData(config);
                                        try
                                        {
                                            conf.Timestamp = 0;
                                            RtmpMessage confMsg = new RtmpMessage();
                                            confMsg.body = conf;
                                            _msgOut.PushMessage(confMsg);
                                        }
                                        finally
                                        {
                                            //conf.release();
                                        }
                                    }
                                    //Check for a keyframe to send
                                    ByteBuffer keyFrame = videoCodec.GetKeyframe();
                                    if (keyFrame != null)
                                    {
                                        VideoData video = new VideoData(keyFrame);
                                        try
                                        {
                                            video.Timestamp = 0;
                                            RtmpMessage videoMsg = new RtmpMessage();
                                            videoMsg.body = video;
                                            _msgOut.PushMessage(videoMsg);
                                            // Don't wait for keyframe
                                            _videoFrameDropper.Reset();
                                        }
                                        finally
                                        {
                                            //video.release();
                                        }
                                    }
                                }
                            }
                        }
                        _msgIn.Subscribe(this, null);
                        break;
                    case 2:
                        //get source input with create
                        _msgIn = _providerService.GetLiveProviderInput(thisScope, itemName, true);
                        _msgIn.Subscribe(this, null);
                        _waiting = true;
                        if (type == -1 && itemLength >= 0)
                        {
                            //log.debug("Creating wait job");
                            // Wait given timeout for stream to be published
                            PlaylistSubscriberStreamJob1 job = new PlaylistSubscriberStreamJob1(this, itemName);
                            _waitLiveJob = _schedulingService.AddScheduledOnceJob(item.Length, job);
                        }
                        else if (type == -2)
                        {
                            //log.debug("Creating wait job");
                            // Wait x seconds for the stream to be published
                            PlaylistSubscriberStreamJob2 job = new PlaylistSubscriberStreamJob2(this, itemName);
                            _waitLiveJob = _schedulingService.AddScheduledOnceJob(15000, job);
                        }
                        else
                        {
                            ConnectToProvider(itemName);
                        }
                        break;
                    case 1:
                        _msgIn = _providerService.GetVODProviderInput(thisScope, itemName);
                        if (_msgIn == null)
                        {
                            SendStreamNotFoundStatus(_currentItem);
                            throw new StreamNotFoundException(itemName);
                        }
                        if (!_msgIn.Subscribe(this, null))
                        {
                            log.Error("Input source subscribe failed");
                        }
                        break;
                    default:
                        SendStreamNotFoundStatus(_currentItem);
                        throw new StreamNotFoundException(itemName);
                }
                _playlistSubscriberStream.State = State.PLAYING;
                IMessage msg = null;
                _streamOffset = 0;
                _streamStartTS = -1;
                if (_playDecision == 1)
                {
                    if (withReset)
                    {
                        ReleasePendingMessage();
                    }
                    SendVODInitCM(_msgIn, item);
                    // Don't use pullAndPush to detect IOExceptions prior to sending NetStream.Play.Start
                    if (item.Start > 0)
                    {
                        _streamOffset = SendVODSeekCM(_msgIn, (int)item.Start);
                        // We seeked to the nearest keyframe so use real timestamp now
                        if (_streamOffset == -1)
                        {
                            _streamOffset = (int)item.Start;
                        }
                    }
                    msg = _msgIn.PullMessage();
                    if (msg is RtmpMessage)
                    {
                        IRtmpEvent body = ((RtmpMessage)msg).body;
                        if (itemLength == 0)
                        {
                            // Only send first video frame
                            body = ((RtmpMessage)msg).body;
                            while (body != null && !(body is VideoData))
                            {
                                msg = _msgIn.PullMessage();
                                if (msg == null)
                                    break;
                                if (msg is RtmpMessage)
                                    body = ((RtmpMessage)msg).body;
                            }
                        }
                        if (body != null)
                        {
                            // Adjust timestamp when playing lists
                            body.Timestamp = body.Timestamp + _timestampOffset;
                        }
                    }
                }
                if (sendNotifications)
                {
                    if (withReset)
                    {
                        SendReset();
                        SendResetStatus(item);
                    }
                    SendStartStatus(item);
                    if (!withReset)
                    {
                        SendSwitchStatus();
                    }
                }
                if (msg != null)
                {
                    SendMessage((RtmpMessage)msg);
                }
                _playlistSubscriberStream.NotifyItemPlay(_currentItem, !_isPullMode);
                if (withReset)
                {
                    long currentTime = System.Environment.TickCount;
                    _playbackStart = currentTime - _streamOffset;
                    _nextCheckBufferUnderrun = currentTime + _bufferCheckInterval;
                    if (_currentItem.Length != 0)
                    {
                        EnsurePullAndPushRunning();
                    }
                }
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Close stream
 /// </summary>
 public void Close()
 {
     lock (this.SyncRoot)
     {
         if (_msgIn != null)
         {
             _msgIn.Unsubscribe(this);
             _msgIn = null;
         }
         _playlistSubscriberStream.State = State.CLOSED;
         ClearWaitJobs();
         ReleasePendingMessage();
         _lastMessage = null;
         SendClearPing();
     }
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Stop playback
 /// </summary>
 public void Stop()
 {
     lock (this.SyncRoot)
     {
         if (_playlistSubscriberStream.State != State.PLAYING && _playlistSubscriberStream.State != State.PAUSED)
             throw new IllegalStateException();
         _playlistSubscriberStream.State = State.STOPPED;
         if (_msgIn != null && !_isPullMode)
         {
             _msgIn.Unsubscribe(this);
             _msgIn = null;
         }
         _playlistSubscriberStream.NotifyItemStop(_currentItem);
         ClearWaitJobs();
         if (!_playlistSubscriberStream.HasMoreItems)
         {
             ReleasePendingMessage();
             _bwController.ResetBuckets(_bwContext);
             _waitingForToken = false;
             if (_playlistSubscriberStream.ItemSize > 0)
                 SendCompleteStatus();
             _bytesSent = 0;
             SendClearPing();
             SendStopStatus(_currentItem);
         }
         else
         {
             if (_lastMessage != null)
             {
                 // Remember last timestamp so we can generate correct headers in playlists.
                 _timestampOffset = _lastMessage.Timestamp;
             }
             _playlistSubscriberStream.NextItem();
         }
     }
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Send VOD check video control message
 /// </summary>
 /// <param name="msgIn"></param>
 /// <returns></returns>
 private bool SendCheckVideoCM(IMessageInput msgIn)
 {
     OOBControlMessage oobCtrlMsg = new OOBControlMessage();
     oobCtrlMsg.Target = typeof(IStreamTypeAwareProvider).Name;
     oobCtrlMsg.ServiceName = "hasVideo";
     msgIn.SendOOBControlMessage(this, oobCtrlMsg);
     if (oobCtrlMsg.Result is Boolean)
     {
         return (Boolean)oobCtrlMsg.Result;
     }
     else
     {
         return false;
     }
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Send VOD seek control message
 /// </summary>
 /// <param name="msgIn"></param>
 /// <param name="position"></param>
 /// <returns></returns>            
 private int 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);
     if (oobCtrlMsg.Result is int)
     {
         return (int)oobCtrlMsg.Result;
     }
     else
     {
         return -1;
     }
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Send VOD init control message
 /// </summary>
 /// <param name="msgIn"></param>
 /// <param name="item"></param>
 private void SendVODInitCM(IMessageInput msgIn, IPlayItem item)
 {
     OOBControlMessage oobCtrlMsg = new OOBControlMessage();
     oobCtrlMsg.Target = typeof(IPassive).Name;
     oobCtrlMsg.ServiceName = "init";
     oobCtrlMsg.ServiceParameterMap.Add("startTS", item.Start);
     _msgIn.SendOOBControlMessage(this, oobCtrlMsg);
 }
Ejemplo n.º 13
0
 private void ConnectToProvider(string itemName)
 {
     if (log.IsDebugEnabled)
         log.Debug(string.Format("Attempting connection to {0}", itemName));
     IScope thisScope = _playlistSubscriberStream.Scope;
     _msgIn = _providerService.GetLiveProviderInput(thisScope, itemName, true);
     if (_msgIn != null)
     {
         log.Debug(string.Format("Provider: {0}", _msgIn));
         if (_msgIn.Subscribe(this, null))
         {
             if (log.IsDebugEnabled)
                 log.Debug(string.Format("Subscribed to {0} provider", itemName));
         }
         else
         {
             if (log.IsWarnEnabled)
                 log.Warn(string.Format("Subscribe to {0} provider failed", itemName));
         }
     }
     else
     {
         if (log.IsWarnEnabled)
             log.Warn(string.Format("Provider was not found for {0}", itemName));
     }
 }
Ejemplo n.º 14
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;
     }
 }
Ejemplo n.º 15
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();
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Play a specific IPlayItem.
 /// The strategy for now is VOD first, Live second.
 /// </summary>
 /// <param name="item">Item to play</param>
 protected void Play(IPlayItem item)
 {
     // Return if already playing
     if (_state != State.STOPPED)
         return;
     // Assume this is not live stream
     bool isLive = false;
     IProviderService providerService = ScopeUtils.GetScopeService(this.Scope, typeof(IProviderService)) as IProviderService;
     _msgIn = providerService.GetVODProviderInput(this.Scope, item.Name);
     if (_msgIn == null)
     {
         _msgIn = providerService.GetLiveProviderInput(this.Scope, item.Name, true);
         isLive = true;
     }
     if (_msgIn == null)
     {
         log.Warn("Can't get both VOD and Live input from providerService");
         return;
     }
     _state = State.PLAYING;
     _currentItem = item;
     SendResetMessage();
     _msgIn.Subscribe(this, null);
     if (isLive)
     {
         if (item.Length >= 0)
         {
             PlayItemScheduledJob job = new PlayItemScheduledJob(this);
             _liveJobName = _schedulingService.AddScheduledOnceJob(item.Length, job);
         }
     }
     else
     {
         long start = item.Start;
         if (start < 0)
             start = 0;
         SendVODInitCM(_msgIn, (int)start);
         StartBroadcastVOD();
     }
 }