Beispiel #1
0
        /// <summary>
        /// Performs the actions that this command implements.
        /// </summary>
        internal override void ExecuteInternal()
        {
            var m = Manager.MediaElement;
            m.Clock.Reset();
            var pause = new PauseCommand(Manager);
            pause.ExecuteInternal();
            var seek = new SeekCommand(Manager, TimeSpan.Zero);
            seek.ExecuteInternal();

            foreach (var renderer in m.Renderers.Values)
                renderer.Stop();

            m.MediaState = CoreMediaState.Stop;
        }
        /// <summary>
        /// Performs the actions that this command implements.
        /// </summary>
        internal override void ExecuteInternal()
        {
            var m = Manager.MediaCore;

            m.Clock.Reset();
            m.MediaState = MediaEngineState.Stop;
            var seek = new SeekCommand(Manager, TimeSpan.Zero);

            seek.ExecuteInternal();

            foreach (var renderer in m.Renderers.Values)
            {
                renderer.Stop();
            }
        }
        /// <summary>
        /// Performs the actions that this command implements.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        internal override async Task ExecuteInternal()
        {
            var m = Manager.MediaCore;

            m.Clock.Reset();
            m.State.UpdateMediaState(PlaybackStatus.Manual);
            var seek = new SeekCommand(Manager, TimeSpan.Zero);
            await seek.ExecuteInternal();

            m.State.UpdateMediaState(PlaybackStatus.Stop, m.WallClock);

            foreach (var renderer in m.Renderers.Values)
            {
                renderer.Stop();
            }
        }
        /// <summary>
        /// Performs the actions that this command implements.
        /// </summary>
        internal override void Execute()
        {
            var m = Manager.MediaElement;

            m.Clock.Reset();
            var seek = new SeekCommand(this.Manager, TimeSpan.Zero);

            seek.Execute();

            foreach (var renderer in m.Renderers.Values)
            {
                renderer.Stop();
            }

            m.MediaState = System.Windows.Controls.MediaState.Stop;
        }
        /// <summary>
        /// Performs the actions represented by this deferred task.
        /// </summary>
        protected override void PerformActions()
        {
            var m = MediaCore;

            m.Clock.Reset();
            m.State.UpdateMediaState(PlaybackStatus.Manual);
            var seek = new SeekCommand(m, TimeSpan.Zero);

            seek.Execute();
            m.State.UpdateMediaState(PlaybackStatus.Stop, m.WallClock);

            foreach (var renderer in m.Renderers.Values)
            {
                renderer.Stop();
            }
        }
        /// <summary>
        /// Seeks to the specified position within the media.
        /// This command is a queued command
        /// </summary>
        /// <param name="position">The position.</param>
        public void Seek(TimeSpan position)
        {
            SeekCommand command = null;

            lock (SyncLock)
            {
                command = Commands.LastOrDefault(c => c.CommandType == MediaCommandType.Seek) as SeekCommand;
                if (command == null || command.IsRunning)
                {
                    command = new SeekCommand(this, position);
                    EnqueueCommand(command);
                }
                else
                {
                    command.TargetPosition = position;
                }
            }
        }
        /// <summary>
        /// Seeks to the specified position within the media.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public async Task Seek(TimeSpan position)
        {
            SeekCommand command = null;
            lock (SyncLock)
            {
                command = Commands.FirstOrDefault(c => c.CommandType == MediaCommandType.Seek) as SeekCommand;
                if (command == null)
                {
                    command = new SeekCommand(this, position);
                    Commands.Add(command);
                }
                else
                {
                    command.TargetPosition = position;
                }
            }

            await command.Promise;
        }
