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.
Unified · Split
| @@ -209,6 +209,10 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map, · 208 unmodified lines | |||
| 209 | if (img->fields & MP_IMGFIELD_INTERLACED) | 209 | if (img->fields & MP_IMGFIELD_INTERLACED) |
| 210 | field = img->fields & MP_IMGFIELD_TOP_FIRST ? 2 : 1; | 210 | field = img->fields & MP_IMGFIELD_TOP_FIRST ? 2 : 1; |
| 211 | p->vsapi->propSetInt(map, "_FieldBased", field, 0); | 211 | 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); | ||
| 212 | } | 216 | } |
| 213 | 217 | ||
| 214 | static int set_vs_frame_props(struct priv *p, VSFrameRef *frame, | 218 | 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 | |||
| 231 | } | 235 | } |
| 232 | 236 | ||
| 233 | static struct mp_image map_vs_frame(struct priv *p, const VSFrameRef *ref, | 237 | static struct mp_image map_vs_frame(struct priv *p, const VSFrameRef *ref, |
| 234 | bool w) | 238 | bool w, struct mp_image *ref_image) |
| 235 | { | 239 | { |
| 236 | const VSFormat *fmt = p->vsapi->getFrameFormat(ref); | 240 | const VSFormat *fmt = p->vsapi->getFrameFormat(ref); |
| 237 | 241 | ||
| 238 | struct mp_image img = {0}; | 242 | struct mp_image img = {0}; |
| 243 | if (ref_image) | ||
| 244 | img = *ref_image; | ||
| 239 | mp_image_setfmt(&img, mp_from_vs(fmt->id)); | 245 | mp_image_setfmt(&img, mp_from_vs(fmt->id)); |
| 240 | mp_image_set_size(&img, p->vsapi->getFrameWidth(ref, 0), | 246 | mp_image_set_size(&img, p->vsapi->getFrameWidth(ref, 0), |
| 241 | p->vsapi->getFrameHeight(ref, 0)); | 247 | 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 | |||
| 270 | 276 | ||
| 271 | struct mp_image *res = NULL; | 277 | struct mp_image *res = NULL; |
| 272 | if (f) { | 278 | 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; | ||
| 279 | const VSMap *map = p->vsapi->getFramePropsRO(f); | 279 | 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}; | ||
| 280 | if (map) { | 292 | if (map) { |
| 281 | int err1, err2; | 293 | int err1, err2; |
| 282 | int num = p->vsapi->propGetInt(map, "_DurationNum", 0, &err1); | 294 | 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 | |||
| 491 | p->vsapi->setFilterError("Could not allocate VS frame", frameCtx); | 503 | p->vsapi->setFilterError("Could not allocate VS frame", frameCtx); |
| 492 | break; | 504 | break; |
| 493 | } | 505 | } |
| 494 | struct mp_image vsframe = map_vs_frame(p, ret, true); | 506 | struct mp_image vsframe = map_vs_frame(p, ret, true, NULL); |
| 495 | mp_image_clear(&vsframe, 0, 0, p->fmt_in.w, p->fmt_in.h); | 507 | mp_image_clear(&vsframe, 0, 0, p->fmt_in.w, p->fmt_in.h); |
| 496 | struct mp_image dummy = {0}; | 508 | struct mp_image dummy = {0}; |
| 497 | mp_image_set_params(&dummy, &p->fmt_in); | 509 | 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 | |||
| 539 | } | 551 | } |
| 540 | 552 | ||
| 541 | mp_mutex_unlock(&p->lock); | 553 | 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); |
| 543 | mp_image_copy(&vsframe, img); | 555 | mp_image_copy(&vsframe, img); |
| 544 | int res = 1e6; | 556 | int res = 1e6; |
| 545 | int dur = img->pkt_duration * res + 0.5; | 557 | int dur = img->pkt_duration * res + 0.5; |