summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2023-09-27 21:52:44 -0500
committerDudemanguy <random342@airmail.cc>2023-09-27 22:38:13 -0500
commitf40bbfec4fcd2d9a787a4d98ec7698a646e5607e (patch)
tree5fcf3c8c80548e578d6cc6f730c5cc5f33ea6e85
parent09b04fbf0940151f5856aa4396f9b467622371a3 (diff)
downloadmpv-f40bbfec4fcd2d9a787a4d98ec7698a646e5607e.tar.bz2
mpv-f40bbfec4fcd2d9a787a4d98ec7698a646e5607e.tar.xz
demux: improve stream selection state
This replaces the previous commit and makes more sense. The internal demux marked tracks as eager depending on their type and for subtitles it would always lazily read them unless there happened to be no available av stream. However, we want the sub stream to be eager if the player is paused. The existing subtitle is still preserved on the screen, but if the user changes tracks that's when the problem occurs. So to handle this case, propagate the mpctx->paused down to the stream selection logic. This modifies both demuxer_refresh_track and demuxer_select_track to take that boolean value. A few other parts of the player use this, but we can just assume false there (no change in behavior from before) since they should never be related to subtitles. The core player code is aware of its own state naturally, and can always pass the appropriate value so go ahead and do so. When we change the pause state, a refresh seek is done on all existing subtitle tracks to make sure their eager state is the appropriate value (i.e. so it's not still set to eager after a pause and a track switch). Slightly invasive change, but it works with the existing logic instead of going around it so ultimately it should be a better approach. We can additionally remove the old force boolean from sub_read_packets since it is no longer needed.
-rw-r--r--demux/demux.c17
-rw-r--r--demux/demux.h4
-rw-r--r--demux/demux_disc.c2
-rw-r--r--demux/demux_timeline.c2
-rw-r--r--player/loadfile.c6
-rw-r--r--player/playloop.c9
-rw-r--r--player/sub.c2
-rw-r--r--sub/dec_sub.c4
-rw-r--r--sub/dec_sub.h2
9 files changed, 29 insertions, 19 deletions
diff --git a/demux/demux.c b/demux/demux.c
index f198cfc9af..575ccc227d 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -864,7 +864,8 @@ static void wakeup_ds(struct demux_stream *ds)
}
static void update_stream_selection_state(struct demux_internal *in,
- struct demux_stream *ds)
+ struct demux_stream *ds,
+ bool paused)
{
ds->eof = false;
ds->refreshing = false;
@@ -886,8 +887,8 @@ static void update_stream_selection_state(struct demux_internal *in,
}
// Subtitles are only eagerly read if there are no other eagerly read
- // streams.
- if (any_av_streams) {
+ // streams or the player is paused.
+ if (any_av_streams && !paused) {
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *s = in->streams[n]->ds;
@@ -1002,7 +1003,7 @@ static void demux_add_sh_stream_locked(struct demux_internal *in,
sh->ds->queue = in->current_range->streams[sh->ds->index];
}
- update_stream_selection_state(in, sh->ds);
+ update_stream_selection_state(in, sh->ds, false);
switch (ds->type) {
case STREAM_AUDIO:
@@ -3961,7 +3962,7 @@ static void initiate_refresh_seek(struct demux_internal *in,
// ref_pts is used only if the stream is enabled. Then it serves as approximate
// start pts for this stream (in the worst case it is ignored).
void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
- double ref_pts, bool selected)
+ double ref_pts, bool selected, bool paused)
{
struct demux_internal *in = demuxer->in;
struct demux_stream *ds = stream->ds;
@@ -3971,7 +3972,7 @@ void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
if (ds->selected != selected) {
MP_VERBOSE(in, "%sselect track %d\n", selected ? "" : "de", stream->index);
ds->selected = selected;
- update_stream_selection_state(in, ds);
+ update_stream_selection_state(in, ds, paused);
in->tracks_switched = true;
if (ds->selected) {
if (in->back_demuxing)
@@ -3991,7 +3992,7 @@ void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
// Execute a refresh seek on the given stream.
// ref_pts has the same meaning as with demuxer_select_track()
void demuxer_refresh_track(struct demuxer *demuxer, struct sh_stream *stream,
- double ref_pts)
+ double ref_pts, bool paused)
{
struct demux_internal *in = demuxer->in;
struct demux_stream *ds = stream->ds;
@@ -3999,7 +4000,7 @@ void demuxer_refresh_track(struct demuxer *demuxer, struct sh_stream *stream,
ref_pts = MP_ADD_PTS(ref_pts, -in->ts_offset);
if (ds->selected) {
MP_VERBOSE(in, "refresh track %d\n", stream->index);
- update_stream_selection_state(in, ds);
+ update_stream_selection_state(in, ds, paused);
if (in->back_demuxing)
ds->back_seek_pos = ref_pts;
if (!in->after_seek)
diff --git a/demux/demux.h b/demux/demux.h
index 08904f26cc..4582c544e7 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -319,9 +319,9 @@ void demux_get_reader_state(struct demuxer *demuxer, struct demux_reader_state *
void demux_block_reading(struct demuxer *demuxer, bool block);
void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
- double ref_pts, bool selected);
+ double ref_pts, bool selected, bool paused);
void demuxer_refresh_track(struct demuxer *demuxer, struct sh_stream *stream,
- double ref_pts);
+ double ref_pts, bool paused);
int demuxer_help(struct mp_log *log, const m_option_t *opt, struct bstr name);
diff --git a/demux/demux_disc.c b/demux/demux_disc.c
index 3dfff45403..5f8885e5e8 100644
--- a/demux/demux_disc.c
+++ b/demux/demux_disc.c
@@ -59,7 +59,7 @@ static void reselect_streams(demuxer_t *demuxer)
for (int n = 0; n < MPMIN(num_slave, p->num_streams); n++) {
if (p->streams[n]) {
demuxer_select_track(p->slave, demux_get_stream(p->slave, n),
- MP_NOPTS_VALUE, demux_stream_is_selected(p->streams[n]));
+ MP_NOPTS_VALUE, demux_stream_is_selected(p->streams[n]), false);
}
}
}
diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c
index 5572fb53bf..21fdcdbe5b 100644
--- a/demux/demux_timeline.c
+++ b/demux/demux_timeline.c
@@ -170,7 +170,7 @@ static void reselect_streams(struct demuxer *demuxer)
if (!src->current || seg->d != src->current->d)
selected = false;
struct sh_stream *sh = demux_get_stream(seg->d, i);
- demuxer_select_track(seg->d, sh, MP_NOPTS_VALUE, selected);
+ demuxer_select_track(seg->d, sh, MP_NOPTS_VALUE, selected, false);
update_slave_stats(demuxer, seg->d);
}
diff --git a/player/loadfile.c b/player/loadfile.c
index 7fe7284e77..521a20d459 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -381,9 +381,9 @@ void reselect_demux_stream(struct MPContext *mpctx, struct track *track,
pts -= 10.0;
}
if (refresh_only)
- demuxer_refresh_track(track->demuxer, track->stream, pts);
+ demuxer_refresh_track(track->demuxer, track->stream, pts, mpctx->paused);
else
- demuxer_select_track(track->demuxer, track->stream, pts, track->selected);
+ demuxer_select_track(track->demuxer, track->stream, pts, track->selected, mpctx->paused);
}
static void enable_demux_thread(struct MPContext *mpctx, struct demuxer *demux)
@@ -1178,7 +1178,7 @@ static void *open_demux_thread(void *ctx)
int num_streams = demux_get_num_stream(demux);
for (int n = 0; n < num_streams; n++) {
struct sh_stream *sh = demux_get_stream(demux, n);
- demuxer_select_track(demux, sh, MP_NOPTS_VALUE, true);
+ demuxer_select_track(demux, sh, MP_NOPTS_VALUE, true, mpctx->paused);
}
demux_set_wakeup_cb(demux, wakeup_demux, mpctx);
diff --git a/player/playloop.c b/player/playloop.c
index 7a1c13f4ad..61d374a589 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -180,6 +180,15 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause)
} else {
(void)get_relative_time(mpctx); // ignore time that passed during pause
}
+
+ if (mpctx->demuxer) {
+ double pts = get_current_time(mpctx);
+ for (int n = 0; n < num_ptracks[STREAM_SUB]; n++) {
+ struct track *track = mpctx->current_track[n][STREAM_SUB];
+ if (track)
+ demuxer_refresh_track(mpctx->demuxer, track->stream, pts, mpctx->paused);
+ }
+ }
}
update_core_idle_state(mpctx);
diff --git a/player/sub.c b/player/sub.c
index 7dd1f2ccb6..91627d8c22 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -100,7 +100,7 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
sub_preload(dec_sub);
}
- if (!sub_read_packets(dec_sub, video_pts, mpctx->paused))
+ if (!sub_read_packets(dec_sub, video_pts))
return false;
// Handle displaying subtitles on terminal; never done for secondary subs
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index dc26aa027e..84c6b7bfbe 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -269,7 +269,7 @@ static bool is_new_segment(struct dec_sub *sub, struct demux_packet *p)
// Read packets from the demuxer stream passed to sub_create(). Return true if
// enough packets were read, false if the player should wait until the demuxer
// signals new packets available (and then should retry).
-bool sub_read_packets(struct dec_sub *sub, double video_pts, bool force)
+bool sub_read_packets(struct dec_sub *sub, double video_pts)
{
bool r = true;
pthread_mutex_lock(&sub->lock);
@@ -291,7 +291,7 @@ bool sub_read_packets(struct dec_sub *sub, double video_pts, bool force)
break;
// (Use this mechanism only if sub_delay matters to avoid corner cases.)
- double min_pts = sub->opts->sub_delay < 0 || force ? video_pts : MP_NOPTS_VALUE;
+ double min_pts = sub->opts->sub_delay < 0 ? video_pts : MP_NOPTS_VALUE;
struct demux_packet *pkt;
int st = demux_read_packet_async_until(sub->sh, min_pts, &pkt);
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index 96b8c29807..c2b75f308a 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -43,7 +43,7 @@ void sub_destroy(struct dec_sub *sub);
bool sub_can_preload(struct dec_sub *sub);
void sub_preload(struct dec_sub *sub);
-bool sub_read_packets(struct dec_sub *sub, double video_pts, bool force);
+bool sub_read_packets(struct dec_sub *sub, double video_pts);
struct sub_bitmaps *sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim,
int format, double pts);
char *sub_get_text(struct dec_sub *sub, double pts, enum sd_text_type type);