History

sub: avoid unneeded calls to is_animated

4e5d996c3a3f74a7308aee53614c2b94c71daebc added this as part of a series of patches written to avoid wasteful sub redraws when playing a still image with subs. The is_animated special case was specifically for ASS subtitles that have animations/effects and would need repeated redraws in the still image case. This check was done unconditionally for all ASS subtitles, but for very big ASS subtitles, this text parsing can get a bit expensive. Because this function call is only ever needed for the weird edge case of ASS subtitles over a still image, some additional logic can be added to avoid calling is_animated in the vast majority of cases. The animated field in demux_packet can be changed to a tristate instead where -1 indicates "unknown" (the default state). In update_subtitle, we can look at the current state of the video tracks and decide whether or not it is neccesary to perform is_animated and pass that knowledge to sd_ass before any subtitle packets are decoded and thus save us from doing this potentially expensive call.

Dudemanguy committed 2 years ago

Commit fa890821 parent 7e821086 files · +37 −12Browse files

Unified · Split

6 files
  1. demux/packet.c +1 −0
  2. demux/packet.h +1 −1
  3. player/sub.c +10 −4
  4. sub/dec_sub.c +1 −1
  5. sub/dec_sub.h +1 −0
  6. sub/sd_ass.c +23 −6
demux/packet.c+1−0
@@ -64,6 +64,7 @@ static struct demux_packet *packet_create(void) · 63 unmodified lines
6464 .end = MP_NOPTS_VALUE,
6565 .stream = -1,
6666 .avpacket = av_packet_alloc(),
67+ .animated = -1,
6768 };
6869 MP_HANDLE_OOM(dp->avpacket);
6970 return dp;
demux/packet.h+1−1
@@ -59,7 +59,7 @@ typedef struct demux_packet { · 58 unmodified lines
5959 double start, end; // set to non-NOPTS iff segmented is set
6060
6161 // subtitles only
62− bool animated;
62+ int animated; // -1 is unknown
6363 bool seen;
6464 int seen_pos;
6565 double sub_duration;
player/sub.c+10−4
@@ -106,6 +106,15 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts, · 105 unmodified lines
106106 sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params);
107107 }
108108
109+ // Checking if packets have special animations is relatively expensive.
110+ // This is only needed if we are rendering ASS subtitles with no video
111+ // being played.
112+ bool still_image = mpctx->video_out && ((mpctx->video_status == STATUS_EOF &&
113+ mpctx->opts->subs_rend->sub_past_video_end) ||
114+ !mpctx->current_track[0][STREAM_VIDEO] ||
115+ mpctx->current_track[0][STREAM_VIDEO]->image);
116+ sub_control(dec_sub, SD_CTRL_SET_ANIMATED_CHECK, &still_image);
117+
109118 if (track->demuxer->fully_read && sub_can_preload(dec_sub)) {
110119 // Assume fully_read implies no interleaved audio/video streams.
111120 // (Reading packets will change the demuxer position.)
@@ -136,10 +145,7 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts, · 24 unmodified lines
136145 // Handle displaying subtitles on VO with no video being played. This is
137146 // quite different, because normally subtitles are redrawn on new video
138147 // frames, using the video frames' timestamps.
139− if (mpctx->video_out && mpctx->video_status == STATUS_EOF &&
140− (mpctx->opts->subs_rend->sub_past_video_end ||
141− !mpctx->current_track[0][STREAM_VIDEO] ||
142− mpctx->current_track[0][STREAM_VIDEO]->image)) {
148+ if (still_image) {
143149 if (osd_pts != video_pts) {
144150 osd_set_force_video_pts(mpctx->osd, video_pts);
145151 osd_query_and_reset_want_redraw(mpctx->osd);
sub/dec_sub.c+1−1
@@ -319,7 +319,7 @@ static bool update_pkt_cache(struct dec_sub *sub, double video_pts) · 318 unmodified lines
319319 return true;
320320 }
321321
322− if (pkt && pkt->animated)
322+ if (pkt && pkt->animated == 1)
323323 return true;
324324
325325 return false;
sub/dec_sub.h+1−0
@@ -16,6 +16,7 @@ struct sd; · 15 unmodified lines
1616
1717 enum sd_ctrl {
1818 SD_CTRL_SUB_STEP,
19+ SD_CTRL_SET_ANIMATED_CHECK,
1920 SD_CTRL_SET_VIDEO_PARAMS,
2021 SD_CTRL_SET_VIDEO_DEF_FPS,
2122 SD_CTRL_UPDATE_OPTS,
sub/sd_ass.c+23−6
@@ -57,8 +57,9 @@ struct sd_ass_priv { · 56 unmodified lines
5757 struct mp_osd_res osd;
5858 struct seen_packet *seen_packets;
5959 int num_seen_packets;
60− bool *packets_animated;
60+ int *packets_animated;
6161 int num_packets_animated;
62+ bool check_animated;
6263 bool duration_unknown;
6364 };
6465
@@ -351,19 +352,32 @@ static void filter_and_add(struct sd *sd, struct demux_packet *pkt) · 286 unmodified lines
351352 llrint(pkt->pts * 1000),
352353 llrint(pkt->duration * 1000));
353354
354− // This bookkeeping is only ever needed for ASS subs
355+ // This bookkeeping only has any practical use for ASS subs
356+ // over a VO with no video.
355357 if (!ctx->is_converted) {
356358 if (!pkt->seen) {
357359 for (int n = track->n_events - 1; n >= 0; n--) {
358− if (n + 1 == old_n_events || pkt->animated)
360+ if (n + 1 == old_n_events || pkt->animated == 1)
359361 break;
360362 ASS_Event *event = &track->events[n];
361− pkt->animated = (event->Effect && event->Effect[0]) ||
362− is_animated(event->Text);
363+ // Might as well mark pkt->animated here with effects if we can.
364+ pkt->animated = (event->Effect && event->Effect[0]) ? 1 : -1;
365+ if (ctx->check_animated && pkt->animated != 1)
366+ pkt->animated = is_animated(event->Text);
363367 }
364368 MP_TARRAY_APPEND(ctx, ctx->packets_animated, ctx->num_packets_animated, pkt->animated);
365369 } else {
366− pkt->animated = ctx->packets_animated[pkt->seen_pos];
370+ if (ctx->check_animated && ctx->packets_animated[pkt->seen_pos] == -1) {
371+ for (int n = track->n_events - 1; n >= 0; n--) {
372+ if (n + 1 == old_n_events || pkt->animated == 1)
373+ break;
374+ ASS_Event *event = &track->events[n];
375+ ctx->packets_animated[pkt->seen_pos] = is_animated(event->Text);
376+ pkt->animated = ctx->packets_animated[pkt->seen_pos];
377+ }
378+ } else {
379+ pkt->animated = ctx->packets_animated[pkt->seen_pos];
380+ }
367381 }
368382 }
369383
@@ -952,6 +966,9 @@ static int control(struct sd *sd, enum sd_ctrl cmd, void *arg) · 582 unmodified lines
952966 a[0] += res / 1000.0 + SUB_SEEK_OFFSET;
953967 return true;
954968 }
969+ case SD_CTRL_SET_ANIMATED_CHECK:
970+ ctx->check_animated = *(bool *)arg;
971+ return CONTROL_OK;
955972 case SD_CTRL_SET_VIDEO_PARAMS:
956973 ctx->video_params = *(struct mp_image_params *)arg;
957974 return CONTROL_OK;

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