Esempio n. 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>
        /// Pauses the media.
        /// </summary>
        /// <returns></returns>
        public async Task Pause()
        {
            PauseCommand command = null;

            lock (SyncLock)
            {
                command = Commands.FirstOrDefault(c => c.CommandType == MediaCommandType.Pause) as PauseCommand;
                if (command == null)
                {
                    command = new PauseCommand(this);
                    Commands.Add(command);
                }
            }

            await command.Promise;
        }
        /// <summary>
        /// Pauses the media.
        /// </summary>
        /// <returns>The awaitable command</returns>
        public async Task PauseAsync()
        {
            PauseCommand command = null;

            lock (SyncLock)
            {
                command = Commands.FirstOrDefault(c => c.CommandType == MediaCommandType.Pause) as PauseCommand;
                if (command == null)
                {
                    command = new PauseCommand(this);
                    EnqueueCommand(command);
                }
            }

            await command.TaskContext;
        }
Esempio n. 4
0
        /// <summary>
        /// Pauses the media.
        /// </summary>
        public void Pause()
        {
            PauseCommand command = null;

            lock (SyncLock)
            {
                command = Commands.FirstOrDefault(c => c.CommandType == MediaCommandType.Pause) as PauseCommand;
                if (command == null)
                {
                    command = new PauseCommand(this);
                    EnqueueCommand(command);
                }
            }

            WaitFor(command);
        }
Esempio n. 5
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(this.Manager);

            pause.ExecuteInternal();
            var seek = new SeekCommand(this.Manager, TimeSpan.Zero);

            seek.ExecuteInternal();

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

            m.MediaState = System.Windows.Controls.MediaState.Stop;
        }
