History

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.

Dudemanguy committed 2 years ago

Commit 68bcbf61 parent b2836bb3 files · +32 −6Browse files

Unified · Split

3 files
  1. player/core.h +2 −0
  2. player/playloop.c +18 −2
  3. player/sub.c +12 −4
player/core.h+2−0
@@ -132,6 +132,8 @@ struct track { · 131 unmodified lines
132 char *external_filename;132 char *external_filename;
133 bool auto_loaded;133 bool auto_loaded;
134 134
135 bool demuxer_ready; // if more packets should be read (subtitles only)
136
135 struct demuxer *demuxer;137 struct demuxer *demuxer;
136 // Invariant: !stream || stream->demuxer == demuxer138 // Invariant: !stream || stream->demuxer == demuxer
137 struct sh_stream *stream;139 struct sh_stream *stream;
player/playloop.c+18−2
@@ -803,6 +803,22 @@ int get_cache_buffering_percentage(struct MPContext *mpctx) · 802 unmodified lines
803 return mpctx->demuxer ? mpctx->cache_buffer : -1;803 return mpctx->demuxer ? mpctx->cache_buffer : -1;
804}804}
805 805
806static void handle_update_subtitles(struct MPContext *mpctx)
807{
808 if (mpctx->video_status == STATUS_EOF) {
809 update_subtitles(mpctx, mpctx->playback_pts);
810 return;
811 }
812
813 for (int n = 0; n < mpctx->num_tracks; n++) {
814 struct track *track = mpctx->tracks[n];
815 if (track->type == STREAM_SUB && !track->demuxer_ready) {
816 update_subtitles(mpctx, mpctx->playback_pts);
817 break;
818 }
819 }
820}
821
806static void handle_cursor_autohide(struct MPContext *mpctx)822static void handle_cursor_autohide(struct MPContext *mpctx)
807{823{
808 struct MPOpts *opts = mpctx->opts;824 struct MPOpts *opts = mpctx->opts;
@@ -1233,8 +1249,8 @@ void run_playloop(struct MPContext *mpctx) · 424 unmodified lines
1233 handle_dummy_ticks(mpctx);1249 handle_dummy_ticks(mpctx);
1234 1250
1235 update_osd_msg(mpctx);1251 update_osd_msg(mpctx);
1236 if (mpctx->video_status == STATUS_EOF)1252
1237 update_subtitles(mpctx, mpctx->playback_pts);1253 handle_update_subtitles(mpctx);
1238 1254
1239 handle_each_frame_screenshot(mpctx);1255 handle_each_frame_screenshot(mpctx);
1240 1256
player/sub.c+12−4
@@ -224,10 +224,18 @@ void reinit_sub(struct MPContext *mpctx, struct track *track) · 223 unmodified lines
224 osd_set_sub(mpctx->osd, order, track->d_sub);224 osd_set_sub(mpctx->osd, order, track->d_sub);
225 225
226 // When paused we have to wait for packets to be available.226 // When paused we have to wait for packets to be available.
227 // So just retry until we get a packet in this case.227 // Retry on a timeout until we get a packet. If still not successful,
228 if (mpctx->playback_initialized)228 // then queue it for later in the playloop (but this will have a delay).
229 while (!update_subtitles(mpctx, mpctx->playback_pts) &&229 if (mpctx->playback_initialized) {
230 mpctx->paused && !mpctx->paused_for_cache);230 track->demuxer_ready = false;
231 int64_t end = mp_time_ns() + MP_TIME_MS_TO_NS(50);
232 while (!track->demuxer_ready && mp_time_ns() < end)
233 track->demuxer_ready = update_subtitles(mpctx, mpctx->playback_pts) ||
234 !mpctx->paused;
235 if (!track->demuxer_ready)
236 mp_wakeup_core(mpctx);
237
238 }
231}239}
232 240
233void reinit_sub_all(struct MPContext *mpctx)241void reinit_sub_all(struct MPContext *mpctx)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t