summaryrefslogtreecommitdiffstats
path: root/player/sub.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/sub.c')
-rw-r--r--player/sub.c86
1 files changed, 61 insertions, 25 deletions
diff --git a/player/sub.c b/player/sub.c
index ae2a85ac1c..65e5732e23 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -21,7 +21,6 @@
#include <math.h>
#include <assert.h>
-#include "config.h"
#include "mpv_talloc.h"
#include "common/msg.h"
@@ -55,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++)
@@ -101,30 +113,43 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
sub_preload(dec_sub);
}
- if (!sub_read_packets(dec_sub, video_pts))
- 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 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) {
- 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 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
@@ -167,8 +192,9 @@ static bool init_subdec(struct MPContext *mpctx, struct track *track)
if (!track->demuxer || !track->stream)
return false;
- track->d_sub = sub_create(mpctx->global, track->stream,
- get_all_attachments(mpctx));
+ track->d_sub = sub_create(mpctx->global, track,
+ get_all_attachments(mpctx),
+ get_order(mpctx, track));
if (!track->d_sub)
return false;
@@ -196,10 +222,20 @@ void reinit_sub(struct MPContext *mpctx, struct track *track)
sub_select(track->d_sub, true);
int order = get_order(mpctx, track);
osd_set_sub(mpctx->osd, order, track->d_sub);
- sub_control(track->d_sub, SD_CTRL_SET_TOP, &(bool){!!order});
- if (mpctx->playback_initialized)
- update_subtitles(mpctx, mpctx->playback_pts);
+ // When paused we have to wait for packets to be available.
+ // 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)