summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/command.c42
-rw-r--r--player/command.h2
-rw-r--r--player/core.h2
-rw-r--r--player/misc.c6
-rw-r--r--player/playloop.c28
5 files changed, 38 insertions, 42 deletions
diff --git a/player/command.c b/player/command.c
index f941e864dc..99538cebcf 100644
--- a/player/command.c
+++ b/player/command.c
@@ -75,8 +75,6 @@ struct command_ctx {
double last_seek_pts;
double marked_pts;
- double prev_pts;
-
char **warned_deprecated;
int num_warned_deprecated;
@@ -220,7 +218,7 @@ static void mp_hook_add(struct MPContext *mpctx, char *client, char *name,
}
// Call before a seek, in order to allow revert-seek to undo the seek.
-static void mark_seek(struct MPContext *mpctx)
+void mark_seek(struct MPContext *mpctx)
{
struct command_ctx *cmd = mpctx->command_ctx;
double now = mp_time_sec();
@@ -3301,9 +3299,11 @@ static int mp_property_ab_loop(void *ctx, struct m_property *prop,
}
int r = mp_property_generic_option(mpctx, prop, action, arg);
if (r > 0 && action == M_PROPERTY_SET) {
+ mpctx->ab_loop_clip = mpctx->playback_pts < opts->ab_loop[1];
if (strcmp(prop->name, "ab-loop-b") == 0) {
- struct command_ctx *cctx = mpctx->command_ctx;
- cctx->prev_pts = opts->ab_loop[0];
+ if (opts->ab_loop[1] != MP_NOPTS_VALUE &&
+ mpctx->playback_pts <= opts->ab_loop[1])
+ mpctx->ab_loop_clip = true;
}
// Update if visible
set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
@@ -5375,7 +5375,6 @@ void command_init(struct MPContext *mpctx)
mpctx->command_ctx = talloc(NULL, struct command_ctx);
*mpctx->command_ctx = (struct command_ctx){
.last_seek_pts = MP_NOPTS_VALUE,
- .prev_pts = MP_NOPTS_VALUE,
};
}
@@ -5388,8 +5387,6 @@ static void command_event(struct MPContext *mpctx, int event, void *arg)
ctx->marked_pts = MP_NOPTS_VALUE;
}
- if (event == MPV_EVENT_SEEK)
- ctx->prev_pts = MP_NOPTS_VALUE;
if (event == MPV_EVENT_IDLE)
ctx->is_idle = true;
if (event == MPV_EVENT_START_FILE)
@@ -5400,35 +5397,6 @@ static void command_event(struct MPContext *mpctx, int event, void *arg)
}
}
-void handle_ab_loop(struct MPContext *mpctx)
-{
- struct command_ctx *ctx = mpctx->command_ctx;
- struct MPOpts *opts = mpctx->opts;
-
- if (opts->pause)
- return;
-
- double now = mpctx->restart_complete ? mpctx->playback_pts : MP_NOPTS_VALUE;
- if (now != MP_NOPTS_VALUE && (opts->ab_loop[0] != MP_NOPTS_VALUE ||
- opts->ab_loop[1] != MP_NOPTS_VALUE))
- {
- double start = opts->ab_loop[0];
- if (start == MP_NOPTS_VALUE)
- start = 0;
- double end = opts->ab_loop[1];
- if (end == MP_NOPTS_VALUE)
- end = INFINITY;
- if (ctx->prev_pts >= start && ctx->prev_pts < end &&
- (now >= end || mpctx->stop_play == AT_END_OF_FILE))
- {
- mark_seek(mpctx);
- queue_seek(mpctx, MPSEEK_ABSOLUTE, start,
- MPSEEK_EXACT, MPSEEK_FLAG_DELAY);
- }
- }
- ctx->prev_pts = now;
-}
-
void handle_command_updates(struct MPContext *mpctx)
{
struct command_ctx *ctx = mpctx->command_ctx;
diff --git a/player/command.h b/player/command.h
index a233319ad7..9ffa5c1340 100644
--- a/player/command.h
+++ b/player/command.h
@@ -57,6 +57,6 @@ enum {
bool mp_hook_test_completion(struct MPContext *mpctx, char *type);
void mp_hook_run(struct MPContext *mpctx, char *client, char *type);
-void handle_ab_loop(struct MPContext *mpctx);
+void mark_seek(struct MPContext *mpctx);
#endif /* MPLAYER_COMMAND_H */
diff --git a/player/core.h b/player/core.h
index 94bfe4aada..25eb8b71a8 100644
--- a/player/core.h
+++ b/player/core.h
@@ -82,6 +82,7 @@ enum seek_precision {
enum seek_flags {
MPSEEK_FLAG_DELAY = 1 << 0, // give player chance to coalesce multiple seeks
+ MPSEEK_FLAG_NOFLUSH = 1 << 1, // keeping remaining data for seamless loops
};
enum video_sync {
@@ -326,6 +327,7 @@ typedef struct MPContext {
bool hrseek_lastframe; // drop everything until last frame reached
bool hrseek_backstep; // go to frame before seek target
double hrseek_pts;
+ bool ab_loop_clip; // clip to the "b" part of an A-B loop if available
// AV sync: the next frame should be shown when the audio out has this
// much (in seconds) buffered data left. Increased when more data is
// written to the ao, decreased when moving to the next video frame.
diff --git a/player/misc.c b/player/misc.c
index a9174c41a9..bd65fb9d5b 100644
--- a/player/misc.c
+++ b/player/misc.c
@@ -90,6 +90,12 @@ double get_play_end_pts(struct MPContext *mpctx)
if (cend != MP_NOPTS_VALUE && (end == MP_NOPTS_VALUE || cend < end))
end = cend;
}
+ if (mpctx->ab_loop_clip && opts->ab_loop[1] != MP_NOPTS_VALUE &&
+ opts->ab_loop[1] > opts->ab_loop[0])
+ {
+ if (end == MP_NOPTS_VALUE || end > opts->ab_loop[1])
+ end = opts->ab_loop[1];
+ }
return end;
}
diff --git a/player/playloop.c b/player/playloop.c
index abba107dc5..ed4f57dd5c 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -172,6 +172,7 @@ void reset_playback_state(struct MPContext *mpctx)
mpctx->last_seek_pts = MP_NOPTS_VALUE;
mpctx->cache_wait_time = 0;
mpctx->step_frames = 0;
+ mpctx->ab_loop_clip = true;
mpctx->restart_complete = false;
#if HAVE_ENCODING
@@ -272,7 +273,9 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
}
}
- clear_audio_output_buffers(mpctx);
+ if (!(seek.flags & MPSEEK_FLAG_NOFLUSH))
+ clear_audio_output_buffers(mpctx);
+
reset_playback_state(mpctx);
/* Use the target time as "current position" for further relative
@@ -301,6 +304,8 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
mpctx->audio_allow_second_chance_seek =
!hr_seek && !(demux_flags & SEEK_FORWARD);
+
+ mpctx->ab_loop_clip = mpctx->last_seek_pts < opts->ab_loop[1];
}
// This combines consecutive seek requests.
@@ -697,10 +702,25 @@ static void handle_sstep(struct MPContext *mpctx)
static void handle_loop_file(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
+
+ if (mpctx->stop_play == AT_END_OF_FILE &&
+ (opts->ab_loop[0] != MP_NOPTS_VALUE || opts->ab_loop[1] != MP_NOPTS_VALUE))
+ {
+ // Assumes execute_queued_seek() happens before next audio/video is
+ // attempted to be decoded or filtered.
+ mpctx->stop_play = KEEP_PLAYING;
+ double start = 0;
+ if (opts->ab_loop[0] != MP_NOPTS_VALUE)
+ start = opts->ab_loop[0];
+ mark_seek(mpctx);
+ queue_seek(mpctx, MPSEEK_ABSOLUTE, start, MPSEEK_EXACT,
+ MPSEEK_FLAG_NOFLUSH);
+ }
+
if (opts->loop_file && mpctx->stop_play == AT_END_OF_FILE) {
mpctx->stop_play = KEEP_PLAYING;
set_osd_function(mpctx, OSD_FFW);
- queue_seek(mpctx, MPSEEK_ABSOLUTE, 0, MPSEEK_DEFAULT, 0);
+ queue_seek(mpctx, MPSEEK_ABSOLUTE, 0, MPSEEK_DEFAULT, MPSEEK_FLAG_NOFLUSH);
if (opts->loop_file > 0)
opts->loop_file--;
}
@@ -894,6 +914,7 @@ static void handle_playback_restart(struct MPContext *mpctx)
mpctx->hrseek_active = false;
mpctx->restart_complete = true;
mpctx->audio_allow_second_chance_seek = false;
+ handle_playback_time(mpctx);
mp_notify(mpctx, MPV_EVENT_PLAYBACK_RESTART, NULL);
if (!mpctx->playing_msg_shown) {
if (opts->playing_msg && opts->playing_msg[0]) {
@@ -913,6 +934,7 @@ static void handle_playback_restart(struct MPContext *mpctx)
}
mpctx->playing_msg_shown = true;
mpctx->sleeptime = 0;
+ mpctx->ab_loop_clip = mpctx->playback_pts < opts->ab_loop[1];
MP_VERBOSE(mpctx, "playback restart complete\n");
}
}
@@ -1013,8 +1035,6 @@ void run_playloop(struct MPContext *mpctx)
handle_loop_file(mpctx);
- handle_ab_loop(mpctx);
-
handle_keep_open(mpctx);
handle_sstep(mpctx);