sd_lavc: fix occasional problems with certain VOs when changing scaling

The OSD is passed to VOs via struct sub_bitmaps, which has a change_id
field. This field is incremented whenever there is a (potential) change
to the other struct contents. If not, the VO can rely on it not having
changed. This must include for example sub_bitmap.x and sub_bitmap.dw.
If these two fields (and y equivalents) change, change_id must change,
even if the subtitle bitmap data might still be the same.

sd_lavc.c stopped respecting this at some unknown point. It could
sometimes cause problems, though usually only with bad and old VOs which
somehow relied on this more than vo_gpu. (I've actually encountered this
before with sd_lavc subtitle scaling, as indicated by a nasty comment,
though probably didn't track this down, since said old VOs can die in a
fire.)

Fix this by maintaining the change_id explicitly. Unfortunately adds
even more code. Instead of comparing the result we could track property
changes, but I think this is better. The number of parts is always very
low with this subtitle decoder, so there's no actual performance issue
to worry about.

This could be triggered by scaling changes (video-zoom etc.), but
probably also changing bitmap subtitle position or scaling.
This commit is contained in:
wm4 2020-05-09 17:55:29 +02:00
parent b3a9058c0d
commit 488c0b4de5
1 changed files with 24 additions and 0 deletions

View File

@ -62,6 +62,8 @@ struct sd_lavc_priv {
AVRational pkt_timebase;
struct sub subs[MAX_QUEUE]; // most recent event first
struct sub_bitmap *outbitmaps;
struct sub_bitmap *prevret;
int prevret_num;
int64_t displayed_id;
int64_t new_id;
struct mp_image_params video_params;
@ -490,6 +492,28 @@ static struct sub_bitmaps *get_bitmaps(struct sd *sd, struct mp_osd_res d,
}
}
if (priv->prevret_num != res->num_parts)
res->change_id++;
if (!res->change_id) {
assert(priv->prevret_num == res->num_parts);
for (int n = 0; n < priv->prevret_num; n++) {
struct sub_bitmap *a = &res->parts[n];
struct sub_bitmap *b = &priv->prevret[n];
if (a->x != b->x || a->y != b->y ||
a->dw != b->dw || a->dh != b->dh)
{
res->change_id++;
break;
}
}
}
priv->prevret_num = res->num_parts;
MP_TARRAY_GROW(priv, priv->prevret, priv->prevret_num);
memcpy(priv->prevret, res->parts, res->num_parts * sizeof(priv->prevret[0]));
return sub_bitmaps_copy(NULL, res);
}