summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2024-04-14 16:37:32 -0500
committerDudemanguy <random342@airmail.cc>2024-04-16 19:45:00 +0000
commit68bcbf66ef4a9bcab1ffd6c5c5cf8fd7fd39bb7e (patch)
treecc13fceb24c80de887186eb2e5810abe0016978b /player
parentb2836bbaf19a1fe819785f26b697bbd725b4f4df (diff)
downloadmpv-68bcbf66ef4a9bcab1ffd6c5c5cf8fd7fd39bb7e.tar.bz2
mpv-68bcbf66ef4a9bcab1ffd6c5c5cf8fd7fd39bb7e.tar.xz
player: avoid busy looping during reinit_sub
If the player is paused, switching subtitle track requires us to read subs packets for an indefinite amount of time in order to actually display the subtitles. The problem with this is that it puts a blocking loop in the play thread which can be slow in cases where it takes a long time to fetch the subtitle (e.g. over a network). 9e27b1f523071db184443d78f7144cb599dd0829 alleviates this when a pause happens because of buffering, but it's not complete. One could encounter this if the user pauses the video first manually and then switches the subtitle track. To solve this better, make it so the loop has a time out (totally arbitrary number) so the player isn't blocked forever. If subtitles are not fetched within that time, we flag the track and try again later in the playloop.
Diffstat (limited to 'player')
-rw-r--r--player/core.h2
-rw-r--r--player/playloop.c20
-rw-r--r--player/sub.c16
3 files changed, 32 insertions, 6 deletions
diff --git a/player/core.h b/player/core.h
index 5e97b6d868..c44868cecd 100644
--- a/player/core.h
+++ b/player/core.h
@@ -132,6 +132,8 @@ struct track {
char *external_filename;
bool auto_loaded;
+ bool demuxer_ready; // if more packets should be read (subtitles only)
+
struct demuxer *demuxer;
// Invariant: !stream || stream->demuxer == demuxer
struct sh_stream *stream;
diff --git a/player/playloop.c b/player/playloop.c
index bf903e54f7..12239d69ab 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -803,6 +803,22 @@ int get_cache_buffering_percentage(struct MPContext *mpctx)
return mpctx->demuxer ? mpctx->cache_buffer : -1;
}
+static void handle_update_subtitles(struct MPContext *mpctx)
+{
+ if (mpctx->video_status == STATUS_EOF) {
+ update_subtitles(mpctx, mpctx->playback_pts);
+ return;
+ }
+
+ for (int n = 0; n < mpctx->num_tracks; n++) {
+ struct track *track = mpctx->tracks[n];
+ if (track->type == STREAM_SUB && !track->demuxer_ready) {
+ update_subtitles(mpctx, mpctx->playback_pts);
+ break;
+ }
+ }
+}
+
static void handle_cursor_autohide(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
@@ -1233,8 +1249,8 @@ void run_playloop(struct MPContext *mpctx)
handle_dummy_ticks(mpctx);
update_osd_msg(mpctx);
- if (mpctx->video_status == STATUS_EOF)
- update_subtitles(mpctx, mpctx->playback_pts);
+
+ handle_update_subtitles(mpctx);
handle_each_frame_screenshot(mpctx);
diff --git a/player/sub.c b/player/sub.c
index 998b88d620..65e5732e23 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -224,10 +224,18 @@ void reinit_sub(struct MPContext *mpctx, struct track *track)
osd_set_sub(mpctx->osd, order, track->d_sub);
// When paused we have to wait for packets to be available.
- // So just retry until we get a packet in this case.
- if (mpctx->playback_initialized)
- while (!update_subtitles(mpctx, mpctx->playback_pts) &&
- mpctx->paused && !mpctx->paused_for_cache);
+ // Retry on a timeout until we get a packet. If still not successful,
+ // then queue it for later in the playloop (but this will have a delay).
+ if (mpctx->playback_initialized) {
+ track->demuxer_ready = false;
+ int64_t end = mp_time_ns() + MP_TIME_MS_TO_NS(50);
+ while (!track->demuxer_ready && mp_time_ns() < end)
+ track->demuxer_ready = update_subtitles(mpctx, mpctx->playback_pts) ||
+ !mpctx->paused;
+ if (!track->demuxer_ready)
+ mp_wakeup_core(mpctx);
+
+ }
}
void reinit_sub_all(struct MPContext *mpctx)