private void DetectPlaybackEnded(MediaType main) { var playbackEndClock = MediaCore.Blocks[main].Count > 0 ? MediaCore.Blocks[main].RangeEndTime : MediaCore.Timing.GetEndTime(main) ?? TimeSpan.MaxValue; // Check End of Media Scenarios if (!Commands.HasPendingCommands && MediaCore.HasDecodingEnded && !CanResumeClock(main)) { // Rendered all and nothing else to render if (State.HasMediaEnded == false) { if (Container.IsStreamSeekable) { var componentStartTime = Container.Components[main].StartTime; var actualComponentDuration = TimeSpan.FromTicks(playbackEndClock.Ticks - componentStartTime.Ticks); Container.Components[main].Duration = actualComponentDuration; } MediaCore.PausePlayback(); MediaCore.ChangePlaybackPosition(playbackEndClock); } State.MediaState = MediaPlaybackState.Stop; State.HasMediaEnded = true; } else { State.HasMediaEnded = false; } }
private void DetectPlaybackEnded(MediaType main) { var playbackEndClock = MediaCore.Blocks[main].Count > 0 ? MediaCore.Blocks[main].RangeEndTime : Container.Components.PlaybackEndTime ?? TimeSpan.MaxValue; var isAtEndOfPlayback = MediaCore.PlaybackPosition.Ticks >= playbackEndClock.Ticks || MediaCore.Timing.HasDisconnectedClocks; // Check End of Media Scenarios if (!Commands.HasPendingCommands && MediaCore.HasDecodingEnded && isAtEndOfPlayback) { // Rendered all and nothing else to render if (State.HasMediaEnded == false) { MediaCore.PausePlayback(); MediaCore.ChangePlaybackPosition(playbackEndClock); } State.MediaState = MediaPlaybackState.Stop; State.HasMediaEnded = true; } else { State.HasMediaEnded = false; } }
/// <summary> /// Provides the implementation for the Pause Media Command. /// </summary> /// <returns>True if the command was successful.</returns> private bool CommandPauseMedia() { if (State.CanPause == false) { return(false); } MediaCore.PausePlayback(); foreach (var renderer in MediaCore.Renderers.Values) { renderer.OnPause(); } MediaCore.ChangePlaybackPosition(SnapPositionToBlockPosition(MediaCore.PlaybackPosition)); State.MediaState = MediaPlaybackState.Pause; return(true); }
private void AlignClocksToPlayback(MediaType main, MediaType[] all) { // we don't want to disturb the clock or align it if we are not ready if (Commands.HasPendingCommands) { return; } if (HasDisconnectedClocks) { foreach (var t in all) { if (t == MediaType.Subtitle) { continue; } var compBlocks = MediaCore.Blocks[t]; var compPosition = MediaCore.Timing.GetPosition(t); if (compBlocks.Count <= 0) { MediaCore.PausePlayback(t, false); if (MediaCore.Timing.GetIsRunning(t)) { this.LogDebug(Aspects.Timing, $"CLOCK PAUSED: {t} clock was paused at {compPosition.Format()} because no decoded {t} content was found"); } continue; } // Don't let the RTC lag behind the blocks or move beyond them if (compPosition.Ticks < compBlocks.RangeStartTime.Ticks) { MediaCore.ChangePlaybackPosition(compBlocks.RangeStartTime, t, false); this.LogDebug(Aspects.Timing, $"CLOCK BEHIND: {t} clock was {compPosition.Format()}. It was updated to {compBlocks.RangeStartTime.Format()}"); } else if (compPosition.Ticks > compBlocks.RangeEndTime.Ticks) { if (t != MediaType.Audio) { MediaCore.PausePlayback(t, false); } MediaCore.ChangePlaybackPosition(compBlocks.RangeEndTime, t, false); this.LogDebug(Aspects.Timing, $"CLOCK AHEAD : {t} clock was {compPosition.Format()}. It was updated to {compBlocks.RangeEndTime.Format()}"); } } return; } // Get a reference to the main blocks. // The range will be 0 if there are no blocks. var blocks = MediaCore.Blocks[main]; var position = MediaCore.PlaybackPosition; if (blocks.Count == 0) { // We have no main blocks in range. All we can do is pause the clock if (MediaCore.Timing.IsRunning) { this.LogDebug(Aspects.Timing, $"CLOCK PAUSED: playback clock was paused at {position.Format()} because no decoded {main} content was found"); } MediaCore.PausePlayback(); return; } if (position.Ticks < blocks.RangeStartTime.Ticks) { // Don't let the RTC lag behind what is available on the main component MediaCore.ChangePlaybackPosition(blocks.RangeStartTime); this.LogTrace(Aspects.Timing, $"CLOCK BEHIND: playback clock was {position.Format()}. It was updated to {blocks.RangeStartTime.Format()}"); } else if (position.Ticks > blocks.RangeEndTime.Ticks) { // Don't let the RTC move beyond what is available on the main component MediaCore.PausePlayback(); MediaCore.ChangePlaybackPosition(blocks.RangeEndTime); this.LogTrace(Aspects.Timing, $"CLOCK AHEAD : playback clock was {position.Format()}. It was updated to {blocks.RangeEndTime.Format()}"); } }
private void AlignClocksToPlayback(MediaType main, MediaType[] all) { // we don't want to disturb the clock or align it if we are not ready if (Commands.HasPendingCommands) { return; } MediaBlockBuffer blocks = null; TimeSpan position = MediaCore.PlaybackPosition; if (HasDisconnectedClocks) { foreach (var t in all) { if (t == MediaType.Subtitle) { continue; } blocks = MediaCore.Blocks[t]; position = MediaCore.Timing.Position(t); // Don't let the RTC lag behind the blocks or move beyond them if (position.Ticks < blocks.RangeStartTime.Ticks) { MediaCore.ChangePlaybackPosition(blocks.RangeStartTime, t); this.LogTrace(Aspects.Timing, $"CLOCK BEHIND: {t} clock was {position.Format()}. It was updated to {blocks.RangeStartTime.Format()}"); } else if (position.Ticks > blocks.RangeEndTime.Ticks) { // we don't use the pause playback method to prevent // reporting the current playback position MediaCore.Timing.Pause(t); MediaCore.ChangePlaybackPosition(blocks.RangeEndTime, t); this.LogTrace(Aspects.Timing, $"CLOCK AHEAD : {t} clock was {position.Format()}. It was updated to {blocks.RangeEndTime.Format()}"); } } return; } // Get a reference to the main blocks. // The range will be 0 if there are no blocks. blocks = MediaCore.Blocks[main]; var range = blocks.GetRangePercent(position); if (range < 0) { // Don't let the RTC lag behind what is available on the main component MediaCore.ChangePlaybackPosition(blocks.RangeStartTime); this.LogTrace(Aspects.Timing, $"CLOCK BEHIND: playback clock was {position.Format()}. It was updated to {blocks.RangeStartTime.Format()}"); } else if (range > 1d) { // Don't let the RTC move beyond what is available on the main component MediaCore.PausePlayback(); MediaCore.ChangePlaybackPosition(blocks.RangeEndTime); this.LogTrace(Aspects.Timing, $"CLOCK AHEAD : playback clock was {position.Format()}. It was updated to {blocks.RangeEndTime.Format()}"); } else if (range == 0 && blocks.Count == 0 && MediaCore.Timing.IsRunning) { // We have no main blocks in range. All we can do is pause the clock this.LogTrace(Aspects.Timing, $"CLOCK PAUSED: playback clock was {position.Format()} but no {main} content was found"); MediaCore.PausePlayback(); } }