Esempio n. 6
0
        /// <summary>
        /// Performs the actions that this command implements.
        /// </summary>
        internal override void ExecuteInternal()
        {
            var m = Manager.MediaElement;

            WasPlaying = m.IsPlaying;

            var pause = new PauseCommand(Manager);

            pause.ExecuteInternal();

            var initialPosition = m.Clock.Position;

            m.SeekingDone?.Reset();
            var startTime = DateTime.UtcNow;

            try
            {
                var main = m.Container.Components.Main.MediaType;
                var t    = MediaType.None;

                // 1. Check if we already have the block. If we do, simply set the clock position to the target position
                // we don't need anything else.
                if (m.Blocks[main].IsInRange(TargetPosition))
                {
                    m.Clock.Position = TargetPosition;
                    return;
                }

                // Signal to wait one more frame dcoding cycle before
                // sending blocks to the renderer.
                m.HasDecoderSeeked = true;

                // wait for the current reading and decoding cycles
                // to finish. We don't want to interfere with reading in progress
                // or decoding in progress
                m.PacketReadingCycle?.WaitOne();

                // Capture seek target adjustment
                var adjustedSeekTarget = TargetPosition;
                if (main == MediaType.Video && m.Blocks[main].IsMonotonic)
                {
                    var targetSkewTicks = (long)Math.Round(
                        m.Blocks[main][0].Duration.Ticks * (m.Blocks[main].Capacity / 2d), 2);
                    adjustedSeekTarget = TimeSpan.FromTicks(adjustedSeekTarget.Ticks - targetSkewTicks);
                }

                // Clear Blocks and frames, reset the render times
                foreach (var mt in m.Container.Components.MediaTypes)
                {
                    m.Blocks[mt].Clear();
                    m.LastRenderTime[mt] = TimeSpan.MinValue;
                }

                // Populate frame queues with after-seek operation
                var frames = m.Container.Seek(adjustedSeekTarget);
                m.HasMediaEnded = false;

                // Clear all the blocks. We don't need them
                foreach (var kvp in m.Blocks)
                {
                    kvp.Value.Clear();
                }

                // Create the blocks from the obtained seek frames
                foreach (var frame in frames)
                {
                    m.Blocks[frame.MediaType]?.Add(frame, m.Container);
                }

                // Now read blocks until we have reached at least the Target Position
                while (m.Container.IsAtEndOfStream == false &&
                       m.Blocks[main].IsFull == false &&
                       m.Blocks[main].IsInRange(TargetPosition) == false)
                {
                    // Read the next packet
                    t = m.Container.Read();

                    // Ignore if we don't have an acceptable packet
                    if (m.Blocks.ContainsKey(t) == false)
                    {
                        continue;
                    }

                    // move on if we have plenty
                    if (m.Blocks[t].IsFull)
                    {
                        continue;
                    }

                    // Decode and add the frames to the corresponding output
                    frames.Clear();
                    frames.AddRange(m.Container.Components[t].ReceiveFrames());

                    foreach (var frame in frames)
                    {
                        m.Blocks[t].Add(frame, m.Container);
                    }
                }

                // Handle out-of sync scenarios
                if (m.Blocks[main].IsInRange(TargetPosition) == false)
                {
                    var minStartTime = m.Blocks[main].RangeStartTime.Ticks;
                    var maxStartTime = m.Blocks[main].RangeEndTime.Ticks;

                    m.Logger.Log(MediaLogMessageType.Warning,
                                 $"SEEK TP: Target Pos {TargetPosition.Format()} not between {m.Blocks[main].RangeStartTime.TotalSeconds:0.000} and {m.Blocks[main].RangeEndTime.TotalSeconds:0.000}");

                    if (adjustedSeekTarget.Ticks < minStartTime)
                    {
                        m.Clock.Position = TimeSpan.FromTicks(minStartTime);
                    }
                    else if (adjustedSeekTarget.Ticks > maxStartTime)
                    {
                        m.Clock.Position = TimeSpan.FromTicks(maxStartTime);
                    }
                    else
                    {
                        m.Clock.Position = TargetPosition;
                    }
                }
                else
                {
                    // TODO: handle this case correctly. The way this is handled currently sucks.
                    if (m.Blocks[main].Count == 0 && TargetPosition != TimeSpan.Zero)
                    {
                        m.Clock.Position = initialPosition;
                    }
                    else
                    {
                        m.Clock.Position = TargetPosition;
                    }
                }
            }
            catch (Exception ex)
            {
                // Log the exception
                m.Logger.Log(MediaLogMessageType.Error,
                             $"SEEK E: {ex.GetType()} - {ex.Message}. Stack Trace:\r\n{ex.StackTrace}");
            }
            finally
            {
                if (m.HasDecoderSeeked)
                {
                    m.Logger.Log(MediaLogMessageType.Debug,
                                 $"SEEK D: Elapsed: {startTime.FormatElapsed()} | Target: {TargetPosition.Format()}");
                }

                m.SeekingDone?.Set();

                if (WasPlaying)
                {
                    var play = new PlayCommand(this.Manager);
                    play.ExecuteInternal();
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Performs the actions that this command implements.
        /// </summary>
        internal override void Execute()
        {
            var m = Manager.MediaElement;

            var pause = new PauseCommand(Manager);

            pause.Execute();

            var initialPosition = m.Clock.Position;

            m.SeekingDone.Reset();
            var startTime = DateTime.UtcNow;

            try
            {
                var main        = m.Container.Components.Main.MediaType;
                var blocks      = m.Blocks[main];
                var isInRange   = blocks.IsInRange(TargetPosition);
                var renderIndex = blocks.IndexOf(TargetPosition);


                // 1. Check if we already have the block. If we do, simply set the clock position to the target position
                // we don't need anything
                if (m.Blocks[main].IsInRange(TargetPosition))
                {
                    m.Clock.Position = TargetPosition;
                    return;
                }

                m.PacketReadingCycle.WaitOne();
                m.FrameDecodingCycle.WaitOne();

                // Clear Blocks and frames, reset the render times
                foreach (var t in m.Container.Components.MediaTypes)
                {
                    m.Frames[t].Clear();
                    m.Blocks[t].Clear();
                    m.LastRenderTime[t] = TimeSpan.MinValue;
                }

                // Populate frame queues with after-seek operation
                var frames = m.Container.Seek(TargetPosition);
                m.HasMediaEnded = false;

                foreach (var frame in frames)
                {
                    m.Frames[frame.MediaType].Push(frame);
                }

                if (frames.Count > 0)
                {
                    var minStartTime = frames.Min(f => f.StartTime.Ticks);
                    var maxStartTime = frames.Max(f => f.StartTime.Ticks);

                    if (TargetPosition.Ticks < minStartTime)
                    {
                        m.Clock.Position = TimeSpan.FromTicks(minStartTime);
                    }
                    else if (TargetPosition.Ticks > maxStartTime)
                    {
                        m.Clock.Position = TimeSpan.FromTicks(maxStartTime);
                    }
                    else
                    {
                        m.Clock.Position = TargetPosition;
                    }
                }
                else
                {
                    if (frames.Count == 0 && TargetPosition != TimeSpan.Zero)
                    {
                        m.Clock.Position = initialPosition;
                    }
                }
            }
            catch (Exception)
            {
                // swallow
            }
            finally
            {
                // Call the seek method on all renderers
                foreach (var kvp in m.Renderers)
                {
                    kvp.Value.Seek();
                }

                m.Logger.Log(MediaLogMessageType.Debug,
                             $"SEEK D: Elapsed: {startTime.FormatElapsed()}");

                m.SeekingDone.Set();
            }
        }