diff options
43 files changed, 649 insertions, 1241 deletions
diff --git a/core/mp_talloc.h b/core/mp_talloc.h index ff2b808125..1dcb0bce07 100644 --- a/core/mp_talloc.h +++ b/core/mp_talloc.h @@ -25,24 +25,34 @@ #define MP_TALLOC_ELEMS(p) (talloc_get_size(p) / sizeof((p)[0])) #define MP_GROW_ARRAY(p, nextidx) do { \ if ((nextidx) == MP_TALLOC_ELEMS(p)) \ - p = talloc_realloc_size(NULL, p, talloc_get_size(p) * 2); } while (0) + (p) = talloc_realloc_size(NULL, p, talloc_get_size(p) * 2); } while (0) #define MP_RESIZE_ARRAY(ctx, p, count) do { \ - p = talloc_realloc_size((ctx), p, (count) * sizeof(p[0])); } while (0) + (p) = talloc_realloc_size((ctx), p, (count) * sizeof((p)[0])); } while (0) #define MP_TARRAY_GROW(ctx, p, nextidx) \ do { \ size_t nextidx_ = (nextidx); \ size_t nelems_ = MP_TALLOC_ELEMS(p); \ if (nextidx_ >= nelems_) \ - p = talloc_realloc_size((ctx), p, \ - (nextidx_ + 1) * sizeof((p)[0]) * 2);\ + (p) = talloc_realloc_size(ctx, p, \ + (nextidx_ + 1) * sizeof((p)[0]) * 2);\ } while (0) #define MP_TARRAY_APPEND(ctx, p, idxvar, ...) \ do { \ MP_TARRAY_GROW(ctx, p, idxvar); \ - p[idxvar] = (MP_EXPAND_ARGS(__VA_ARGS__)); \ - idxvar++; \ + (p)[(idxvar)] = (MP_EXPAND_ARGS(__VA_ARGS__));\ + (idxvar)++; \ + } while (0) + +// Doesn't actually free any memory, or do any other talloc calls. +#define MP_TARRAY_REMOVE_AT(p, idxvar, at) \ + do { \ + size_t at_ = (at); \ + assert(at_ <= (idxvar)); \ + memmove((p) + at_, (p) + at_ + 1, \ + ((idxvar) - at_ - 1) * sizeof((p)[0])); \ + (idxvar)--; \ } while (0) #define talloc_struct(ctx, type, ...) \ diff --git a/core/mplayer.c b/core/mplayer.c index 008a783d73..48375ee9df 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2442,6 +2442,28 @@ no_video: return 0; } +static bool filter_output_queued_frame(struct MPContext *mpctx) +{ + struct sh_video *sh_video = mpctx->sh_video; + struct vo *video_out = mpctx->video_out; + + struct mp_image *img = vf_chain_output_queued_frame(sh_video->vfilter); + if (img && video_out->config_ok) + vo_draw_image(video_out, img); + talloc_free(img); + + return !!img; +} + +static void filter_video(struct MPContext *mpctx, struct mp_image *frame) +{ + struct sh_video *sh_video = mpctx->sh_video; + + frame->pts = sh_video->pts; + vf_filter_frame(sh_video->vfilter, frame); + filter_output_queued_frame(mpctx); +} + static double update_video_nocorrect_pts(struct MPContext *mpctx) { struct sh_video *sh_video = mpctx->sh_video; @@ -2451,7 +2473,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) // In nocorrect-pts mode there is no way to properly time these frames if (vo_get_buffered_frame(video_out, 0) >= 0) break; - if (vf_output_queued_frame(sh_video->vfilter)) + if (filter_output_queued_frame(mpctx)) break; unsigned char *packet = NULL; frame_time = sh_video->next_frame_time; @@ -2476,7 +2498,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) decoded_frame = decode_video(sh_video, sh_video->ds->current, packet, in_size, framedrop_type, sh_video->pts); if (decoded_frame) { - filter_video(sh_video, decoded_frame, sh_video->pts); + filter_video(mpctx, decoded_frame); } break; } @@ -2528,9 +2550,7 @@ static double update_video(struct MPContext *mpctx) while (1) { if (vo_get_buffered_frame(video_out, false) >= 0) break; - // XXX Time used in this call is not counted in any performance - // timer now - if (vf_output_queued_frame(sh_video->vfilter)) + if (filter_output_queued_frame(mpctx)) break; int in_size = 0; unsigned char *buf = NULL; @@ -2557,11 +2577,11 @@ static double update_video(struct MPContext *mpctx) mpctx->hrseek_framedrop = false; int framedrop_type = mpctx->hrseek_framedrop ? 1 : check_framedrop(mpctx, sh_video->frametime); - void *decoded_frame = decode_video(sh_video, pkt, buf, in_size, - framedrop_type, pts); + struct mp_image *decoded_frame = + decode_video(sh_video, pkt, buf, in_size, framedrop_type, pts); if (decoded_frame) { determine_frame_pts(mpctx); - filter_video(sh_video, decoded_frame, sh_video->pts); + filter_video(mpctx, decoded_frame); } else if (!pkt) { if (vo_get_buffered_frame(video_out, true) < 0) return -1; diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 9ec5e3db65..8730703216 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -104,7 +104,6 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value) void get_detected_video_colorspace(struct sh_video *sh, struct mp_csp_details *csp) { struct MPOpts *opts = sh->opts; - struct vf_instance *vf = sh->vfilter; csp->format = opts->requested_colorspace; csp->levels_in = opts->requested_input_range; @@ -113,7 +112,7 @@ void get_detected_video_colorspace(struct sh_video *sh, struct mp_csp_details *c if (csp->format == MP_CSP_AUTO) csp->format = sh->colorspace; if (csp->format == MP_CSP_AUTO) - csp->format = mp_csp_guess_colorspace(vf->w, vf->h); + csp->format = mp_csp_guess_colorspace(sh->disp_w, sh->disp_h); if (csp->levels_in == MP_CSP_LEVELS_AUTO) csp->levels_in = sh->color_range; @@ -400,8 +399,10 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, } #endif - if (!mpi || drop_frame) + if (!mpi || drop_frame) { + talloc_free(mpi); return NULL; // error / skipped frame + } if (field_dominance == 0) mpi->fields |= MP_IMGFIELD_TOP_FIRST; @@ -432,11 +433,3 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, sh_video->num_sorted_pts_problems++; return mpi; } - -int filter_video(sh_video_t *sh_video, void *frame, double pts) -{ - mp_image_t *mpi = frame; - vf_instance_t *vf = sh_video->vfilter; - // apply video filters and call the leaf vo/ve - return vf->put_image(vf, mpi, pts); -} diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 9eb90a5d5a..c7c535c68e 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -33,7 +33,6 @@ struct demux_packet; void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, unsigned char *start, int in_size, int drop_frame, double pts); -int filter_video(sh_video_t *sh_video, void *frame, double pts); int get_video_quality_max(sh_video_t *sh_video); diff --git a/video/decode/lavc.h b/video/decode/lavc.h index c4d24aad94..a355f61310 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -8,13 +8,9 @@ #include "demux/stheader.h" #include "video/mp_image.h" -#define MAX_NUM_MPI 50 - typedef struct ffmpeg_ctx { AVCodecContext *avctx; AVFrame *pic; - struct mp_image *last_mpi; - struct mp_image hwdec_mpi[MAX_NUM_MPI]; struct hwdec *hwdec; enum PixelFormat pix_fmt; int do_hw_dr1, do_dr1; @@ -28,6 +24,7 @@ typedef struct ffmpeg_ctx { int rawvideo_fmt; AVCodec *software_fallback; struct FramePool *dr1_buffer_pool; + struct mp_image_pool *non_dr1_pool; } vd_ffmpeg_ctx; int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame); diff --git a/video/decode/vd.c b/video/decode/vd.c index e030cf4bd0..e3cb70ad1b 100644 --- a/video/decode/vd.c +++ b/video/decode/vd.c @@ -190,9 +190,6 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) "VO Config (%dx%d->%dx%d,flags=%d,0x%X)\n", sh->disp_w, sh->disp_h, screen_size_x, screen_size_y, vocfg_flags, out_fmt); - vf->w = sh->disp_w; - vf->h = sh->disp_h; - if (vf_config_wrapper (vf, sh->disp_w, sh->disp_h, screen_size_x, screen_size_y, vocfg_flags, out_fmt) == 0) { diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 3ee8cc7932..7fd7437a3b 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -41,6 +41,7 @@ #include "vd.h" #include "video/img_format.h" +#include "video/mp_image_pool.h" #include "video/filter/vf.h" #include "demux/stheader.h" #include "demux/demux_packet.h" @@ -244,6 +245,7 @@ static int init(sh_video_t *sh) ctx = sh->context = talloc_zero(NULL, vd_ffmpeg_ctx); ctx->rawvideo_fmt = PIX_FMT_NONE; + ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16)); if (sh->codec->dll) { lavc_codec = avcodec_find_decoder_by_name(sh->codec->dll); @@ -478,7 +480,6 @@ static void uninit_avctx(sh_video_t *sh) av_freep(&avctx); avcodec_free_frame(&ctx->pic); - mp_image_unrefp(&ctx->last_mpi); mp_buffer_pool_free(&ctx->dr1_buffer_pool); } @@ -518,7 +519,7 @@ static int init_vo(sh_video_t *sh) width != sh->disp_w || height != sh->disp_h || avctx->pix_fmt != ctx->pix_fmt || !ctx->vo_initialized) { - mp_image_unrefp(&ctx->last_mpi); + mp_image_pool_clear(ctx->non_dr1_pool); ctx->vo_initialized = 0; mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] aspect_ratio: %f\n", aspect); @@ -579,22 +580,6 @@ static void draw_slice_hwdec(struct AVCodecContext *s, vf->control(vf, VFCTRL_HWDEC_DECODER_RENDER, state_ptr); } -static struct mp_image *get_image_hwdec(vd_ffmpeg_ctx *ctx) -{ - for (int n = 0; n < MAX_NUM_MPI; n++) { - struct mp_image *cur = &ctx->hwdec_mpi[n]; - if (cur->usage_count == 0) { - *cur = (struct mp_image) { - .number = n, - .imgfmt = ctx->best_csp, - .usage_count = 1, - }; - return cur; - } - } - return NULL; -} - static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic) { sh_video_t *sh = avctx->opaque; @@ -620,12 +605,12 @@ static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic) assert(IMGFMT_IS_HWACCEL(ctx->best_csp)); - struct mp_image *mpi = get_image_hwdec(ctx); - if (!mpi) - return -1; + struct mp_image *mpi = NULL; struct vf_instance *vf = sh->vfilter; - vf->control(vf, VFCTRL_HWDEC_GET_SURFACE, mpi); + vf->control(vf, VFCTRL_HWDEC_ALLOC_SURFACE, &mpi); + if (!mpi) + return -1; for (int i = 0; i < 4; i++) pic->data[i] = mpi->planes[i]; @@ -647,9 +632,8 @@ static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic) assert(pic->type == FF_BUFFER_TYPE_USER); assert(mpi); - assert(mpi->usage_count > 0); - mpi->usage_count--; + talloc_free(mpi); for (int i = 0; i < 4; i++) pic->data[i] = NULL; @@ -726,13 +710,14 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, void *data, return -1; struct mp_image *mpi = NULL; - if (ctx->do_hw_dr1 && pic->opaque) + if (ctx->do_hw_dr1 && pic->opaque) { mpi = pic->opaque; // reordered frame + assert(mpi); + mpi = mp_image_new_ref(mpi); + } if (!mpi) { struct mp_image new = {0}; - new.type = MP_IMGTYPE_EXPORT; - new.flags = MP_IMGFLAG_PRESERVE; mp_image_set_size(&new, avctx->width, avctx->height); mp_image_setfmt(&new, ctx->best_csp); for (int i = 0; i < 4; i++) { @@ -741,23 +726,17 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, void *data, } if (ctx->do_dr1 && pic->opaque) { struct FrameBuffer *fb = pic->opaque; - mp_image_unrefp(&ctx->last_mpi); - mp_buffer_ref(fb); // reference for last_mpi - ctx->last_mpi = mp_image_new_external_ref(&new, fb, fb_ref, - fb_unref, fb_is_unique); + mp_buffer_ref(fb); // initial reference for mpi + mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref, + fb_is_unique); } else { - if (!ctx->last_mpi) - ctx->last_mpi = mp_image_alloc(ctx->best_csp, new.w, new.h); - mp_image_make_writeable(&ctx->last_mpi); - assert(ctx->last_mpi->w == new.w && ctx->last_mpi->h == new.h); - assert(ctx->last_mpi->imgfmt == new.imgfmt); - mp_image_copy(ctx->last_mpi, &new); + mpi = mp_image_pool_get(ctx->non_dr1_pool, new.imgfmt, + new.w, new.h); + mp_image_copy(mpi, &new); } - mpi = ctx->last_mpi; } - if (!mpi->planes[0]) - return 0; // ? + assert(mpi->planes[0]); assert(mpi->imgfmt == pixfmt2imgfmt(avctx->pix_fmt)); diff --git a/video/filter/vf.c b/video/filter/vf.c index 417d5be1a3..4da167641a 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -33,6 +33,7 @@ #include "video/img_format.h" #include "video/mp_image.h" +#include "video/mp_image_pool.h" #include "vf.h" #include "video/memcpy_pic.h" @@ -177,182 +178,21 @@ void vf_mpi_clear(mp_image_t *mpi, int x0, int y0, int w, int h) } } -mp_image_t *vf_get_image(vf_instance_t *vf, unsigned int outfmt, - int mp_imgtype, int mp_imgflag, int w, int h) +// Get a new image for filter output, with size and pixel format according to +// the last vf_config call. +struct mp_image *vf_alloc_out_image(struct vf_instance *vf) { - mp_image_t *mpi = NULL; - int w2; - int number = mp_imgtype >> 16; - - assert(w == -1 || w >= vf->w); - assert(h == -1 || h >= vf->h); - assert(vf->w > 0); - assert(vf->h > 0); - - if (w == -1) - w = vf->w; - if (h == -1) - h = vf->h; - - w2 = (mp_imgflag & MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE) ? FFALIGN(w, 32) : w; - - if (vf->put_image == vf_next_put_image) { - // passthru mode, if the filter uses the fallback/default put_image() - mpi = vf_get_image(vf->next,outfmt,mp_imgtype,mp_imgflag,w,h); - mpi->usage_count++; - return mpi; - } - - // Note: we should call libvo first to check if it supports direct rendering - // and if not, then fallback to software buffers: - switch (mp_imgtype & 0xff) { - case MP_IMGTYPE_EXPORT: - if (!vf->imgctx.export_images[0]) - vf->imgctx.export_images[0] = new_mp_image(w2, h); - mpi = vf->imgctx.export_images[0]; - break; - case MP_IMGTYPE_STATIC: - if (!vf->imgctx.static_images[0]) - vf->imgctx.static_images[0] = new_mp_image(w2, h); - mpi = vf->imgctx.static_images[0]; - break; - case MP_IMGTYPE_TEMP: - if (!vf->imgctx.temp_images[0]) - vf->imgctx.temp_images[0] = new_mp_image(w2, h); - mpi = vf->imgctx.temp_images[0]; - break; - case MP_IMGTYPE_IPB: - if (!(mp_imgflag & MP_IMGFLAG_READABLE)) { // B frame: - if (!vf->imgctx.temp_images[0]) - vf->imgctx.temp_images[0] = new_mp_image(w2, h); - mpi = vf->imgctx.temp_images[0]; - break; - } - case MP_IMGTYPE_IP: - if (!vf->imgctx.static_images[vf->imgctx.static_idx]) - vf->imgctx.static_images[vf->imgctx.static_idx] = new_mp_image(w2, h); - mpi = vf->imgctx.static_images[vf->imgctx.static_idx]; - vf->imgctx.static_idx ^= 1; - break; - case MP_IMGTYPE_NUMBERED: - if (number == -1) { - int i; - for (i = 0; i < NUM_NUMBERED_MPI; i++) - if (!vf->imgctx.numbered_images[i] || - !vf->imgctx.numbered_images[i]->usage_count) - break; - number = i; - } - if (number < 0 || number >= NUM_NUMBERED_MPI) - return NULL; - if (!vf->imgctx.numbered_images[number]) - vf->imgctx.numbered_images[number] = new_mp_image(w2, h); - mpi = vf->imgctx.numbered_images[number]; - mpi->number = number; - break; - } - if (mpi) { - int missing_palette = !(mpi->flags & MP_IMGFLAG_RGB_PALETTE) && - (mp_imgflag & MP_IMGFLAG_RGB_PALETTE); - mpi->type = mp_imgtype; - mpi->w = vf->w; - mpi->h = vf->h; - // keep buffer allocation status & color flags only: - mpi->flags &= MP_IMGFLAG_ALLOCATED | MP_IMGFLAG_TYPE_DISPLAYED | - MP_IMGFLAGMASK_COLORS; - // accept restrictions, palette flags only: - mpi->flags |= mp_imgflag & (MP_IMGFLAGMASK_RESTRICTIONS | - MP_IMGFLAG_RGB_PALETTE); - if (mpi->width != w2 || mpi->height != h || missing_palette) { - if (mpi->flags & MP_IMGFLAG_ALLOCATED) { - if (mpi->width < w2 || mpi->height < h || missing_palette) { - // need to re-allocate buffer memory: - av_free(mpi->planes[0]); - if (mpi->flags & MP_IMGFLAG_RGB_PALETTE) - av_free(mpi->planes[1]); - for (int n = 0; n < MP_MAX_PLANES; n++) - mpi->planes[n] = NULL; - mpi->flags &= ~MP_IMGFLAG_ALLOCATED; - mp_msg(MSGT_VFILTER, MSGL_V, - "vf.c: have to REALLOCATE buffer memory :(\n"); - } - } - mpi->width = w2; - mpi->chroma_width = (w2 + (1 << mpi->chroma_x_shift) - 1) >> - mpi->chroma_x_shift; - mpi->height = h; - mpi->chroma_height = (h + (1 << mpi->chroma_y_shift) - 1) >> - mpi->chroma_y_shift; - } - if (!mpi->bpp) - mp_image_setfmt(mpi, outfmt); - if (!(mpi->flags & MP_IMGFLAG_ALLOCATED) && - mpi->type > MP_IMGTYPE_EXPORT) { - // check libvo first! - if (vf->get_image) - vf->get_image(vf, mpi); - - if (!(mpi->flags & MP_IMGFLAG_DIRECT)) { - // non-direct and not yet allocated image. allocate it! - if (!mpi->bpp) { // no way we can allocate this - mp_msg(MSGT_DECVIDEO, MSGL_FATAL, - "vf_get_image: Tried to allocate a format that " - "can not be allocated!\n"); - return NULL; - } - - // check if codec prefer aligned stride: - if (mp_imgflag & MP_IMGFLAG_PREFER_ALIGNED_STRIDE) { - int align = (mpi->flags & MP_IMGFLAG_PLANAR && - mpi->flags & MP_IMGFLAG_YUV) ? - (16 << mpi->chroma_x_shift) - 1 : 32; // OK? - w2 = FFALIGN(w, align); - if (mpi->width != w2) { - // we have to change width... check if we CAN co it: - int flags = vf->query_format(vf, outfmt); - // should not fail - if (!(flags & (VFCAP_CSP_SUPPORTED | - VFCAP_CSP_SUPPORTED_BY_HW))) - mp_msg(MSGT_DECVIDEO, MSGL_WARN, - "??? vf_get_image{vf->query_format(outfmt)} " - "failed!\n"); - if (flags & VFCAP_ACCEPT_STRIDE) { - mpi->width = w2; - mpi->chroma_width = - (w2 + (1 << mpi->chroma_x_shift) - 1) >> - mpi->chroma_x_shift; - } - } - } + assert(vf->fmt_out.configured); + return mp_image_pool_get(vf->out_pool, vf->fmt_out.fmt, + vf->fmt_out.w, vf->fmt_out.h); +} - mp_image_alloc_planes(mpi); - vf_mpi_clear(mpi, 0, 0, mpi->width, mpi->height); - } - } - if (!(mpi->flags & MP_IMGFLAG_TYPE_DISPLAYED)) { - mp_msg(MSGT_DECVIDEO, MSGL_V, - "*** [%s] %s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n", - vf->info->name, - (mpi->type == MP_IMGTYPE_EXPORT) ? "Exporting" : - ((mpi->flags & MP_IMGFLAG_DIRECT) ? - "Direct Rendering" : "Allocating"), - mpi->width, mpi->height, mpi->bpp, - (mpi->flags & MP_IMGFLAG_YUV) ? "YUV" : - ((mpi->flags & MP_IMGFLAG_SWAPPED) ? "BGR" : "RGB"), - (mpi->flags & MP_IMGFLAG_PLANAR) ? "planar" : "packed", - mpi->bpp * mpi->width * mpi->height / 8); - mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "(imgfmt: %x, planes: %p,%p,%p " - "strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n", - mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2], - mpi->stride[0], mpi->stride[1], mpi->stride[2], - mpi->chroma_width, mpi->chroma_height, - mpi->chroma_x_shift, mpi->chroma_y_shift); - mpi->flags |= MP_IMGFLAG_TYPE_DISPLAYED; - } - mpi->qscale = NULL; - mpi->usage_count++; - } - return mpi; +void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img) +{ + assert(vf->fmt_out.configured); + assert(vf->fmt_out.fmt == img->imgfmt); + assert(vf->fmt_out.w == img->w && vf->fmt_out.h == img->h); + mp_image_pool_make_writeable(vf->out_pool, img); } //============================================================================ @@ -362,6 +202,14 @@ static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt) return vf_next_query_format(vf, fmt); } + +static struct mp_image *vf_default_filter(struct vf_instance *vf, + struct mp_image *mpi) +{ + assert(!vf->filter_ext); + return mpi; +} + struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts, const vf_info_t *const *filter_list, vf_instance_t *next, const char *name, @@ -378,16 +226,15 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts, if (!strcmp(filter_list[i]->name, name)) break; } - vf = calloc(1, sizeof *vf); + vf = talloc_zero(NULL, struct vf_instance); vf->opts = opts; vf->info = filter_list[i]; vf->next = next; vf->config = vf_next_config; vf->control = vf_next_control; vf->query_format = vf_default_query_format; - vf->put_image = vf_next_put_image; - vf->default_caps = VFCAP_ACCEPT_STRIDE; - vf->default_reqs = 0; + vf->filter = vf_default_filter; + vf->out_pool = talloc_steal(vf, mp_image_pool_new(16)); if (vf->info->opts) { // vf_vo get some special argument const m_struct_t *st = vf->info->opts; void *vf_priv = m_struct_alloc(st); @@ -404,7 +251,7 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts, *retcode = vf->info->vf_open(vf, (char *)args); if (*retcode > 0) return vf; - free(vf); + talloc_free(vf); return NULL; } @@ -530,6 +377,7 @@ void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src) dst->pict_type = src->pict_type; dst->fields = src->fields; dst->qscale_type = src->qscale_type; + dst->pts = src->pts; if (dst->width == src->width && dst->height == src->height) { dst->qstride = src->qstride; dst->qscale = src->qscale; @@ -542,60 +390,84 @@ void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src) } } -void vf_queue_frame(vf_instance_t *vf, int (*func)(vf_instance_t *)) +// Used by filters to add a filtered frame to the output queue. +// Ownership of img is transferred from caller to the filter chain. +void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img) { - vf->continue_buffered_image = func; + if (img) + MP_TARRAY_APPEND(vf, vf->out_queued, vf->num_out_queued, img); } -// Output the next buffered image (if any) from the filter chain. -// The queue could be kept as a simple stack/list instead avoiding the -// looping here, but there's currently no good context variable where -// that could be stored so this was easier to implement. |