Beispiel #8
0
        /// <summary>
        /// Performs the actions represented by this deferred task.
        /// </summary>
        protected override void PerformActions()
        {
            var m = MediaCore;

            m.Log(MediaLogMessageType.Debug, $"Command {CommandType}: Entered");

            try
            {
                m.State.UpdateMediaState(PlaybackStatus.Manual);

                // Signal the start of a sync-buffering scenario
                m.Clock.Pause();

                // Wait for the cycles to complete
                var workerEvents = new IWaitEvent[] { m.BlockRenderingCycle, m.PacketReadingCycle };
                foreach (var workerEvent in workerEvents)
                {
                    workerEvent.Wait();
                }

                // Signal a change so the user get the chance to update
                // selected streams and options
                m.SendOnMediaChanging();

                // Side load subtitles
                m.PreloadSubtitles();

                // Capture the current media types before components change
                var oldMediaTypes = m.Container.Components.MediaTypes.ToArray();

                // Recreate selected streams as media components
                var mediaTypes = m.Container.UpdateComponents();
                m.State.UpdateFixedContainerProperties();

                // find all existing component blocks and renderers that no longer exist
                // We always remove the audio component in case there is a change in audio device
                var removableMediaTypes = oldMediaTypes
                                          .Where(t => mediaTypes.Contains(t) == false)
                                          .Union(new[] { MediaType.Audio })
                                          .Distinct()
                                          .ToArray();

                // find all existing component blocks and renderers that no longer exist
                foreach (var t in removableMediaTypes)
                {
                    // Remove the renderer for the component
                    if (m.Renderers.ContainsKey(t))
                    {
                        m.Renderers[t].Close();
                        m.Renderers.Remove(t);
                    }

                    // Remove the block buffer for the component
                    if (m.Blocks.ContainsKey(t))
                    {
                        m.Blocks[t]?.Dispose();
                        m.Blocks.Remove(t);
                    }
                }

                // Create the block buffers and renderers as necessary
                foreach (var t in mediaTypes)
                {
                    if (m.Blocks.ContainsKey(t) == false)
                    {
                        m.Blocks[t] = new MediaBlockBuffer(Constants.MaxBlocks[t], t);
                    }

                    if (m.Renderers.ContainsKey(t) == false)
                    {
                        m.Renderers[t] = MediaEngine.Platform.CreateRenderer(t, m);
                    }

                    m.Blocks[t].Clear();
                    m.Renderers[t].WaitForReadyState();
                }

                // Depending on whether or not the media is seekable
                // perform either a seek operation or a quick buffering operation.
                if (m.State.IsSeekable)
                {
                    // Let's simply do an automated seek
                    var seekCommand = new SeekCommand(m, m.WallClock);
                    seekCommand.Execute();
                    return;
                }
                else
                {
                    // Let's perform quick-buffering
                    m.Container.Components.RunQuickBuffering(m);

                    // Mark the renderers as invalidated
                    foreach (var t in mediaTypes)
                    {
                        m.InvalidateRenderer(t);
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorException = ex;
            }
        }
Beispiel #9
0
        /// <summary>
        /// Provides the implementation of the command
        /// </summary>
        /// <returns>The awaitable task.</returns>
        internal override async Task ExecuteInternal()
        {
            var m = Manager.MediaCore;

            // Avoid running the command if run conditions are not met
            if (m == null || m.IsDisposed || m.State.IsOpen == false || m.State.IsOpening)
            {
                return;
            }

            var resumeClock = false;
            var isSeeking   = m.State.IsSeeking;

            try
            {
                // Signal the start of a changing event
                m.MediaChangingDone.Begin();
                m.State.IsSeeking = true;

                // Signal the start of a sync-buffering scenario
                m.HasDecoderSeeked = true;
                resumeClock        = m.Clock.IsRunning;
                m.Clock.Pause();

                // Wait for the cycles to complete
                var workerEvents = new IWaitEvent[] { m.BlockRenderingCycle, m.PacketReadingCycle };
                foreach (var workerEvent in workerEvents)
                {
                    workerEvent.Wait();
                }

                // Send the changing event to the connector
                var beforeComponentTypes = m.Container.Components.MediaTypes;
                await m.SendOnMediaChanging();

                m.Container.UpdateComponents();
                var afterComponentTypes      = m.Container.Components.MediaTypes;
                var disposableComponentTypes = beforeComponentTypes
                                               .Where(c => afterComponentTypes.Contains(c) == false)
                                               .ToArray();

                // Remove components that are no longer needed
                foreach (var t in disposableComponentTypes)
                {
                    if (m.Renderers.ContainsKey(t))
                    {
                        m.Renderers[t].Close();
                        m.Renderers.Remove(t);
                    }

                    if (m.Blocks.ContainsKey(t))
                    {
                        m.Blocks[t]?.Dispose();
                        m.Blocks.Remove(t);
                    }
                }

                // Create the block buffers and renderers as necessary
                // TODO: For smoother transition, only invalidate/change the components
                // that actually changed.
                foreach (var t in afterComponentTypes)
                {
                    if (m.Blocks.ContainsKey(t) == false)
                    {
                        m.Blocks[t] = new MediaBlockBuffer(Constants.MaxBlocks[t], t);
                    }

                    if (m.Renderers.ContainsKey(t) == false)
                    {
                        m.Renderers[t] = MediaEngine.Platform.CreateRenderer(t, m);
                    }

                    m.Blocks[t].Clear();
                    m.Renderers[t].WaitForReadyState();
                }

                if (m.State.IsSeekable)
                {
                    var seekCommand = new SeekCommand(Manager, m.WallClock);
                    seekCommand.RunSynchronously();
                }
                else
                {
                    foreach (var t in afterComponentTypes)
                    {
                        m.InvalidateRenderer(t);
                    }
                }
            }
            catch
            {
                // TODO: Handle errors here
            }
            finally
            {
                if (resumeClock)
                {
                    m?.Clock?.Play();
                }
                m.State.IsSeeking = isSeeking;
                m.MediaChangingDone.Complete();
            }
        }
        /// <summary>
        /// Provides the implementation of the command
        /// </summary>
        /// <returns>
        /// The awaitable task.
        /// </returns>
        internal override async Task ExecuteInternal()
        {
            var m = Manager.MediaCore;

            // Avoid running the command if run conditions are not met
            if (m == null || m.IsDisposed || m.State.IsOpen == false || m.State.IsOpening || m.State.IsChanging)
            {
                return;
            }

            m.State.IsChanging = true;
            var resumeClock = false;
            var isSeeking   = m.State.IsSeeking;

            try
            {
                // Signal the start of a changing event
                m.MediaChangingDone.Begin();
                m.State.IsSeeking = true;

                // Signal the start of a sync-buffering scenario
                m.HasDecoderSeeked = true;
                resumeClock        = m.Clock.IsRunning;
                m.Clock.Pause();

                // Wait for the cycles to complete
                var workerEvents = new IWaitEvent[] { m.BlockRenderingCycle, m.PacketReadingCycle };
                foreach (var workerEvent in workerEvents)
                {
                    workerEvent.Wait();
                }

                // Signal a change so the user get the chance to update
                // selected streams and options
                await m.SendOnMediaChanging();

                // Capture the current media types before components change
                var oldMediaTypes = m.Container.Components.MediaTypes.ToArray();

                // Recreate selected streams as media components
                var mediaTypes = m.Container.UpdateComponents();

                // remove all exiting component blocks and renderers that no longer exist
                var removableMediaTypes = oldMediaTypes
                                          .Where(t => mediaTypes.Contains(t) == false).ToArray();

                foreach (var t in removableMediaTypes)
                {
                    if (m.Renderers.ContainsKey(t))
                    {
                        m.Renderers[t].Close();
                        m.Renderers.Remove(t);
                    }

                    if (m.Blocks.ContainsKey(t))
                    {
                        m.Blocks[t]?.Dispose();
                        m.Blocks.Remove(t);
                    }
                }

                // Create the block buffers and renderers as necessary
                foreach (var t in mediaTypes)
                {
                    if (m.Blocks.ContainsKey(t) == false)
                    {
                        m.Blocks[t] = new MediaBlockBuffer(Constants.MaxBlocks[t], t);
                    }

                    if (m.Renderers.ContainsKey(t) == false)
                    {
                        m.Renderers[t] = MediaEngine.Platform.CreateRenderer(t, m);
                    }

                    m.Blocks[t].Clear();
                    m.Renderers[t].WaitForReadyState();
                }

                // Mark a seek operation in order to invalidate renderers
                if (m.State.IsSeekable)
                {
                    // Let's simply do an automated seek
                    var seekCommand = new SeekCommand(Manager, m.WallClock);
                    seekCommand.RunSynchronously();
                    return;
                }

                // We need to perform some packet reading and decoding
                var main = m.Container.Components.Main.MediaType;
                var auxs = m.Container.Components.MediaTypes.ExcludeMediaType(main);

                // Read and decode blocks until the main component is half full
                while (m.ShouldReadMorePackets && m.CanReadMorePackets)
                {
                    // Read some packets
                    m.Container.Read();

                    // Decode frames and add the blocks
                    foreach (var t in mediaTypes)
                    {
                        var frames = m.Container.Components[t].ReceiveFrames();
                        foreach (var frame in frames)
                        {
                            if (frame != null)
                            {
                                m.Blocks[t].Add(frame, m.Container);
                            }
                        }
                    }

                    // Check if we have at least a half a buffer on main
                    if (m.Blocks[main].CapacityPercent >= 0.5)
                    {
                        break;
                    }
                }

                // Check if we have a valid range. If not, just set it what the main component is dictating
                if (m.Blocks[main].Count > 0 && m.Blocks[main].IsInRange(m.WallClock) == false)
                {
                    m.Clock.Update(m.Blocks[main].RangeStartTime);
                }

                // Have the other components catch up
                foreach (var t in auxs)
                {
                    if (m.Blocks[main].Count <= 0)
                    {
                        break;
                    }
                    if (t != MediaType.Audio && t != MediaType.Video)
                    {
                        continue;
                    }

                    while (m.Blocks[t].RangeEndTime < m.Blocks[main].RangeEndTime)
                    {
                        if (m.ShouldReadMorePackets == false || m.CanReadMorePackets == false)
                        {
                            break;
                        }

                        // Read some packets
                        m.Container.Read();

                        // Decode frames and add the blocks
                        var frames = m.Container.Components[t].ReceiveFrames();
                        foreach (var frame in frames)
                        {
                            if (frame != null)
                            {
                                m.Blocks[t].Add(frame, m.Container);
                            }
                        }
                    }
                }

                foreach (var t in mediaTypes)
                {
                    m.InvalidateRenderer(t);
                }

                m.HasDecoderSeeked = true;
            }
            catch
            {
                // TODO: Handle errors here
            }
            finally
            {
                if (resumeClock)
                {
                    m?.Clock?.Play();
                }
                m.State.IsSeeking = isSeeking;
                m.MediaChangingDone.Complete();
                m.State.IsChanging = false;
                await m.SendOnMediaChanged();
            }
        }