summaryrefslogtreecommitdiffstats
path: root/player/sub.c
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2024-01-21 17:14:39 -0600
committerDudemanguy <random342@airmail.cc>2024-02-15 16:43:11 +0000
commit8f043de961f5b57c60e61e49b1841ad20faa64fe (patch)
tree69c4510a26174548181db3226328a06b0ba65a3a /player/sub.c
parent0a4b098c616bf1b6700bc88878b028bf1f446868 (diff)
downloadmpv-8f043de961f5b57c60e61e49b1841ad20faa64fe.tar.bz2
mpv-8f043de961f5b57c60e61e49b1841ad20faa64fe.tar.xz
player/sub: avoid wasteful subtitle redraws
This only affects two special cases: printing subtitles to the terminal and printing subtitles on a still picture. Previously, mpv was very dumb here and spammed this logic on every single loop. For terminal subtitles, this isn't as big of a deal, but for the image case this is pretty bad. The entire VO constantly redrew even when there was no need to which can be very expensive depending on user settings. Instead, let's rework sub_read_packets so that it also tells us whether or not the subtitle packets update in some way in addition to telling us whether or not to read more. Since we cache all packets thanks to the previous commit, we can leverage this information to make a guess whether or not the current subtitle packet is supposed to be visible on the screen. Because the redraw now only happens when it is needed, the mp_set_timeout_hack can be removed.
Diffstat (limited to 'player/sub.c')
-rw-r--r--player/sub.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/player/sub.c b/player/sub.c
index 5d7baef3e6..998b88d620 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -54,6 +54,19 @@ static void reset_subtitles(struct MPContext *mpctx, struct track *track)
term_osd_set_subs(mpctx, NULL);
}
+// Only matters for subs on an image.
+void redraw_subs(struct MPContext *mpctx)
+{
+ for (int n = 0; n < num_ptracks[STREAM_SUB]; n++) {
+ if (mpctx->current_track[n][STREAM_SUB] &&
+ mpctx->current_track[n][STREAM_SUB]->d_sub)
+ {
+ mpctx->redraw_subs = true;
+ break;
+ }
+ }
+}
+
void reset_subtitle_state(struct MPContext *mpctx)
{
for (int n = 0; n < mpctx->num_tracks; n++)
@@ -100,33 +113,43 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
sub_preload(dec_sub);
}
- if (!sub_read_packets(dec_sub, video_pts, mpctx->paused))
- return false;
+ bool packets_read = false;
+ bool sub_updated = false;
+ sub_read_packets(dec_sub, video_pts, mpctx->paused, &packets_read, &sub_updated);
- // Handle displaying subtitles on terminal; never done for secondary subs
- if (mpctx->current_track[0][STREAM_SUB] == track && !mpctx->video_out) {
- char *text = sub_get_text(dec_sub, video_pts, SD_TEXT_TYPE_PLAIN);
- term_osd_set_subs(mpctx, text);
- talloc_free(text);
- }
+ double osd_pts = osd_get_force_video_pts(mpctx->osd);
+
+ // Check if we need to update subtitles for these special cases. Always
+ // update on discontinuities like seeking or a new file.
+ if (sub_updated || mpctx->redraw_subs || osd_pts == MP_NOPTS_VALUE) {
+ // Always force a redecode of all packets if we have a refresh.
+ if (mpctx->redraw_subs)
+ sub_redecode_cached_packets(dec_sub);
- // Handle displaying subtitles on VO with no video being played. This is
- // quite different, because normally subtitles are redrawn on new video
- // frames, using the video frames' timestamps.
- if (mpctx->video_out && mpctx->video_status == STATUS_EOF &&
- (mpctx->opts->subs_rend->sub_past_video_end ||
- !mpctx->current_track[0][STREAM_VIDEO] ||
- mpctx->current_track[0][STREAM_VIDEO]->image)) {
- if (osd_get_force_video_pts(mpctx->osd) != video_pts) {
- osd_set_force_video_pts(mpctx->osd, video_pts);
- osd_query_and_reset_want_redraw(mpctx->osd);
- vo_redraw(mpctx->video_out);
- // Force an arbitrary minimum FPS
- mp_set_timeout(mpctx, 0.1);
+ // Handle displaying subtitles on terminal; never done for secondary subs
+ if (mpctx->current_track[0][STREAM_SUB] == track && !mpctx->video_out) {
+ char *text = sub_get_text(dec_sub, video_pts, SD_TEXT_TYPE_PLAIN);
+ term_osd_set_subs(mpctx, text);
+ talloc_free(text);
+ }
+
+ // Handle displaying subtitles on VO with no video being played. This is
+ // quite different, because normally subtitles are redrawn on new video
+ // frames, using the video frames' timestamps.
+ if (mpctx->video_out && mpctx->video_status == STATUS_EOF &&
+ (mpctx->opts->subs_rend->sub_past_video_end ||
+ !mpctx->current_track[0][STREAM_VIDEO] ||
+ mpctx->current_track[0][STREAM_VIDEO]->image)) {
+ if (osd_pts != video_pts) {
+ osd_set_force_video_pts(mpctx->osd, video_pts);
+ osd_query_and_reset_want_redraw(mpctx->osd);
+ vo_redraw(mpctx->video_out);
+ }
}
}
- return true;
+ mpctx->redraw_subs = false;
+ return packets_read;
}
// Return true if the subtitles for the given PTS are ready; false if the player