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
64 .end = MP_NOPTS_VALUE,64 .end = MP_NOPTS_VALUE,
65 .stream = -1,65 .stream = -1,
66 .avpacket = av_packet_alloc(),66 .avpacket = av_packet_alloc(),
67 .animated = -1,
67 };68 };
68 MP_HANDLE_OOM(dp->avpacket);69 MP_HANDLE_OOM(dp->avpacket);
69 return dp;70 return dp;
demux/packet.h+1−1
@@ -59,7 +59,7 @@ typedef struct demux_packet { · 58 unmodified lines
59 double start, end; // set to non-NOPTS iff segmented is set59 double start, end; // set to non-NOPTS iff segmented is set
60 60
61 // subtitles only61 // subtitles only
62 bool animated;62 int animated; // -1 is unknown
63 bool seen;63 bool seen;
64 int seen_pos;64 int seen_pos;
65 double sub_duration;65 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
106 sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params);106 sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params);
107 }107 }
108 108
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
109 if (track->demuxer->fully_read && sub_can_preload(dec_sub)) {118 if (track->demuxer->fully_read && sub_can_preload(dec_sub)) {
110 // Assume fully_read implies no interleaved audio/video streams.119 // Assume fully_read implies no interleaved audio/video streams.
111 // (Reading packets will change the demuxer position.)120 // (Reading packets will change the demuxer position.)
@@ -136,10 +145,7 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts, · 24 unmodified lines
136 // Handle displaying subtitles on VO with no video being played. This is145 // Handle displaying subtitles on VO with no video being played. This is
137 // quite different, because normally subtitles are redrawn on new video146 // quite different, because normally subtitles are redrawn on new video
138 // frames, using the video frames' timestamps.147 // frames, using the video frames' timestamps.
139 if (mpctx->video_out && mpctx->video_status == STATUS_EOF &&148 if (still_image) {
140 (mpctx->opts->subs_rend->sub_past_video_end ||
141 !mpctx->current_track[0][STREAM_VIDEO] ||
142 mpctx->current_track[0][STREAM_VIDEO]->image)) {
143 if (osd_pts != video_pts) {149 if (osd_pts != video_pts) {
144 osd_set_force_video_pts(mpctx->osd, video_pts);150 osd_set_force_video_pts(mpctx->osd, video_pts);
145 osd_query_and_reset_want_redraw(mpctx->osd);151 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
319 return true;319 return true;
320 }320 }
321 321
322 if (pkt && pkt->animated)322 if (pkt && pkt->animated == 1)
323 return true;323 return true;
324 324
325 return false;325 return false;
sub/dec_sub.h+1−0
@@ -16,6 +16,7 @@ struct sd; · 15 unmodified lines
16 16
17enum sd_ctrl {17enum sd_ctrl {
18 SD_CTRL_SUB_STEP,18 SD_CTRL_SUB_STEP,
19 SD_CTRL_SET_ANIMATED_CHECK,
19 SD_CTRL_SET_VIDEO_PARAMS,20 SD_CTRL_SET_VIDEO_PARAMS,
20 SD_CTRL_SET_VIDEO_DEF_FPS,21 SD_CTRL_SET_VIDEO_DEF_FPS,
21 SD_CTRL_UPDATE_OPTS,22 SD_CTRL_UPDATE_OPTS,
sub/sd_ass.c+23−6
@@ -57,8 +57,9 @@ struct sd_ass_priv { · 56 unmodified lines
57 struct mp_osd_res osd;57 struct mp_osd_res osd;
58 struct seen_packet *seen_packets;58 struct seen_packet *seen_packets;
59 int num_seen_packets;59 int num_seen_packets;
60 bool *packets_animated;60 int *packets_animated;
61 int num_packets_animated;61 int num_packets_animated;
62 bool check_animated;
62 bool duration_unknown;63 bool duration_unknown;
63};64};
64 65
@@ -351,19 +352,32 @@ static void filter_and_add(struct sd *sd, struct demux_packet *pkt) · 286 unmodified lines
351 llrint(pkt->pts * 1000),352 llrint(pkt->pts * 1000),
352 llrint(pkt->duration * 1000));353 llrint(pkt->duration * 1000));
353 354
354 // This bookkeeping is only ever needed for ASS subs355 // This bookkeeping only has any practical use for ASS subs
356 // over a VO with no video.
355 if (!ctx->is_converted) {357 if (!ctx->is_converted) {
356 if (!pkt->seen) {358 if (!pkt->seen) {
357 for (int n = track->n_events - 1; n >= 0; n--) {359 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)
359 break;361 break;
360 ASS_Event *event = &track->events[n];362 ASS_Event *event = &track->events[n];
361 pkt->animated = (event->Effect && event->Effect[0]) ||363 // Might as well mark pkt->animated here with effects if we can.
362 is_animated(event->Text);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);
363 }367 }
364 MP_TARRAY_APPEND(ctx, ctx->packets_animated, ctx->num_packets_animated, pkt->animated);368 MP_TARRAY_APPEND(ctx, ctx->packets_animated, ctx->num_packets_animated, pkt->animated);
365 } else {369 } 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 }
367 }381 }
368 }382 }
369 383
@@ -952,6 +966,9 @@ static int control(struct sd *sd, enum sd_ctrl cmd, void *arg) · 582 unmodified lines
952 a[0] += res / 1000.0 + SUB_SEEK_OFFSET;966 a[0] += res / 1000.0 + SUB_SEEK_OFFSET;
953 return true;967 return true;
954 }968 }
969 case SD_CTRL_SET_ANIMATED_CHECK:
970 ctx->check_animated = *(bool *)arg;
971 return CONTROL_OK;
955 case SD_CTRL_SET_VIDEO_PARAMS:972 case SD_CTRL_SET_VIDEO_PARAMS:
956 ctx->video_params = *(struct mp_image_params *)arg;973 ctx->video_params = *(struct mp_image_params *)arg;
957 return CONTROL_OK;974 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