History

vf_vapoursynth: pass image properties from input

This might not always be correct depending on filtering done in VS. But unless VS send us all the metadata we have to get it from somewhere. Fixes dynamic frame metadata, which was copied from fmt_in, initialized only upon reinitialization. Fixes crashes caused by the use of stale pointers.

Kacper Michajłow committed 2 years ago

Commit 21e167c1 parent 83e51a81 file · +21 −9Browse files

Unified · Split

video/filter/vf_vapoursynth.c+21−9
@@ -209,6 +209,10 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map, · 208 unmodified lines
209209 if (img->fields & MP_IMGFIELD_INTERLACED)
210210 field = img->fields & MP_IMGFIELD_TOP_FIRST ? 2 : 1;
211211 p->vsapi->propSetInt(map, "_FieldBased", field, 0);
212+
213+ // Don't increase the reference count. It is not intended to be read externally,
214+ // and we know it will be alive when we retrieve it.
215+ p->vsapi->propSetData(map, "_MP_IMAGE", (const char *)img, sizeof(*img), 0);
212216 }
213217
214218 static int set_vs_frame_props(struct priv *p, VSFrameRef *frame,
@@ -231,11 +235,13 @@ static VSFrameRef *alloc_vs_frame(struct priv *p, struct mp_image_params *fmt) · 16 unmodified lines
231235 }
232236
233237 static struct mp_image map_vs_frame(struct priv *p, const VSFrameRef *ref,
234− bool w)
238+ bool w, struct mp_image *ref_image)
235239 {
236240 const VSFormat *fmt = p->vsapi->getFrameFormat(ref);
237241
238242 struct mp_image img = {0};
243+ if (ref_image)
244+ img = *ref_image;
239245 mp_image_setfmt(&img, mp_from_vs(fmt->id));
240246 mp_image_set_size(&img, p->vsapi->getFrameWidth(ref, 0),
241247 p->vsapi->getFrameHeight(ref, 0));
@@ -270,13 +276,19 @@ static void VS_CC vs_frame_done(void *userData, const VSFrameRef *f, int n, · 28 unmodified lines
270276
271277 struct mp_image *res = NULL;
272278 if (f) {
273− struct mp_image img = map_vs_frame(p, f, false);
274− struct mp_image dummy = {.params = p->fmt_in};
275− if (p->fmt_in.w != img.w || p->fmt_in.h != img.h)
276− dummy.params.crop = (struct mp_rect){0, 0, img.w, img.h};
277− mp_image_copy_attributes(&img, &dummy);
278− img.pkt_duration = -1;
279279 const VSMap *map = p->vsapi->getFramePropsRO(f);
280+ if (!map)
281+ MP_ERR(p, "Failed to get frame properties!");
282+ struct mp_image *mpi = NULL;
283+ if (map) {
284+ mpi = (void *)p->vsapi->propGetData(map, "_MP_IMAGE", 0, NULL);
285+ if (!mpi)
286+ MP_ERR(p, "Failed to get mp_image attributes!");
287+ }
288+ struct mp_image img = map_vs_frame(p, f, false, mpi);
289+ img.pkt_duration = -1;
290+ if (mpi && (mpi->params.w != img.w || mpi->params.h != img.h))
291+ img.params.crop = (struct mp_rect){0, 0, img.w, img.h};
280292 if (map) {
281293 int err1, err2;
282294 int num = p->vsapi->propGetInt(map, "_DurationNum", 0, &err1);
@@ -491,7 +503,7 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason, · 208 unmodified lines
491503 p->vsapi->setFilterError("Could not allocate VS frame", frameCtx);
492504 break;
493505 }
494− struct mp_image vsframe = map_vs_frame(p, ret, true);
506+ struct mp_image vsframe = map_vs_frame(p, ret, true, NULL);
495507 mp_image_clear(&vsframe, 0, 0, p->fmt_in.w, p->fmt_in.h);
496508 struct mp_image dummy = {0};
497509 mp_image_set_params(&dummy, &p->fmt_in);
@@ -539,7 +551,7 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason, · 41 unmodified lines
539551 }
540552
541553 mp_mutex_unlock(&p->lock);
542− struct mp_image vsframe = map_vs_frame(p, ret, true);
554+ struct mp_image vsframe = map_vs_frame(p, ret, true, NULL);
543555 mp_image_copy(&vsframe, img);
544556 int res = 1e6;
545557 int dur = img->pkt_duration * res + 0.5;

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