mirror of https://github.com/mpv-player/mpv
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).
9e27b1f523
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.
This commit is contained in:
parent
b2836bbaf1
commit
68bcbf66ef
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
16
player/sub.c
16
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)
|
||||
|
|
Loading…
Reference in New Issue