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(vf->fmt_out.configured); + return mp_image_pool_get(vf->out_pool, vf->fmt_out.fmt, + vf->fmt_out.w, vf->fmt_out.h); +} - 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; - } - } - } - - 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. - -int vf_output_queued_frame(vf_instance_t *vf) +static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf) { - while (1) { - int ret; - vf_instance_t *current; - vf_instance_t *last = NULL; - int (*tmp)(vf_instance_t *); - for (current = vf; current; current = current->next) - if (current->continue_buffered_image) - last = current; - if (!last) - return 0; - tmp = last->continue_buffered_image; - last->continue_buffered_image = NULL; - ret = tmp(last); - if (ret) - return ret; + struct mp_image *res = NULL; + if (vf->num_out_queued) { + res = vf->out_queued[0]; + MP_TARRAY_REMOVE_AT(vf->out_queued, vf->num_out_queued, 0); + } + return res; +} + +// Input a frame into the filter chain. +// Return >= 0 on success, < 0 on failure (even if output frames were produced) +int vf_filter_frame(struct vf_instance *vf, struct mp_image *img) +{ + assert(vf->fmt_in.configured); + assert(img->w == vf->fmt_in.w && img->h == vf->fmt_in.h); + assert(img->imgfmt == vf->fmt_in.fmt); + + if (vf->filter_ext) { + return vf->filter_ext(vf, img); + } else { + vf_add_output_frame(vf, vf->filter(vf, img)); + return 0; } } +// Output the next queued image (if any) from the full filter chain. +struct mp_image *vf_chain_output_queued_frame(struct vf_instance *vf) +{ + while (1) { + struct vf_instance *last = NULL; + for (struct vf_instance * cur = vf; cur; cur = cur->next) { + if (cur->num_out_queued) + last = cur; + } + if (!last) + return NULL; + struct mp_image *img = vf_dequeue_output_frame(last); + if (!last->next) + return img; + vf_filter_frame(last->next, img); + } +} + +static void vf_forget_frames(struct vf_instance *vf) +{ + for (int n = 0; n < vf->num_out_queued; n++) + talloc_free(vf->out_queued[n]); + vf->num_out_queued = 0; +} -/** - * \brief Video config() function wrapper - * - * Blocks config() calls with different size or format for filters - * with VFCAP_CONSTANT - * - * First call is redirected to vf->config. - * - * In following calls, it verifies that the configuration parameters - * are unchanged, and returns either success or error. - * - */ int vf_config_wrapper(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) { - vf->fmt.have_configured = 1; - vf->fmt.orig_height = height; - vf->fmt.orig_width = width; - vf->fmt.orig_fmt = outfmt; + vf_forget_frames(vf); + mp_image_pool_clear(vf->out_pool); + + vf->fmt_in = vf->fmt_out = (struct vf_format){0}; + int r = vf->config(vf, width, height, d_width, d_height, flags, outfmt); - if (!r) - vf->fmt.have_configured = 0; + if (r) { + vf->fmt_in = (struct vf_format) { + .configured = 1, + .w = width, + .h = height, + .fmt = outfmt, + }; + vf->fmt_out = vf->next ? vf->next->fmt_in : (struct vf_format){0}; + } return r; } @@ -604,7 +476,6 @@ int vf_next_config(struct vf_instance *vf, unsigned int voflags, unsigned int outfmt) { struct MPOpts *opts = vf->opts; - int miss; int flags = vf->next->query_format(vf->next, outfmt); if (!flags) { // hmm. colorspace mismatch!!! @@ -623,19 +494,6 @@ int vf_next_config(struct vf_instance *vf, return 0; // FAIL } } - mp_msg(MSGT_VFILTER, MSGL_V, "REQ: flags=0x%X req=0x%X \n", - flags, vf->default_reqs); - miss = vf->default_reqs - (flags & vf->default_reqs); - if (miss & VFCAP_ACCEPT_STRIDE) { - // vf requires stride support but vf->next doesn't support it! - // let's insert the 'expand' filter, it does the job for us: - vf_instance_t *vf2 = vf_open_filter(opts, vf->next, "expand", NULL); - if (!vf2) - return 0; // shouldn't happen! - vf->next = vf2; - } - vf->next->w = width; - vf->next->h = height; return vf_config_wrapper(vf->next, width, height, d_width, d_height, voflags, outfmt); } @@ -653,11 +511,6 @@ int vf_next_query_format(struct vf_instance *vf, unsigned int fmt) return flags; } -int vf_next_put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) -{ - return vf->next->put_image(vf->next, mpi, pts); -} - //============================================================================ vf_instance_t *append_filters(vf_instance_t *last, @@ -688,13 +541,8 @@ void vf_uninit_filter(vf_instance_t *vf) { if (vf->uninit) vf->uninit(vf); - free_mp_image(vf->imgctx.static_images[0]); - free_mp_image(vf->imgctx.static_images[1]); - free_mp_image(vf->imgctx.temp_images[0]); - free_mp_image(vf->imgctx.export_images[0]); - for (int i = 0; i < NUM_NUMBERED_MPI; i++) - free_mp_image(vf->imgctx.numbered_images[i]); - free(vf); + vf_forget_frames(vf); + talloc_free(vf); } void vf_uninit_filter_chain(vf_instance_t *vf) diff --git a/video/filter/vf.h b/video/filter/vf.h index 1a850995f3..ac9394024f 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -41,19 +41,9 @@ typedef struct vf_info { const void *opts; } vf_info_t; -#define NUM_NUMBERED_MPI 50 - -struct vf_image_context { - mp_image_t *static_images[2]; - mp_image_t *temp_images[1]; - mp_image_t *export_images[1]; - mp_image_t *numbered_images[NUM_NUMBERED_MPI]; - int static_idx; -}; - -struct vf_format_context { - int have_configured; - int orig_width, orig_height, orig_fmt; +struct vf_format { + int configured; + int w, h, fmt; }; typedef struct vf_instance { @@ -64,22 +54,31 @@ typedef struct vf_instance { unsigned int flags, unsigned int outfmt); int (*control)(struct vf_instance *vf, int request, void *data); int (*query_format)(struct vf_instance *vf, unsigned int fmt); - void (*get_image)(struct vf_instance *vf, mp_image_t *mpi); - int (*put_image)(struct vf_instance *vf, mp_image_t *mpi, double pts); + + // Filter mpi and return the result. The input mpi reference is owned by + // the filter, the returned reference is owned by the caller. + // Return NULL if the output frame is skipped. + struct mp_image *(*filter)(struct vf_instance *vf, struct mp_image *mpi); + + // Like filter(), but can return an error code ( >= 0 means success). This + // callback is also more practical when the filter can return multiple + // output images. Use vf_add_output_frame() to queue output frames. + int (*filter_ext)(struct vf_instance *vf, struct mp_image *mpi); + void (*uninit)(struct vf_instance *vf); - int (*continue_buffered_image)(struct vf_instance *vf); // caps: unsigned int default_caps; // used by default query_format() - unsigned int default_reqs; // used by default config() // data: - int w, h; - struct vf_image_context imgctx; - struct vf_format_context fmt; + struct vf_format fmt_in, fmt_out; struct vf_instance *next; - mp_image_t *dmpi; + + struct mp_image_pool *out_pool; struct vf_priv_s *priv; struct MPOpts *opts; + + struct mp_image **out_queued; + int num_out_queued; } vf_instance_t; typedef struct vf_seteq { @@ -98,7 +97,7 @@ struct vf_ctrl_screenshot { #define VFCTRL_SET_EQUALIZER 6 // set color options (brightness,contrast etc) #define VFCTRL_GET_EQUALIZER 8 // get color options (brightness,contrast etc) #define VFCTRL_HWDEC_DECODER_RENDER 9 // vdpau hw decoding -#define VFCTRL_HWDEC_GET_SURFACE 10 // vdpau hw decoding +#define VFCTRL_HWDEC_ALLOC_SURFACE 10 // vdpau hw decoding #define VFCTRL_SCREENSHOT 14 // Take screenshot, arg is vf_ctrl_screenshot #define VFCTRL_INIT_OSD 15 // Filter OSD renderer present? #define VFCTRL_SET_DEINTERLACE 18 // Set deinterlacing status @@ -111,8 +110,13 @@ struct vf_ctrl_screenshot { // functions: 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); + +struct mp_image *vf_alloc_out_image(struct vf_instance *vf); +void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img); +void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img); + +int vf_filter_frame(struct vf_instance *vf, struct mp_image *img); +struct mp_image *vf_chain_output_queued_frame(struct vf_instance *vf); vf_instance_t *vf_open_plugin(struct MPOpts *opts, const vf_info_t * const *filter_list, vf_instance_t *next, @@ -123,14 +127,10 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts, vf_instance_t *vf_open_filter(struct MPOpts *opts, vf_instance_t *next, const char *name, char **args); vf_instance_t *vf_add_before_vo(vf_instance_t **vf, char *name, char **args); -vf_instance_t *vf_open_encoder(struct MPOpts *opts, vf_instance_t *next, - const char *name, char *args); unsigned int vf_match_csp(vf_instance_t **vfp, const unsigned int *list, unsigned int preferred); void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src); -void vf_queue_frame(vf_instance_t *vf, int (*)(vf_instance_t *)); -int vf_output_queued_frame(vf_instance_t *vf); // default wrappers: int vf_next_config(struct vf_instance *vf, @@ -138,7 +138,6 @@ int vf_next_config(struct vf_instance *vf, unsigned int flags, unsigned int outfmt); int vf_next_control(struct vf_instance *vf, int request, void *data); int vf_next_query_format(struct vf_instance *vf, unsigned int fmt); -int vf_next_put_image(struct vf_instance *vf, mp_image_t *mpi, double pts); struct m_obj_settings; vf_instance_t *append_filters(vf_instance_t *last, diff --git a/video/filter/vf_crop.c b/video/filter/vf_crop.c index ed3457da70..692d05bcc9 100644 --- a/video/filter/vf_crop.c +++ b/video/filter/vf_crop.c @@ -84,11 +84,9 @@ static int config(struct vf_instance *vf, return vf_next_config(vf,vf->priv->crop_w,vf->priv->crop_h,d_width,d_height,flags,outfmt); } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi; - dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_EXPORT, 0, - vf->priv->crop_w, vf->priv->crop_h); +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + mp_image_t *dmpi = mpi; if(mpi->flags&MP_IMGFLAG_PLANAR){ dmpi->planes[0]=mpi->planes[0]+ vf->priv->crop_y*mpi->stride[0]+vf->priv->crop_x; @@ -102,19 +100,16 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ dmpi->planes[0]=mpi->planes[0]+ vf->priv->crop_y*mpi->stride[0]+ vf->priv->crop_x*(mpi->bpp/8); - dmpi->planes[1]=mpi->planes[1]; // passthrough rgb8 palette } - dmpi->stride[0]=mpi->stride[0]; - dmpi->width=mpi->width; - return vf_next_put_image(vf,dmpi, pts); + mp_image_set_size(dmpi, vf->priv->crop_w, vf->priv->crop_h); + return mpi; } //===========================================================================// static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->put_image=put_image; - vf->default_reqs=VFCAP_ACCEPT_STRIDE; + vf->filter=filter; mp_msg(MSGT_VFILTER, MSGL_INFO, "Crop: %d x %d, %d ; %d\n", vf->priv->crop_w, vf->priv->crop_h, diff --git a/video/filter/vf_delogo.c b/video/filter/vf_delogo.c index f53e5059bd..f709aad4d0 100644 --- a/video/filter/vf_delogo.c +++ b/video/filter/vf_delogo.c @@ -101,7 +101,7 @@ static void update_sub(struct vf_priv_s *p, double pts) } static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, - int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) { + int logo_x, int logo_y, int logo_w, int logo_h, int band, int show) { int y, x; int interp, dist; uint8_t *xdst, *xsrc; @@ -124,8 +124,6 @@ static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int topright = src+logo_y1*srcStride+logo_x2-1; botleft = src+(logo_y2-1)*srcStride+logo_x1; - if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride); - dst += (logo_y1+1)*dstStride; src += (logo_y1+1)*srcStride; @@ -175,55 +173,26 @@ static int config(struct vf_instance *vf, return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); } - -static void get_image(struct vf_instance *vf, mp_image_t *mpi){ - if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change - if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ - // ok, we can do pp in-place (or pp disabled): - mpi->priv = - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - mpi->type, mpi->flags, mpi->w, mpi->h); - mpi->planes[0]=vf->dmpi->planes[0]; - mpi->stride[0]=vf->dmpi->stride[0]; - mpi->width=vf->dmpi->width; - if(mpi->flags&MP_IMGFLAG_PLANAR){ - mpi->planes[1]=vf->dmpi->planes[1]; - mpi->planes[2]=vf->dmpi->planes[2]; - mpi->stride[1]=vf->dmpi->stride[1]; - mpi->stride[2]=vf->dmpi->stride[2]; +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + struct mp_image *dmpi = mpi; + if (!mp_image_is_writeable(mpi)) { + dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); } - mpi->flags|=MP_IMGFLAG_DIRECT; -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi; - - if(mpi->flags&MP_IMGFLAG_DIRECT) { - vf->dmpi = mpi->priv; - mpi->priv = NULL; - } else { - // no DR, so get a new image! hope we'll get DR buffer: - vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->w,mpi->h); - } - dmpi= vf->dmpi; if (vf->priv->timed_rect) - update_sub(vf->priv, pts); + update_sub(vf->priv, dmpi->pts); delogo(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, - vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show, - mpi->flags&MP_IMGFLAG_DIRECT); + vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show); delogo(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, - vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show, - mpi->flags&MP_IMGFLAG_DIRECT); + vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show); delogo(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, - vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show, - mpi->flags&MP_IMGFLAG_DIRECT); + vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show); - vf_clone_mpi_attributes(dmpi, mpi); - - return vf_next_put_image(vf,dmpi, pts); + if (dmpi != mpi) + talloc_free(mpi); + return dmpi; } static void uninit(struct vf_instance *vf){ @@ -323,8 +292,7 @@ load_error: static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->put_image=put_image; - vf->get_image=get_image; + vf->filter=filter; vf->query_format=query_format; vf->uninit=uninit; diff --git a/video/filter/vf_divtc.c b/video/filter/vf_divtc.c index 02386d0d3b..dadccf9a9b 100644 --- a/video/filter/vf_divtc.c +++ b/video/filter/vf_divtc.c @@ -46,6 +46,7 @@ struct vf_priv_s unsigned int *csdata; int *history; struct vf_detc_pts_buf ptsbuf; + struct mp_image *buffer; }; /* @@ -258,19 +259,23 @@ static int match(struct vf_priv_s *p, int *diffs, return m; } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - mp_image_t *dmpi, *tmpi=0; int n, m, f, newphase; struct vf_priv_s *p=vf->priv; unsigned int checksum; double d; - dmpi=vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | - MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE, - mpi->width, mpi->height); - vf_clone_mpi_attributes(dmpi, mpi); + if (!p->buffer || p->buffer->w != mpi->w || p->buffer->h != mpi->h || + p->buffer->imgfmt != mpi->imgfmt) + { + mp_image_unrefp(&p->buffer); + p->buffer = mp_image_alloc(mpi->imgfmt, mpi->w, mpi->h); + talloc_steal(vf, p->buffer); + } + + struct mp_image *dmpi = p->buffer; + double pts = mpi->pts; newphase=p->phase; @@ -360,26 +365,24 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) case 0: imgop(copyop, dmpi, mpi, 0); vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); + talloc_free(mpi); return 0; case 4: if(p->deghost>0) { - tmpi=vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | - MP_IMGFLAG_READABLE, - mpi->width, mpi->height); - vf_clone_mpi_attributes(tmpi, mpi); + imgop(copyop, dmpi, mpi, 0); + vf_make_out_image_writeable(vf, mpi); - imgop(copyop, tmpi, mpi, 0); - imgop(deghost_plane, tmpi, dmpi, p->deghost); - imgop(copyop, dmpi, mpi, 0); - return vf_next_put_image(vf, tmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); + imgop(deghost_plane, mpi, dmpi, p->deghost); + mpi->pts = vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0); + return mpi; } } imgop(copyop, dmpi, mpi, 0); - return vf_next_put_image(vf, dmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); + mpi->pts = vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0); + return mpi; } static int analyze(struct vf_priv_s *p) @@ -613,10 +616,9 @@ static int vf_open(vf_instance_t *vf, char *args) return 0; } - vf->put_image=put_image; + vf->filter=filter; vf->uninit=uninit; vf->query_format=query_format; - vf->default_reqs=VFCAP_ACCEPT_STRIDE; if(!(vf->priv=p=calloc(1, sizeof(struct vf_priv_s)))) goto nomem; diff --git a/video/filter/vf_dlopen.c b/video/filter/vf_dlopen.c index e440b3759e..639f1c1d36 100644 --- a/video/filter/vf_dlopen.c +++ b/video/filter/vf_dlopen.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "config.h" #include "core/mp_msg.h" @@ -149,14 +150,13 @@ static int config(struct vf_instance *vf, return 0; } - if (vf->priv->out_cnt >= 2) { - int i; - for (i = 0; i < vf->priv->out_cnt; ++i) { - vf->priv->outpic[i] = - alloc_mpi(vf->priv->out_width, vf->priv->out_height, - vf->priv->outfmt); - set_imgprop(&vf->priv->filter.outpic[i], vf->priv->outpic[i]); - } + for (int i = 0; i < vf->priv->out_cnt; ++i) { + talloc_free(vf->priv->outpic[i]); + vf->priv->outpic[i] = + mp_image_alloc(vf->priv->out_width, vf->priv->out_height, + vf->priv->outfmt); + set_imgprop(&vf->priv->filter.outpic[i], vf->priv->outpic[i]); + talloc_steal(vf, vf->priv->outpic[i]); } return vf_next_config(vf, vf->priv->out_width, @@ -175,52 +175,13 @@ static void uninit(struct vf_instance *vf) DLLClose(vf->priv->dll); vf->priv->dll = NULL; } - if (vf->priv->out_cnt >= 2) { - int i; - for (i = 0; i < vf->priv->out_cnt; ++i) { - free_mp_image(vf->priv->outpic[i]); - vf->priv->outpic[i] = NULL; - } - } if (vf->priv->qbuffer) { free(vf->priv->qbuffer); vf->priv->qbuffer = NULL; } } -// NOTE: only called if (vf->priv->out_cnt >= 2) { -static int continue_put_image(struct vf_instance *vf) -{ - int k; - int ret = 0; - - mp_image_t *dmpi = - vf_get_image(vf->next, vf->priv->outfmt, MP_IMGTYPE_EXPORT, 0, - vf->priv->outpic[vf->priv->outbufferpos]->w, - vf->priv->outpic[vf->priv->outbufferpos]->h); - for (k = 0; k < vf->priv->outpic[vf->priv->outbufferpos]->num_planes; - ++k) { - dmpi->planes[k] = vf->priv->outpic[vf->priv->outbufferpos]->planes[k]; - dmpi->stride[k] = vf->priv->outpic[vf->priv->outbufferpos]->stride[k]; - } - - // pass through qscale if we can - vf_clone_mpi_attributes(dmpi, vf->priv->outbuffermpi); - - ret = - vf_next_put_image(vf, dmpi, - vf->priv->filter.outpic[vf->priv->outbufferpos].pts); - - ++vf->priv->outbufferpos; - - // more frames left? - if (vf->priv->outbufferpos < vf->priv->outbufferlen) - vf_queue_frame(vf, continue_put_image); - - return ret; -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static int filter(struct vf_instance *vf, struct mp_image *mpi) { int i, k; @@ -245,36 +206,32 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) vf->priv->filter.inpic_qscalestride = 0; vf->priv->filter.inpic_qscaleshift = 0; } - vf->priv->filter.inpic.pts = pts; + vf->priv->filter.inpic.pts = mpi->pts; - if (vf->priv->out_cnt >= 2) { - // more than one out pic - int ret = vf->priv->filter.put_image(&vf->priv->filter); - if (ret <= 0) - return ret; + struct mp_image *out[FILTER_MAX_OUTCNT] = {0}; - vf->priv->outbuffermpi = mpi; - vf->priv->outbufferlen = ret; - vf->priv->outbufferpos = 0; - return continue_put_image(vf); - } else { - // efficient case: exactly one out pic - mp_image_t *dmpi = - vf_get_image(vf->next, vf->priv->outfmt, - MP_IMGTYPE_TEMP, - MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE, - vf->priv->out_width, vf->priv->out_height); - set_imgprop(&vf->priv->filter.outpic[0], dmpi); - - int ret = vf->priv->filter.put_image(&vf->priv->filter); - if (ret <= 0) - return ret; - - // pass through qscale if we can - vf_clone_mpi_attributes(dmpi, mpi); - - return vf_next_put_image(vf, dmpi, vf->priv->filter.outpic[0].pts); + for (int n = 0; n < vf->priv->out_cnt; n++) { + out[n] = vf_alloc_out_image(vf); + mp_image_copy_attributes(out[n], mpi); + set_imgprop(&vf->priv->filter.outpic[n], out[n]); } + + // more than one out pic + int ret = vf->priv->filter.put_image(&vf->priv->filter); + if (ret < 0) + ret = 0; + assert(ret <= vf->priv->out_cnt); + + for (int n = 0; n < ret; n++) { + out[n]->pts = vf->priv->filter.outpic[n].pts; + vf_add_output_frame(vf, out[n]); + } + for (int n = ret; n < FILTER_MAX_OUTCNT; n++) { + talloc_free(out[n]); + } + + talloc_free(mpi); + return 0; } //===========================================================================// @@ -319,7 +276,7 @@ static int vf_open(vf_instance_t *vf, char *args) vf->priv->cfg_dllname); return 0; } - + vf_dlopen_getcontext_func *func = (vf_dlopen_getcontext_func *) DLLSymbol(vf->priv->dll, "vf_dlopen_getcontext"); if (!func) { @@ -352,7 +309,7 @@ static int vf_open(vf_instance_t *vf, char *args) return 0; } - vf->put_image = put_image; + vf->filter_ext = filter; vf->query_format = query_format; vf->config = config; vf->uninit = uninit; diff --git a/video/filter/vf_down3dright.c b/video/filter/vf_down3dright.c index 64ecaffb94..b1835cd26b 100644 --- a/video/filter/vf_down3dright.c +++ b/video/filter/vf_down3dright.c @@ -96,21 +96,16 @@ static void toright(unsigned char *dst[3], unsigned char *src[3], } } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - mp_image_t *dmpi; - - // hope we'll get DR buffer: - dmpi=vf_get_image(vf->next, IMGFMT_YV12, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | - ((vf->priv->scaleh == 1) ? MP_IMGFLAG_READABLE : 0), - mpi->w * vf->priv->scalew, - mpi->h / vf->priv->scaleh - vf->priv->skipline); + mp_image_t *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); toright(dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h, vf->priv); - return vf_next_put_image(vf,dmpi, pts); + talloc_free(mpi); + return dmpi; } static int config(struct vf_instance *vf, @@ -144,7 +139,7 @@ static int vf_open(vf_instance_t *vf, char *args) { vf->config=config; vf->query_format=query_format; - vf->put_image=put_image; + vf->filter=filter; vf->uninit=uninit; vf->priv = calloc(1, sizeof (struct vf_priv_s)); diff --git a/video/filter/vf_dsize.c b/video/filter/vf_dsize.c index 7df9feb127..ef1d679906 100644 --- a/video/filter/vf_dsize.c +++ b/video/filter/vf_dsize.c @@ -85,7 +85,6 @@ static int vf_open(vf_instance_t *vf, char *args) { vf->config = config; vf->uninit = uninit; - //vf->default_caps = 0; vf->priv = calloc(sizeof(struct vf_priv_s), 1); vf->priv->aspect = 0.; vf->priv->w = -1; diff --git a/video/filter/vf_eq.c b/video/filter/vf_eq.c index 57945dc379..cfbe7ea17e 100644 --- a/video/filter/vf_eq.c +++ b/video/filter/vf_eq.c @@ -237,16 +237,20 @@ void apply_lut (eq2_param_t *par, unsigned char *dst, unsigned char *src, } } -static -int put_image (vf_instance_t *vf, mp_image_t *src, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *src) { - unsigned i; vf_eq2_t *eq2; - mp_image_t *dst; unsigned long img_n,img_c; eq2 = vf->priv; + bool skip = true; + for (int i = 0; i < 3; i++) + skip &= eq2->param[i].adjust == NULL; + + if (skip) + return src; + if ((eq2->buf_w[0] != src->w) || (eq2->buf_h[0] != src->h)) { eq2->buf_w[0] = src->w; eq2->buf_h[0] = src->h; @@ -262,23 +266,24 @@ int put_image (vf_instance_t *vf, mp_image_t *src, double pts) eq2->buf[0] = realloc (eq2->buf[0], img_n); } - dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h); + struct mp_image dst = *src; - for (i = 0; i < ((src->num_planes>1)?3:1); i++) { + for (int i = 0; i < ((src->num_planes>1)?3:1); i++) { if (eq2->param[i].adjust != NULL) { - dst->planes[i] = eq2->buf[i]; - dst->stride[i] = eq2->buf_w[i]; + dst.planes[i] = eq2->buf[i]; + dst.stride[i] = eq2->buf_w[i]; - eq2->param[i].adjust (&eq2->param[i], dst->planes[i], src->planes[i], - eq2->buf_w[i], eq2->buf_h[i], dst->stride[i], src->stride[i]); - } - else { - dst->planes[i] = src->planes[i]; - dst->stride[i] = src->stride[i]; + eq2->param[i].adjust (&eq2->param[i], dst.planes[i], src->planes[i], + eq2->buf_w[i], eq2->buf_h[i], dst.stride[i], src->stride[i]); } } - return vf_next_put_image (vf, dst, pts); + struct mp_image *new = vf_alloc_out_image(vf); + mp_image_copy(new, &dst); + mp_image_copy_attributes(new, &dst); + + talloc_free(src); + return new; } static @@ -454,7 +459,7 @@ int vf_open(vf_instance_t *vf, char *args) vf->control = control; vf->query_format = query_format; - vf->put_image = put_image; + vf->filter = filter; vf->uninit = uninit; vf->priv = malloc (sizeof (vf_eq2_t)); diff --git a/video/filter/vf_expand.c b/video/filter/vf_expand.c index 3d1e3467f4..5f5ffcae7f 100644 --- a/video/filter/vf_expand.c +++ b/video/filter/vf_expand.c @@ -124,97 +124,54 @@ static int config(struct vf_instance *vf, return vf_next_config(vf,vf->priv->exp_w,vf->priv->exp_h,d_width,d_height,flags,outfmt); } -// there are 4 cases: -// codec --DR--> expand --DR--> vo -// codec --DR--> expand -copy-> vo -// codec -copy-> expand --DR--> vo -// codec -copy-> expand -copy-> vo (worst case) - -static void get_image(struct vf_instance *vf, mp_image_t *mpi){ -// if(mpi->type==MP_IMGTYPE_IPB) return; // not yet working - if(vf->priv->exp_w==mpi->width || - (mpi->flags&(MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ACCEPT_WIDTH)) ){ - // try full DR ! - mpi->priv=vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - mpi->type, mpi->flags, - FFMAX(vf->priv->exp_w, mpi->width +vf->priv->exp_x), - FFMAX(vf->priv->exp_h, mpi->height+vf->priv->exp_y)); - // set up mpi as a cropped-down image of dmpi: - if(mpi->flags&MP_IMGFLAG_PLANAR){ - mpi->planes[0]=vf->dmpi->planes[0]+ - vf->priv->exp_y*vf->dmpi->stride[0]+vf->priv->exp_x; - mpi->planes[1]=vf->dmpi->planes[1]+ - (vf->priv->exp_y>>mpi->chroma_y_shift)*vf->dmpi->stride[1]+(vf->priv->exp_x>>mpi->chroma_x_shift); - mpi->planes[2]=vf->dmpi->planes[2]+ - (vf->priv->exp_y>>mpi->chroma_y_shift)*vf->dmpi->stride[2]+(vf->priv->exp_x>>mpi->chroma_x_shift); - mpi->stride[1]=vf->dmpi->stride[1]; - mpi->stride[2]=vf->dmpi->stride[2]; - } else { - mpi->planes[0]=vf->dmpi->planes[0]+ - vf->priv->exp_y*vf->dmpi->stride[0]+ - vf->priv->exp_x*(vf->dmpi->bpp/8); - } - mpi->stride[0]=vf->dmpi->stride[0]; - mpi->width=vf->dmpi->width; - mpi->flags|=MP_IMGFLAG_DIRECT; - } -} - -// w, h = width and height of the actual video frame (located at exp_x/exp_y) -static void clear_borders(struct vf_instance *vf, int w, int h) +// w, h = width and height of the source frame (located at exp_x/exp_y) +static void clear_borders(struct vf_instance *vf, struct mp_image *dmpi, + int w, int h) { // upper border (over the full width) - vf_mpi_clear(vf->dmpi, 0, 0, vf->priv->exp_w, vf->priv->exp_y); + vf_mpi_clear(dmpi, 0, 0, vf->priv->exp_w, vf->priv->exp_y); // lower border - vf_mpi_clear(vf->dmpi, 0, vf->priv->exp_y + h, vf->priv->exp_w, + vf_mpi_clear(dmpi, 0, vf->priv->exp_y + h, vf->priv->exp_w, vf->priv->exp_h - (vf->priv->exp_y + h)); // left - vf_mpi_clear(vf->dmpi, 0, vf->priv->exp_y, vf->priv->exp_x, h); + vf_mpi_clear(dmpi, 0, vf->priv->exp_y, vf->priv->exp_x, h); // right - vf_mpi_clear(vf->dmpi, vf->priv->exp_x + w, vf->priv->exp_y, + vf_mpi_clear(dmpi, vf->priv->exp_x + w, vf->priv->exp_y, vf->priv->exp_w - (vf->priv->exp_x + w), h); } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - if(mpi->flags&MP_IMGFLAG_DIRECT){ - vf->dmpi=mpi->priv; - if(!vf->dmpi) { mp_tmsg(MSGT_VFILTER, MSGL_WARN, "Why do we get NULL??\n"); return 0; } - mpi->priv=NULL; - clear_borders(vf,mpi->w,mpi->h); - // we've used DR, so we're ready... - if(!(mpi->flags&MP_IMGFLAG_PLANAR)) - vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette - return vf_next_put_image(vf,vf->dmpi, pts); - } +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + if (vf->priv->exp_x == 0 && vf->priv->exp_y == 0 && + vf->priv->exp_w == mpi->w && vf->priv->exp_h == mpi->h) + return mpi; - // hope we'll get DR buffer: - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - vf->priv->exp_w, vf->priv->exp_h); + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); // copy mpi->dmpi... if(mpi->flags&MP_IMGFLAG_PLANAR){ - memcpy_pic(vf->dmpi->planes[0]+ - vf->priv->exp_y*vf->dmpi->stride[0]+vf->priv->exp_x, + memcpy_pic(dmpi->planes[0]+ + vf->priv->exp_y*dmpi->stride[0]+vf->priv->exp_x, mpi->planes[0], mpi->w, mpi->h, - vf->dmpi->stride[0],mpi->stride[0]); - memcpy_pic(vf->dmpi->planes[1]+ - (vf->priv->exp_y>>mpi->chroma_y_shift)*vf->dmpi->stride[1]+(vf->priv->exp_x>>mpi->chroma_x_shift), + dmpi->stride[0],mpi->stride[0]); + memcpy_pic(dmpi->planes[1]+ + (vf->priv->exp_y>>mpi->chroma_y_shift)*dmpi->stride[1]+(vf->priv->exp_x>>mpi->chroma_x_shift), mpi->planes[1], (mpi->w>>mpi->chroma_x_shift), (mpi->h>>mpi->chroma_y_shift), - vf->dmpi->stride[1],mpi->stride[1]); - memcpy_pic(vf->dmpi->planes[2]+ - (vf->priv->exp_y>>mpi->chroma_y_shift)*vf->dmpi->stride[2]+(vf->priv->exp_x>>mpi->chroma_x_shift), + dmpi->stride[1],mpi->stride[1]); + memcpy_pic(dmpi->planes[2]+ + (vf->priv->exp_y>>mpi->chroma_y_shift)*dmpi->stride[2]+(vf->priv->exp_x>>mpi->chroma_x_shift), mpi->planes[2], (mpi->w>>mpi->chroma_x_shift), (mpi->h>>mpi->chroma_y_shift), - vf->dmpi->stride[2],mpi->stride[2]); + dmpi->stride[2],mpi->stride[2]); } else { - memcpy_pic(vf->dmpi->planes[0]+ - vf->priv->exp_y*vf->dmpi->stride[0]+vf->priv->exp_x*(vf->dmpi->bpp/8), - mpi->planes[0], mpi->w*(vf->dmpi->bpp/8), mpi->h, - vf->dmpi->stride[0],mpi->stride[0]); - vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette + memcpy_pic(dmpi->planes[0]+ + vf->priv->exp_y*dmpi->stride[0]+vf->priv->exp_x*(dmpi->bpp/8), + mpi->planes[0], mpi->w*(dmpi->bpp/8), mpi->h, + dmpi->stride[0],mpi->stride[0]); } - clear_borders(vf,mpi->w,mpi->h); - return vf_next_put_image(vf,vf->dmpi, pts); + clear_borders(vf, dmpi, mpi->w, mpi->h); + talloc_free(mpi); + return dmpi; } //===========================================================================// @@ -231,8 +188,7 @@ static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; vf->control=control; vf->query_format=query_format; - vf->get_image=get_image; - vf->put_image=put_image; + vf->filter=filter; mp_msg(MSGT_VFILTER, MSGL_INFO, "Expand: %d x %d, %d ; %d, aspect: %f, round: %d\n", vf->priv->cfg_exp_w, vf->priv->cfg_exp_h, diff --git a/video/filter/vf_flip.c b/video/filter/vf_flip.c index d5792f27ca..49d6993023 100644 --- a/video/filter/vf_flip.c +++ b/video/filter/vf_flip.c @@ -37,64 +37,27 @@ static int config(struct vf_instance *vf, return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); } -static void get_image(struct vf_instance *vf, mp_image_t *mpi){ - if(mpi->flags&MP_IMGFLAG_ACCEPT_STRIDE){ - // try full DR ! - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - mpi->type, mpi->flags, mpi->width, mpi->height); - // set up mpi as a upside-down image of dmpi: - mpi->planes[0]=vf->dmpi->planes[0]+ - vf->dmpi->stride[0]*(vf->dmpi->height-1); - mpi->stride[0]=-vf->dmpi->stride[0]; - if(mpi->flags&MP_IMGFLAG_PLANAR){ - mpi->planes[1]=vf->dmpi->planes[1]+ - vf->dmpi->stride[1]*((vf->dmpi->height>>mpi->chroma_y_shift)-1); - mpi->stride[1]=-vf->dmpi->stride[1]; - mpi->planes[2]=vf->dmpi->planes[2]+ - vf->dmpi->stride[2]*((vf->dmpi->height>>mpi->chroma_y_shift)-1); - mpi->stride[2]=-vf->dmpi->stride[2]; - } - mpi->flags|=MP_IMGFLAG_DIRECT; - mpi->priv=(void*)vf->dmpi; - } -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - if(mpi->flags&MP_IMGFLAG_DIRECT){ - // we've used DR, so we're ready... - if(!(mpi->flags&MP_IMGFLAG_PLANAR)) - ((mp_image_t*)mpi->priv)->planes[1] = mpi->planes[1]; // passthrough rgb8 palette - return vf_next_put_image(vf,(mp_image_t*)mpi->priv, pts); - } - - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->width, mpi->height); - - // set up mpi as a upside-down image of dmpi: - vf->dmpi->planes[0]=mpi->planes[0]+ +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + mpi->planes[0]=mpi->planes[0]+ mpi->stride[0]*(mpi->height-1); - vf->dmpi->stride[0]=-mpi->stride[0]; - if(vf->dmpi->flags&MP_IMGFLAG_PLANAR){ - vf->dmpi->planes[1]=mpi->planes[1]+ + mpi->stride[0]=-mpi->stride[0]; + if(mpi->flags&MP_IMGFLAG_PLANAR){ + mpi->planes[1]=mpi->planes[1]+ mpi->stride[1]*((mpi->height>>mpi->chroma_y_shift)-1); - vf->dmpi->stride[1]=-mpi->stride[1]; - vf->dmpi->planes[2]=mpi->planes[2]+ + mpi->stride[1]=-mpi->stride[1]; + mpi->planes[2]=mpi->planes[2]+ mpi->stride[2]*((mpi->height>>mpi->chroma_y_shift)-1); - vf->dmpi->stride[2]=-mpi->stride[2]; - } else - vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!! - - return vf_next_put_image(vf,vf->dmpi, pts); + mpi->stride[2]=-mpi->stride[2]; + } + return mpi; } //===========================================================================// static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->get_image=get_image; - vf->put_image=put_image; - vf->default_reqs=VFCAP_ACCEPT_STRIDE; + vf->filter=filter; return 1; } diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 7e0ab634c4..8abbd9b054 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -58,7 +58,6 @@ static int config(struct vf_instance *vf, int width, int height, static int vf_open(vf_instance_t *vf, char *args){ vf->query_format=query_format; - vf->default_caps=0; if (vf->priv->outfmt) vf->config=config; return 1; diff --git a/video/filter/vf_gradfun.c b/video/filter/vf_gradfun.c index b7f59f7d5c..b9d07bc907 100644 --- a/video/filter/vf_gradfun.c +++ b/video/filter/vf_gradfun.c @@ -245,8 +245,8 @@ static void blur_line_sse2(uint16_t *dc, uint16_t *buf, uint16_t *buf1, } #endif // HAVE_6REGS && HAVE_SSE2 -static void filter(struct vf_priv_s *ctx, uint8_t *dst, uint8_t *src, - int width, int height, int dstride, int sstride, int r) +static void filter_plane(struct vf_priv_s *ctx, uint8_t *dst, uint8_t *src, + int width, int height, int dstride, int sstride, int r) { int bstride = ((width+15)&~15)/2; int y; @@ -287,38 +287,15 @@ static void filter(struct vf_priv_s *ctx, uint8_t *dst, uint8_t *src, } } -static void get_image(struct vf_instance *vf, mp_image_t *mpi) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - if (mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change - // ok, we can do pp in-place: - vf->dmpi = vf_get_image(vf->next, mpi->imgfmt, - mpi->type, mpi->flags, mpi->width, mpi->height); - mpi->planes[0] = vf->dmpi->planes[0]; - mpi->stride[0] = vf->dmpi->stride[0]; - mpi->width = vf->dmpi->width; - if (mpi->flags&MP_IMGFLAG_PLANAR){ - mpi->planes[1] = vf->dmpi->planes[1]; - mpi->planes[2] = vf->dmpi->planes[2]; - mpi->stride[1] = vf->dmpi->stride[1]; - mpi->stride[2] = vf->dmpi->stride[2]; + struct mp_image *dmpi = mpi; + if (!mp_image_is_writeable(mpi)) { + dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); } - mpi->flags |= MP_IMGFLAG_DIRECT; -} -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) -{ - mp_image_t *dmpi = vf->dmpi; - int p; - - if (!(mpi->flags&MP_IMGFLAG_DIRECT)) { - // no DR, so get a new image. hope we'll get DR buffer: - dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP, - MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE, - mpi->w, mpi->h); - } - vf_clone_mpi_attributes(dmpi, mpi); - - for (p=0; pnum_planes; p++) { + for (int p=0; p < mpi->num_planes; p++) { int w = mpi->w; int h = mpi->h; int r = vf->priv->radius; @@ -329,14 +306,16 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) r = av_clip((r+1)&~1,4,32); } if (FFMIN(w,h) > 2*r) - filter(vf->priv, dmpi->planes[p], mpi->planes[p], w, h, - dmpi->stride[p], mpi->stride[p], r); + filter_plane(vf->priv, dmpi->planes[p], mpi->planes[p], w, h, + dmpi->stride[p], mpi->stride[p], r); else if (dmpi->planes[p] != mpi->planes[p]) memcpy_pic(dmpi->planes[p], mpi->planes[p], w, h, dmpi->stride[p], mpi->stride[p]); } - return vf_next_put_image(vf, dmpi, pts); + if (dmpi != mpi) + talloc_free(mpi); + return dmpi; } static int query_format(struct vf_instance *vf, unsigned int fmt) @@ -386,8 +365,7 @@ static void uninit(struct vf_instance *vf) static int vf_open(vf_instance_t *vf, char *args) { - vf->get_image=get_image; - vf->put_image=put_image; + vf->filter=filter; vf->query_format=query_format; vf->config=config; vf->uninit=uninit; diff --git a/video/filter/vf_hqdn3d.c b/video/filter/vf_hqdn3d.c index ff01a6d422..1ec0cc5c66 100644 --- a/video/filter/vf_hqdn3d.c +++ b/video/filter/vf_hqdn3d.c @@ -208,16 +208,14 @@ static void deNoise(unsigned char *Frame, // mpi->planes[x] } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ int cw= mpi->w >> mpi->chroma_x_shift; int ch= mpi->h >> mpi->chroma_y_shift; int W = mpi->w, H = mpi->h; - mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->w,mpi->h); - - if(!dmpi) return 0; + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); deNoise(mpi->planes[0], dmpi->planes[0], vf->priv->Line, &vf->priv->Frame[0], W, H, @@ -238,7 +236,8 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ vf->priv->Coefs[2], vf->priv->Coefs[3]); - return vf_next_put_image(vf,dmpi, pts); + talloc_free(mpi); + return dmpi; } //===========================================================================// @@ -284,7 +283,7 @@ static int vf_open(vf_instance_t *vf, char *args){ double Param1, Param2, Param3, Param4; vf->config=config; - vf->put_image=put_image; + vf->filter=filter; vf->query_format=query_format; vf->uninit=uninit; vf->priv=malloc(sizeof(struct vf_priv_s)); diff --git a/video/filter/vf_ilpack.c b/video/filter/vf_ilpack.c index 6519a0c512..73f816cb9e 100644 --- a/video/filter/vf_ilpack.c +++ b/video/filter/vf_ilpack.c @@ -372,18 +372,16 @@ static void ilpack(unsigned char *dst, unsigned char *src[3], } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - mp_image_t *dmpi; + mp_image_t *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); - // hope we'll get DR buffer: - dmpi=vf_get_image(vf->next, IMGFMT_YUY2, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->w, mpi->h); ilpack(dmpi->planes[0], mpi->planes, dmpi->stride[0], mpi->stride, mpi->w, mpi->h, vf->priv->pack); - return vf_next_put_image(vf,dmpi, pts); + talloc_free(mpi); + return dmpi; } static int config(struct vf_instance *vf, @@ -411,7 +409,7 @@ static int vf_open(vf_instance_t *vf, char *args) { vf->config=config; vf->query_format=query_format; - vf->put_image=put_image; + vf->filter=filter; vf->priv = calloc(1, sizeof(struct vf_priv_s)); vf->priv->mode = 1; if (args) sscanf(args, "%d", &vf->priv->mode); diff --git a/video/filter/vf_mirror.c b/video/filter/vf_mirror.c index e201edecd1..10ac5f308f 100644 --- a/video/filter/vf_mirror.c +++ b/video/filter/vf_mirror.c @@ -83,13 +83,10 @@ static void mirror(unsigned char* dst,unsigned char* src,int dststride,int srcst //===========================================================================// -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi; - - // hope we'll get DR buffer: - dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->w, mpi->h); +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + mp_image_t *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); if(mpi->flags&MP_IMGFLAG_PLANAR){ mirror(dmpi->planes[0],mpi->planes[0], @@ -108,14 +105,15 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ dmpi->planes[1]=mpi->planes[1]; // passthrough rgb8 palette } - return vf_next_put_image(vf,dmpi, pts); + talloc_free(mpi); + return dmpi; } //===========================================================================// static int vf_open(vf_instance_t *vf, char *args){ //vf->config=config; - vf->put_image=put_image; + vf->filter=filter; return 1; } diff --git a/video/filter/vf_noformat.c b/video/filter/vf_noformat.c index 032d11fd57..6964a2955c 100644 --- a/video/filter/vf_noformat.c +++ b/video/filter/vf_noformat.c @@ -47,7 +47,6 @@ static int query_format(struct vf_instance *vf, unsigned int fmt){ static int vf_open(vf_instance_t *vf, char *args){ vf->query_format=query_format; - vf->default_caps=0; return 1; } diff --git a/video/filter/vf_noise.c b/video/filter/vf_noise.c index 19a41111ed..44f96765b4 100644 --- a/video/filter/vf_noise.c +++ b/video/filter/vf_noise.c @@ -316,43 +316,18 @@ static int config(struct vf_instance *vf, return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); } -static void get_image(struct vf_instance *vf, mp_image_t *mpi){ - if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change - if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ - // ok, we can do pp in-place (or pp disabled): - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - mpi->type, mpi->flags, mpi->w, mpi->h); - mpi->planes[0]=vf->dmpi->planes[0]; - mpi->stride[0]=vf->dmpi->stride[0]; - mpi->width=vf->dmpi->width; - if(mpi->flags&MP_IMGFLAG_PLANAR){ - mpi->planes[1]=vf->dmpi->planes[1]; - mpi->planes[2]=vf->dmpi->planes[2]; - mpi->stride[1]=vf->dmpi->stride[1]; - mpi->stride[2]=vf->dmpi->stride[2]; - } - mpi->flags|=MP_IMGFLAG_DIRECT; -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi; - - if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ - // no DR, so get a new image! hope we'll get DR buffer: - vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->w,mpi->h); -//printf("nodr\n"); - } -//else printf("dr\n"); - dmpi= vf->dmpi; +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + struct mp_image *dmpi = mpi; + if (!mp_image_is_writeable(mpi)) { + dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); + } noise(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam); noise(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam); noise(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam); - vf_clone_mpi_attributes(dmpi, mpi); - #if HAVE_MMX if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t"); #endif @@ -360,7 +335,9 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t"); #endif - return vf_next_put_image(vf,dmpi, pts); + if (dmpi != mpi) + talloc_free(mpi); + return dmpi; } static void uninit(struct vf_instance *vf){ @@ -422,8 +399,7 @@ static const unsigned int fmt_list[]={ static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->put_image=put_image; - vf->get_image=get_image; + vf->filter=filter; vf->query_format=query_format; vf->uninit=uninit; vf->priv=malloc(sizeof(struct vf_priv_s)); diff --git a/video/filter/vf_phase.c b/video/filter/vf_phase.c index 74e8a1ce47..021143feb2 100644 --- a/video/filter/vf_phase.c +++ b/video/filter/vf_phase.c @@ -196,16 +196,13 @@ static enum mode analyze_plane(unsigned char *old, unsigned char *new, return mode; } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - mp_image_t *dmpi; int w; enum mode mode; - if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->w, mpi->h))) - return 0; + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); w=dmpi->w; if(!(dmpi->flags&MP_IMGFLAG_PLANAR)) @@ -237,7 +234,8 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) &vf->priv->buf[2], mode); } - return vf_next_put_image(vf, dmpi, pts); + talloc_free(mpi); + return dmpi; } static void uninit(struct vf_instance *vf) @@ -252,9 +250,8 @@ static void uninit(struct vf_instance *vf) static int vf_open(vf_instance_t *vf, char *args) { - vf->put_image = put_image; + vf->filter = filter; vf->uninit = uninit; - vf->default_reqs = VFCAP_ACCEPT_STRIDE; if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s)))) { diff --git a/video/filter/vf_pp.c b/video/filter/vf_pp.c index 7ff079d1da..82bc0181e0 100644 --- a/video/filter/vf_pp.c +++ b/video/filter/vf_pp.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "config.h" #include "core/mp_msg.h" @@ -93,43 +94,26 @@ static int control(struct vf_instance *vf, int request, void* data){ return vf_next_control(vf,request,data); } -static void get_image(struct vf_instance *vf, mp_image_t *mpi){ - if(vf->priv->pp&0xFFFF) return; // non-local filters enabled - if((mpi->type==MP_IMGTYPE_IPB || vf->priv->pp) && - mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change - if(!(mpi->flags&MP_IMGFLAG_ACCEPT_STRIDE) && mpi->imgfmt!=vf->priv->outfmt) - return; // colorspace differ - // ok, we can do pp in-place (or pp disabled): - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height); - mpi->planes[0]=vf->dmpi->planes[0]; - mpi->stride[0]=vf->dmpi->stride[0]; - mpi->width=vf->dmpi->width; - if(mpi->flags&MP_IMGFLAG_PLANAR){ - mpi->planes[1]=vf->dmpi->planes[1]; - mpi->planes[2]=vf->dmpi->planes[2]; - mpi->stride[1]=vf->dmpi->stride[1]; - mpi->stride[2]=vf->dmpi->stride[2]; - } - mpi->flags|=MP_IMGFLAG_DIRECT; -} +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + // pass-through if pp disabled + if (!vf->priv->pp) + return mpi; -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ - // no DR, so get a new image! hope we'll get DR buffer: - vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | - MP_IMGFLAG_PREFER_ALIGNED_STRIDE | MP_IMGFLAG_READABLE, -// MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, -// mpi->w,mpi->h); - (mpi->width+7)&(~7),(mpi->height+7)&(~7)); - vf->dmpi->w=mpi->w; vf->dmpi->h=mpi->h; // display w;h + bool non_local = vf->priv->pp & 0xFFFF; + + struct mp_image *dmpi = mpi; + if (!mp_image_is_writeable(mpi) || non_local) { + dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); } - if(vf->priv->pp || !(mpi->flags&MP_IMGFLAG_DIRECT)){ + // apparently this is required + assert(mpi->stride[0] >= ((mpi->w+7)&(~7))); + // do the postprocessing! (or copy if no DR) pp_postprocess((const uint8_t **)mpi->planes, mpi->stride, - vf->dmpi->planes,vf->dmpi->stride, + dmpi->planes,dmpi->stride, (mpi->w+7)&(~7),mpi->h, mpi->qscale, mpi->qstride, vf->priv->ppMode[ vf->priv->pp ], vf->priv->context, @@ -138,8 +122,10 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ #else mpi->pict_type); #endif - } - return vf_next_put_image(vf,vf->dmpi, pts); + + if (dmpi != mpi) + talloc_free(mpi); + return dmpi; } //===========================================================================// @@ -162,8 +148,7 @@ static int vf_open(vf_instance_t *vf, char *args){ vf->query_format=query_format; vf->control=control; vf->config=config; - vf->get_image=get_image; - vf->put_image=put_image; + vf->filter=filter; vf->uninit=uninit; vf->default_caps=VFCAP_ACCEPT_STRIDE|VFCAP_POSTPROC; vf->priv=malloc(sizeof(struct vf_priv_s)); diff --git a/video/filter/vf_pullup.c b/video/filter/vf_pullup.c index acac407429..84bc64b1cf 100644 --- a/video/filter/vf_pullup.c +++ b/video/filter/vf_pullup.c @@ -75,55 +75,25 @@ static void init_pullup(struct vf_instance *vf, mp_image_t *mpi) vf->priv->qbuf = malloc(c->w[3]); } - -#if 0 -static void get_image(struct vf_instance *vf, mp_image_t *mpi) -{ - struct pullup_context *c = vf->priv->ctx; - struct pullup_buffer *b; - - if (mpi->type == MP_IMGTYPE_STATIC) return; - - if (!vf->priv->init) init_pullup(vf, mpi); - - b = pullup_get_buffer(c, 2); - if (!b) return; /* shouldn't happen... */ - - mpi->priv = b; - - mpi->planes[0] = b->planes[0]; - mpi->planes[1] = b->planes[1]; - mpi->planes[2] = b->planes[2]; - mpi->stride[0] = c->stride[0]; - mpi->stride[1] = c->stride[1]; - mpi->stride[2] = c->stride[2]; - - mpi->flags |= MP_IMGFLAG_DIRECT; -} -#endif - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { struct pullup_context *c = vf->priv->ctx; struct pullup_buffer *b; struct pullup_frame *f; - mp_image_t *dmpi; - int ret; int p; int i; + double pts = mpi->pts; + struct mp_image *dmpi = NULL; if (!vf->priv->init) init_pullup(vf, mpi); - if (mpi->flags & MP_IMGFLAG_DIRECT) { - b = mpi->priv; - mpi->priv = 0; - } else { + if (1) { b = pullup_get_buffer(c, 2); if (!b) { mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n"); f = pullup_get_frame(c); pullup_release_frame(f); - return 0; + goto skip; } memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h, c->stride[0], mpi->stride[0]); @@ -174,21 +144,23 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) /* Fake yes for first few frames (buffer depth) to keep from * breaking A/V sync with G1's bad architecture... */ - if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0; + //if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0; + if (!f) + goto skip; if (f->length < 2) { pullup_release_frame(f); f = pullup_get_frame(c); - if (!f) return 0; + if (!f) goto skip; if (f->length < 2) { pullup_release_frame(f); if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST)) - return 0; + goto skip; f = pullup_get_frame(c); - if (!f) return 0; + if (!f) goto skip; if (f->length < 2) { pullup_release_frame(f); - return 0; + goto skip; } } } @@ -210,66 +182,42 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) } #endif - /* If the frame isn't already exportable... */ - while (!f->buffer) { - dmpi = vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->width, mpi->height); - /* FIXME: Is it ok to discard dmpi if it's not direct? */ - if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) { - pullup_pack_frame(c, f); - break; - } - /* Direct render fields into output buffer */ - my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0], - mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2); - my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0], - f->ofields[1]->planes[0] + c->stride[0], - mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2); - if (mpi->flags & MP_IMGFLAG_PLANAR) { - my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1], - mpi->chroma_width, mpi->chroma_height/2, - dmpi->stride[1]*2, c->stride[1]*2); - my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1], - f->ofields[1]->planes[1] + c->stride[1], - mpi->chroma_width, mpi->chroma_height/2, - dmpi->stride[1]*2, c->stride[1]*2); - my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2], - mpi->chroma_width, mpi->chroma_height/2, - dmpi->stride[2]*2, c->stride[2]*2); - my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2], - f->ofields[1]->planes[2] + c->stride[2], - mpi->chroma_width, mpi->chroma_height/2, - dmpi->stride[2]*2, c->stride[2]*2); - } - pullup_release_frame(f); - if (mpi->qscale) { - dmpi->qscale = vf->priv->qbuf; - dmpi->qstride = mpi->qstride; - dmpi->qscale_type = mpi->qscale_type; - } - return vf_next_put_image(vf, dmpi, f->pts); - } - dmpi = vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->width, mpi->height); + /* If the frame isn't already exportable... */ + if (!f->buffer) + pullup_pack_frame(c, f); - dmpi->planes[0] = f->buffer->planes[0]; - dmpi->planes[1] = f->buffer->planes[1]; - dmpi->planes[2] = f->buffer->planes[2]; + // NOTE: the copy could probably be avoided by changing or using the + // pullup internal buffer management. But right now just do the + // safe thing and always copy. Code outside the filter might + // hold a buffer reference even if the filter chain is destroyed. + dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); - dmpi->stride[0] = c->stride[0]; - dmpi->stride[1] = c->stride[1]; - dmpi->stride[2] = c->stride[2]; + struct mp_image data = *dmpi; + data.planes[0] = f->buffer->planes[0]; + data.planes[1] = f->buffer->planes[1]; + data.planes[2] = f->buffer->planes[2]; + + data.stride[0] = c->stride[0]; + data.stride[1] = c->stride[1]; + data.stride[2] = c->stride[2]; + + mp_image_copy(dmpi, &data); + + dmpi->pts = f->pts; + + // Warning: entirely bogus memory management of qscale if (mpi->qscale) { dmpi->qscale = vf->priv->qbuf; dmpi->qstride = mpi->qstride; dmpi->qscale_type = mpi->qscale_type; } - ret = vf_next_put_image(vf, dmpi, f->pts); pullup_release_frame(f); - return ret; + +skip: + talloc_free(mpi); + return dmpi; } static int query_format(struct vf_instance *vf, unsigned int fmt) @@ -302,12 +250,10 @@ static int vf_open(vf_instance_t *vf, char *args) { struct vf_priv_s *p; struct pullup_context *c; - //vf->get_image = get_image; - vf->put_image = put_image; + vf->filter = filter; vf->config = config; vf->query_format = query_format; vf->uninit = uninit; - vf->default_reqs = VFCAP_ACCEPT_STRIDE; vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); p->ctx = c = pullup_alloc_context(); p->fakecount = 1; diff --git a/video/filter/vf_rotate.c b/video/filter/vf_rotate.c index 8994cf4588..1ef6bf2300 100644 --- a/video/filter/vf_rotate.c +++ b/video/filter/vf_rotate.c @@ -74,22 +74,16 @@ static int config(struct vf_instance *vf, if (vf->priv->direction & 4) { if (widthpriv->direction&=3; } - if (vf->priv->direction & 4){ - vf->put_image=vf_next_put_image; // passthru mode! -/* FIXME: this should be in an other procedure in vf.c; that should always check - whether the filter after the passthrough one still (not)supports slices */ - return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); - } return vf_next_config(vf,height,width,d_height,d_width,flags,outfmt); } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi; +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + if (vf->priv->direction & 4) + return mpi; - // hope we'll get DR buffer: - dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, - mpi->h, mpi->w); + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); if(mpi->flags&MP_IMGFLAG_PLANAR){ rotate(dmpi->planes[0],mpi->planes[0], @@ -108,7 +102,8 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette } - return vf_next_put_image(vf,dmpi, pts); + talloc_free(mpi); + return dmpi; } //===========================================================================// @@ -132,7 +127,7 @@ static int query_format(struct vf_instance *vf, unsigned int fmt){ static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->put_image=put_image; + vf->filter=filter; vf->query_format=query_format; vf->priv=malloc(sizeof(struct vf_priv_s)); vf->priv->direction=args?atoi(args):0; diff --git a/video/filter/vf_scale.c b/video/filter/vf_scale.c index 5749aa0baf..30a185390e 100644 --- a/video/filter/vf_scale.c +++ b/video/filter/vf_scale.c @@ -408,31 +408,15 @@ static void scale(struct SwsContext *sws1, struct SwsContext *sws2, uint8_t *src } } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi=mpi->priv; +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); -// printf("vf_scale::put_image(): processing whole frame! dmpi=%p flag=%d\n", -// dmpi, (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)); + scale(vf->priv->ctx, vf->priv->ctx, mpi->planes,mpi->stride,0,mpi->h,dmpi->planes,dmpi->stride, vf->priv->interlaced); - if(!dmpi){ - - // hope we'll get DR buffer: - dmpi=vf_get_image(vf->next,vf->priv->fmt, - MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE, - vf->priv->w, vf->priv->h); - - scale(vf->priv->ctx, vf->priv->ctx, mpi->planes,mpi->stride,0,mpi->h,dmpi->planes,dmpi->stride, vf->priv->interlaced); - } - - if(vf->priv->w==mpi->w && vf->priv->h==mpi->h){ - // just conversion, no scaling -> keep postprocessing data - // this way we can apply pp filter to non-yv12 source using scaler - vf_clone_mpi_attributes(dmpi, mpi); - } - - if(vf->priv->palette) dmpi->planes[1]=vf->priv->palette; // export palette! - - return vf_next_put_image(vf,dmpi, pts); + talloc_free(mpi); + return dmpi; } static int control(struct vf_instance *vf, int request, void* data){ @@ -588,7 +572,7 @@ static void uninit(struct vf_instance *vf){ static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->put_image=put_image; + vf->filter=filter; vf->query_format=query_format; vf->control= control; vf->uninit=uninit; diff --git a/video/filter/vf_screenshot.c b/video/filter/vf_screenshot.c index d94bb3c5cf..d02581a461 100644 --- a/video/filter/vf_screenshot.c +++ b/video/filter/vf_screenshot.c @@ -34,7 +34,7 @@ #include struct vf_priv_s { - mp_image_t *image; + int display_w, display_h; void (*image_callback)(void *, mp_image_t *); void *image_callback_ctx; int shot; @@ -46,58 +46,24 @@ static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) { - free_mp_image(vf->priv->image); - vf->priv->image = new_mp_image(width, height); - mp_image_setfmt(vf->priv->image, outfmt); - vf->priv->image->display_w = d_width; - vf->priv->image->display_h = d_height; + vf->priv->display_w = d_width; + vf->priv->display_h = d_height; return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); } -static void get_image(struct vf_instance *vf, mp_image_t *mpi) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - vf->dmpi= vf_get_image(vf->next, mpi->imgfmt, - mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height); - - for (int i = 0; i < MP_MAX_PLANES; i++) { - mpi->planes[i]=vf->dmpi->planes[i]; - mpi->stride[i]=vf->dmpi->stride[i]; - } - mpi->width=vf->dmpi->width; - - mpi->flags|=MP_IMGFLAG_DIRECT; - - mpi->priv=(void*)vf->dmpi; -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) -{ - mp_image_t *dmpi = (mp_image_t *)mpi->priv; - - if(!(mpi->flags&(MP_IMGFLAG_DIRECT))){ - dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_EXPORT, 0, - mpi->width, mpi->height); - vf_clone_mpi_attributes(dmpi, mpi); - for (int i = 0; i < MP_MAX_PLANES; i++) { - dmpi->planes[i]=mpi->planes[i]; - dmpi->stride[i]=mpi->stride[i]; - } - dmpi->width=mpi->width; - dmpi->height=mpi->height; - } - if(vf->priv->shot) { vf->priv->shot=0; - mp_image_t image = *dmpi; + mp_image_t image = *mpi; image.flags &= ~MP_IMGFLAG_ALLOCATED; mp_image_copy_attributes(&image, mpi); - mp_image_set_display_size(&image, vf->priv->image->display_w, - vf->priv->image->display_h); + mp_image_set_display_size(&image, vf->priv->display_w, + vf->priv->display_h); vf->priv->image_callback(vf->priv->image_callback_ctx, &image); } - return vf_next_put_image(vf, dmpi, pts); + return mpi; } static int control (vf_instance_t *vf, int request, void *data) @@ -126,7 +92,6 @@ static int query_format(struct vf_instance *vf, unsigned int fmt) static void uninit(vf_instance_t *vf) { - free_mp_image(vf->priv->image); free(vf->priv); } @@ -134,13 +99,11 @@ static int vf_open(vf_instance_t *vf, char *args) { vf->config=config; vf->control=control; - vf->put_image=put_image; + vf->filter=filter; vf->query_format=query_format; - vf->get_image=get_image; vf->uninit=uninit; vf->priv=malloc(sizeof(struct vf_priv_s)); vf->priv->shot=0; - vf->priv->image=NULL; return 1; } diff --git a/video/filter/vf_softpulldown.c b/video/filter/vf_softpulldown.c index a679ef9b44..ce7cddb29a 100644 --- a/video/filter/vf_softpulldown.c +++ b/video/filter/vf_softpulldown.c @@ -35,30 +35,25 @@ struct vf_priv_s { long long out; struct vf_detc_pts_buf ptsbuf; int last_frame_duration; - double buffered_pts; - mp_image_t *buffered_mpi; - int buffered_last_frame_duration; + struct mp_image *buffer; }; -static int continue_buffered_image(struct vf_instance *vf) +static int filter(struct vf_instance *vf, struct mp_image *mpi) { - double pts = vf->priv->buffered_pts; - mp_image_t *mpi = vf->priv->buffered_mpi; - vf->priv->out++; - vf->priv->state=0; - return vf_next_put_image(vf, mpi, vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, pts, 0, 0, vf->priv->buffered_last_frame_duration)); -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) -{ - mp_image_t *dmpi; - int ret = 0; int flags = mpi->fields; int state = vf->priv->state; + struct vf_priv_s *p = vf->priv; - dmpi = vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | - MP_IMGFLAG_PRESERVE, mpi->width, mpi->height); + if (!p->buffer || p->buffer->w != mpi->w || p->buffer->h != mpi->h || + p->buffer->imgfmt != mpi->imgfmt) + { + mp_image_unrefp(&p->buffer); + p->buffer = mp_image_alloc(mpi->imgfmt, mpi->w, mpi->h); + talloc_steal(vf, p->buffer); + } + mp_image_copy_attributes(p->buffer, mpi); + + struct mp_image *dmpi = p->buffer; vf->priv->in++; @@ -75,7 +70,9 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) } if (state == 0) { - ret = vf_next_put_image(vf, mpi, vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, pts, 0, 0, vf->priv->last_frame_duration)); + struct mp_image *new = mp_image_new_ref(mpi); + new->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, vf->priv->last_frame_duration); + vf_add_output_frame(vf, new); vf->priv->out++; if (flags & MP_IMGFIELD_REPEAT_FIRST) { my_memcpy_pic(dmpi->planes[0], @@ -111,13 +108,16 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, mpi->stride[2]*2); } - ret = vf_next_put_image(vf, dmpi, vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, pts, 0, 0, vf->priv->last_frame_duration)); + struct mp_image *new = mp_image_new_ref(mpi); + new->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, vf->priv->last_frame_duration); + vf_add_output_frame(vf, new); vf->priv->out++; if (flags & MP_IMGFIELD_REPEAT_FIRST) { - vf->priv->buffered_mpi = mpi; - vf->priv->buffered_pts = pts; - vf->priv->buffered_last_frame_duration = vf->priv->last_frame_duration; - vf_queue_frame(vf, continue_buffered_image); + struct mp_image *new = mp_image_new_ref(mpi); + new->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, 3); + vf_add_output_frame(vf, new); + vf->priv->out++; + vf->priv->state=0; } else { my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2, @@ -145,7 +145,9 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) else vf->priv->last_frame_duration = 2; - return ret; + talloc_free(mpi); + + return 0; } static int config(struct vf_instance *vf, @@ -164,9 +166,8 @@ static void uninit(struct vf_instance *vf) static int vf_open(vf_instance_t *vf, char *args) { vf->config = config; - vf->put_image = put_image; + vf->filter_ext = filter; vf->uninit = uninit; - vf->default_reqs = VFCAP_ACCEPT_STRIDE; vf->priv = calloc(1, sizeof(struct vf_priv_s)); vf->priv->last_frame_duration = 2; vf_detc_init_pts_buf(&vf->priv->ptsbuf); diff --git a/video/filter/vf_stereo3d.c b/video/filter/vf_stereo3d.c index f1b1a82409..3e055b22ea 100644 --- a/video/filter/vf_stereo3d.c +++ b/video/filter/vf_stereo3d.c @@ -279,11 +279,10 @@ static int config(struct vf_instance *vf, int width, int height, int d_width, d_width, d_height, flags, outfmt); } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - mp_image_t *dmpi; if (vf->priv->in.fmt == vf->priv->out.fmt) { //nothing to do - dmpi = mpi; + return mpi; } else { int out_off_left, out_off_right; int in_off_left = vf->priv->in.row_left * mpi->stride[0] + @@ -291,9 +290,9 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) int in_off_right = vf->priv->in.row_right * mpi->stride[0] + vf->priv->in.off_right; - dmpi = vf_get_image(vf->next, IMGFMT_RGB24, MP_IMGTYPE_TEMP, - MP_IMGFLAG_ACCEPT_STRIDE, - vf->priv->out.width, vf->priv->out.height); + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); + out_off_left = vf->priv->out.row_left * dmpi->stride[0] + vf->priv->out.off_left; out_off_right = vf->priv->out.row_right * dmpi->stride[0] + @@ -374,11 +373,13 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) default: mp_msg(MSGT_VFILTER, MSGL_WARN, "[stereo3d] stereo format of output is not supported\n"); - return 0; + return NULL; break; } + + talloc_free(mpi); + return dmpi; } - return vf_next_put_image(vf, dmpi, pts); } static int query_format(struct vf_instance *vf, unsigned int fmt) @@ -398,7 +399,7 @@ static int vf_open(vf_instance_t *vf, char *args) { vf->config = config; vf->uninit = uninit; - vf->put_image = put_image; + vf->filter = filter; vf->query_format = query_format; return 1; diff --git a/video/filter/vf_sub.c b/video/filter/vf_sub.c index 3307af0c90..10fcdbfc5b 100644 --- a/video/filter/vf_sub.c +++ b/video/filter/vf_sub.c @@ -89,37 +89,6 @@ static int config(struct vf_instance *vf, d_height, flags, outfmt); } -static void get_image(struct vf_instance *vf, mp_image_t *mpi) -{ - if (mpi->type == MP_IMGTYPE_IPB) - return; - if (mpi->flags & MP_IMGFLAG_PRESERVE) - return; - if (mpi->imgfmt != vf->priv->outfmt) - return; // colorspace differ - - // width never changes, always try full DR - mpi->priv = vf->dmpi = vf_get_image(vf->next, mpi->imgfmt, mpi->type, - mpi->flags | MP_IMGFLAG_READABLE, - FFMAX(mpi->width, vf->priv->outw), - FFMAX(mpi->height, vf->priv->outh)); - - int tmargin = vf->priv->opt_top_margin; - // set up mpi as a cropped-down image of dmpi: - if (mpi->flags & MP_IMGFLAG_PLANAR) { - mpi->planes[0] = vf->dmpi->planes[0] + tmargin * vf->dmpi->stride[0]; - mpi->planes[1] = vf->dmpi->planes[1] + (tmargin >> mpi->chroma_y_shift) * vf->dmpi->stride[1]; - mpi->planes[2] = vf->dmpi->planes[2] + (tmargin >> mpi->chroma_y_shift) * vf->dmpi->stride[2]; - mpi->stride[1] = vf->dmpi->stride[1]; - mpi->stride[2] = vf->dmpi->stride[2]; - } else { - mpi->planes[0] = vf->dmpi->planes[0] + tmargin * vf->dmpi->stride[0]; - } - mpi->stride[0] = vf->dmpi->stride[0]; - mpi->width = vf->dmpi->width; - mpi->flags |= MP_IMGFLAG_DIRECT; -} - static void blank(mp_image_t *mpi, int y1, int y2) { int color[3] = {16, 128, 128}; // black (YUV) @@ -144,81 +113,67 @@ static void blank(mp_image_t *mpi, int y1, int y2) } } -static int prepare_image(struct vf_instance *vf, mp_image_t *mpi) +static void prepare_image(struct vf_instance *vf, struct mp_image *dmpi, + struct mp_image *mpi) { int tmargin = vf->priv->opt_top_margin; - if (mpi->flags & MP_IMGFLAG_DIRECT) { - vf->dmpi = mpi->priv; - if (!vf->dmpi) { - mp_tmsg(MSGT_ASS, MSGL_WARN, "Why do we get NULL??\n"); - return 0; - } - mpi->priv = NULL; - // we've used DR, so we're ready... - if (tmargin) - blank(vf->dmpi, 0, tmargin); - if (vf->priv->opt_bottom_margin) - blank(vf->dmpi, vf->priv->outh - vf->priv->opt_bottom_margin, - vf->priv->outh); - if (!(mpi->flags & MP_IMGFLAG_PLANAR)) - vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette - return 0; - } - - // hope we'll get DR buffer: - vf->dmpi = vf_get_image(vf->next, vf->priv->outfmt, MP_IMGTYPE_TEMP, - MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_READABLE, - vf->priv->outw, vf->priv->outh); - // copy mpi->dmpi... if (mpi->flags & MP_IMGFLAG_PLANAR) { - memcpy_pic(vf->dmpi->planes[0] + tmargin * vf->dmpi->stride[0], + memcpy_pic(dmpi->planes[0] + tmargin * dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h, - vf->dmpi->stride[0], + dmpi->stride[0], mpi->stride[0]); - memcpy_pic(vf->dmpi->planes[1] + (tmargin >> mpi->chroma_y_shift) * vf->dmpi->stride[1], + memcpy_pic(dmpi->planes[1] + (tmargin >> mpi->chroma_y_shift) * dmpi->stride[1], mpi->planes[1], mpi->w >> mpi->chroma_x_shift, mpi->h >> mpi->chroma_y_shift, - vf->dmpi->stride[1], + dmpi->stride[1], mpi->stride[1]); - memcpy_pic(vf->dmpi->planes[2] + (tmargin >> mpi->chroma_y_shift) * vf->dmpi->stride[2], + memcpy_pic(dmpi->planes[2] + (tmargin >> mpi->chroma_y_shift) * dmpi->stride[2], mpi->planes[2], mpi->w >> mpi->chroma_x_shift, mpi->h >> mpi->chroma_y_shift, - vf->dmpi->stride[2], + dmpi->stride[2], mpi->stride[2]); } else { - memcpy_pic(vf->dmpi->planes[0] + tmargin * vf->dmpi->stride[0], + memcpy_pic(dmpi->planes[0] + tmargin * dmpi->stride[0], mpi->planes[0], - mpi->w * (vf->dmpi->bpp / 8), + mpi->w * (dmpi->bpp / 8), mpi->h, - vf->dmpi->stride[0], + dmpi->stride[0], mpi->stride[0]); - vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette + dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette } if (tmargin) - blank(vf->dmpi, 0, tmargin); + blank(dmpi, 0, tmargin); if (vf->priv->opt_bottom_margin) - blank(vf->dmpi, vf->priv->outh - vf->priv->opt_bottom_margin, + blank(dmpi, vf->priv->outh - vf->priv->opt_bottom_margin, vf->priv->outh); - return 0; } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { struct vf_priv_s *priv = vf->priv; struct osd_state *osd = priv->osd; - prepare_image(vf, mpi); + if (vf->priv->opt_top_margin || vf->priv->opt_bottom_margin || + !mp_image_is_writeable(mpi)) + { + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); + prepare_image(vf, dmpi, mpi); + talloc_free(mpi); + mpi = dmpi; + } + mp_image_set_colorspace_details(mpi, &priv->csp); - if (pts != MP_NOPTS_VALUE) - osd_draw_on_image(osd, priv->dim, pts, OSD_DRAW_SUB_FILTER, vf->dmpi); + if (mpi->pts != MP_NOPTS_VALUE) + osd_draw_on_image(osd, priv->dim, mpi->pts, OSD_DRAW_SUB_FILTER, mpi); - return vf_next_put_image(vf, vf->dmpi, pts); + return mpi; } static int query_format(struct vf_instance *vf, unsigned int fmt) @@ -273,8 +228,7 @@ static int vf_open(vf_instance_t *vf, char *args) vf->query_format = query_format; vf->uninit = uninit; vf->control = control; - vf->get_image = get_image; - vf->put_image = put_image; + vf->filter = filter; vf->default_caps = VFCAP_OSD; return 1; } diff --git a/video/filter/vf_swapuv.c b/video/filter/vf_swapuv.c index 1aa0b1061f..5e879ff557 100644 --- a/video/filter/vf_swapuv.c +++ b/video/filter/vf_swapuv.c @@ -29,49 +29,16 @@ #include "video/mp_image.h" #include "vf.h" - -//===========================================================================// - -static void get_image(struct vf_instance *vf, mp_image_t *mpi){ - mp_image_t *dmpi= vf_get_image(vf->next, mpi->imgfmt, - mpi->type, mpi->flags, mpi->w, mpi->h); - - mpi->planes[0]=dmpi->planes[0]; - mpi->planes[1]=dmpi->planes[2]; - mpi->planes[2]=dmpi->planes[1]; - mpi->stride[0]=dmpi->stride[0]; - mpi->stride[1]=dmpi->stride[2]; - mpi->stride[2]=dmpi->stride[1]; - mpi->width=dmpi->width; - - mpi->flags|=MP_IMGFLAG_DIRECT; - mpi->priv=(void*)dmpi; +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + struct mp_image old = *mpi; + mpi->planes[1] = old.planes[2]; + mpi->stride[1] = old.stride[2]; + mpi->planes[2] = old.planes[1]; + mpi->stride[2] = old.stride[1]; + return mpi; } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - mp_image_t *dmpi; - - if(mpi->flags&MP_IMGFLAG_DIRECT){ - dmpi=(mp_image_t*)mpi->priv; - } else { - dmpi=vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h); - assert(mpi->flags&MP_IMGFLAG_PLANAR); - dmpi->planes[0]=mpi->planes[0]; - dmpi->planes[1]=mpi->planes[2]; - dmpi->planes[2]=mpi->planes[1]; - dmpi->stride[0]=mpi->stride[0]; - dmpi->stride[1]=mpi->stride[2]; - dmpi->stride[2]=mpi->stride[1]; - dmpi->width=mpi->width; - } - - vf_clone_mpi_attributes(dmpi, mpi); - - return vf_next_put_image(vf,dmpi, pts); -} - -//===========================================================================// - static int query_format(struct vf_instance *vf, unsigned int fmt){ switch(fmt) { @@ -88,8 +55,7 @@ static int query_format(struct vf_instance *vf, unsigned int fmt){ } static int vf_open(vf_instance_t *vf, char *args){ - vf->put_image=put_image; - vf->get_image=get_image; + vf->filter=filter; vf->query_format=query_format; return 1; } diff --git a/video/filter/vf_unsharp.c b/video/filter/vf_unsharp.c index 4a53d0a795..c3150b9a33 100644 --- a/video/filter/vf_unsharp.c +++ b/video/filter/vf_unsharp.c @@ -155,40 +155,18 @@ static int config( struct vf_instance *vf, //===========================================================================// -static void get_image( struct vf_instance *vf, mp_image_t *mpi ) { - if( mpi->flags & MP_IMGFLAG_PRESERVE ) - return; // don't change - if( mpi->imgfmt!=vf->priv->outfmt ) - return; // colorspace differ - - mpi->priv = - vf->dmpi = vf_get_image( vf->next, mpi->imgfmt, mpi->type, mpi->flags, mpi->width, mpi->height ); - mpi->planes[0] = vf->dmpi->planes[0]; - mpi->stride[0] = vf->dmpi->stride[0]; - mpi->width = vf->dmpi->width; - if( mpi->flags & MP_IMGFLAG_PLANAR ) { - mpi->planes[1] = vf->dmpi->planes[1]; - mpi->planes[2] = vf->dmpi->planes[2]; - mpi->stride[1] = vf->dmpi->stride[1]; - mpi->stride[2] = vf->dmpi->stride[2]; +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + struct mp_image *dmpi = mpi; + if (!mp_image_is_writeable(mpi)) { + dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); } - mpi->flags |= MP_IMGFLAG_DIRECT; -} - -static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) { - mp_image_t *dmpi = mpi->priv; - mpi->priv = NULL; - - if( !(mpi->flags & MP_IMGFLAG_DIRECT) ) - // no DR, so get a new image! hope we'll get DR buffer: - dmpi = vf->dmpi = vf_get_image( vf->next,vf->priv->outfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->width, mpi->height); unsharp( dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam ); unsharp( dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam ); unsharp( dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam ); - vf_clone_mpi_attributes(dmpi, mpi); - #if HAVE_MMX if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t"); @@ -198,7 +176,9 @@ static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) { __asm__ volatile ("sfence\n\t"); #endif - return vf_next_put_image( vf, dmpi, pts); + if (dmpi != mpi) + talloc_free(mpi); + return dmpi; } static void uninit( struct vf_instance *vf ) { @@ -269,8 +249,7 @@ static const unsigned int fmt_list[] = { static int vf_open( vf_instance_t *vf, char *args ) { vf->config = config; - vf->put_image = put_image; - vf->get_image = get_image; + vf->filter = filter; vf->query_format = query_format; vf->uninit = uninit; vf->priv = malloc( sizeof(struct vf_priv_s) ); diff --git a/video/filter/vf_vo.c b/video/filter/vf_vo.c index 731d1bbcff..93ca91b2b1 100644 --- a/video/filter/vf_vo.c +++ b/video/filter/vf_vo.c @@ -105,8 +105,8 @@ static int control(struct vf_instance *vf, int request, void *data) } case VFCTRL_HWDEC_DECODER_RENDER: return vo_control(video_out, VOCTRL_HWDEC_DECODER_RENDER, data); - case VFCTRL_HWDEC_GET_SURFACE: - return vo_control(video_out, VOCTRL_HWDEC_GET_SURFACE, data); + case VFCTRL_HWDEC_ALLOC_SURFACE: + return vo_control(video_out, VOCTRL_HWDEC_ALLOC_SURFACE, data); } return CONTROL_UNKNOWN; } @@ -121,13 +121,6 @@ static int query_format(struct vf_instance *vf, unsigned int fmt) return flags; } -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) -{ - if (!video_out->config_ok) - return 0; - return vo_draw_image(video_out, mpi, pts); -} - static void uninit(struct vf_instance *vf) { if (vf->priv) { @@ -143,7 +136,6 @@ static int vf_open(vf_instance_t *vf, char *args) vf->config = config; vf->control = control; vf->query_format = query_format; - vf->put_image = put_image; vf->uninit = uninit; vf->priv = calloc(1, sizeof(struct vf_priv_s)); vf->priv->vo = (struct vo *)args; diff --git a/video/filter/vf_yadif.c b/video/filter/vf_yadif.c index 1158cffbbf..4e53ef168c 100644 --- a/video/filter/vf_yadif.c +++ b/video/filter/vf_yadif.c @@ -394,11 +394,11 @@ static int config(struct vf_instance *vf, return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); } -static int continue_buffered_image(struct vf_instance *vf); +static int continue_buffered_image(struct vf_instance *vf, struct mp_image *mpi); -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ +static int filter_image(struct vf_instance *vf, struct mp_image *mpi) +{ int tff; - if(vf->priv->parity < 0) { if (mpi->fields & MP_IMGFIELD_ORDERED) tff = !!(mpi->fields & MP_IMGFIELD_TOP_FIRST); @@ -414,47 +414,47 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ if (vf->priv->buffered_pts == MP_NOPTS_VALUE) delta = 1001.0/60000.0; // delta = field time distance else - delta = (pts - vf->priv->buffered_pts) / 2; + delta = (mpi->pts - vf->priv->buffered_pts) / 2; if (delta <= 0.0 || delta >= 0.5) delta = 0.0; vf->priv->buffered_pts_delta = delta; } - vf->priv->buffered_mpi = mpi; vf->priv->buffered_tff = tff; vf->priv->buffered_i = 0; - vf->priv->buffered_pts = pts; + vf->priv->buffered_pts = mpi->pts; - if(vf->priv->do_deinterlace == 0) - return vf_next_put_image(vf, mpi, pts); - else if(vf->priv->do_deinterlace == 1){ - vf->priv->do_deinterlace= 2; - return 0; - }else - return continue_buffered_image(vf); + if (vf->priv->do_deinterlace == 0) { + vf_add_output_frame(vf, mpi); + mpi = NULL; + } else if (vf->priv->do_deinterlace == 1) { + vf->priv->do_deinterlace = 2; + } else { + while (continue_buffered_image(vf, mpi)) { + } + } + + talloc_free(mpi); + + return 0; } -static int continue_buffered_image(struct vf_instance *vf) +static int continue_buffered_image(struct vf_instance *vf, struct mp_image *mpi) { - mp_image_t *mpi = vf->priv->buffered_mpi; int tff = vf->priv->buffered_tff; double pts = vf->priv->buffered_pts; int i; int ret=0; - mp_image_t *dmpi; pts += (vf->priv->buffered_i - 0.5 * (vf->priv->mode&1)) * vf->priv->buffered_pts_delta; for(i = vf->priv->buffered_i; i<=(vf->priv->mode&1); i++){ - dmpi=vf_get_image(vf->next,mpi->imgfmt, - MP_IMGTYPE_TEMP, - MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE, - mpi->width,mpi->height); - vf_clone_mpi_attributes(dmpi, mpi); + struct mp_image *dmpi = vf_alloc_out_image(vf); + mp_image_copy_attributes(dmpi, mpi); filter(vf->priv, dmpi->planes, dmpi->stride, mpi->w, mpi->h, i ^ tff ^ 1, tff); if (i < (vf->priv->mode & 1)) - vf_queue_frame(vf, continue_buffered_image); - ret |= vf_next_put_image(vf, dmpi, pts); + ret = 1; // more images to come + vf_add_output_frame(vf, dmpi); break; } vf->priv->buffered_i = 1; @@ -502,7 +502,7 @@ static int control(struct vf_instance *vf, int request, void* data){ static int vf_open(vf_instance_t *vf, char *args){ vf->config=config; - vf->put_image=put_image; + vf->filter_ext=filter_image; vf->query_format=query_format; vf->uninit=uninit; vf->priv=malloc(sizeof(struct vf_priv_s)); diff --git a/video/mp_image.h b/video/mp_image.h index 2fb693eb65..989f3ba909 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -144,8 +144,10 @@ typedef struct mp_image { int chroma_y_shift; // vertical enum mp_csp colorspace; enum mp_csp_levels levels; + /* only inside filter chain */ + double pts; /* memory management */ - int number, usage_count; // used by old VF/DR and vdpau code only + int number, usage_count; struct m_refcount *refcount; /* for private use by filter or vo driver (to store buffer id or dmpi) */ void* priv; diff --git a/video/out/vo.c b/video/out/vo.c index 18e000e3ab..9a75ccb789 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -38,6 +38,7 @@ #include "core/mp_fifo.h" #include "core/m_config.h" #include "core/mp_msg.h" +#include "video/mp_image.h" #include "video/vfcap.h" #include "sub/sub.h" @@ -159,28 +160,20 @@ int vo_control(struct vo *vo, uint32_t request, void *data) return vo->driver->control(vo, request, data); } -static void draw_image_pts(struct vo *vo, struct mp_image *mpi, double pts) -{ - if (vo->driver->draw_image_pts) { - vo->driver->draw_image_pts(vo, mpi, pts); - } else { - vo->driver->draw_image(vo, mpi); - } -} - // Return -1 if driver appears not to support a draw_image interface, // 0 otherwise (whether the driver actually drew something or not). -int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts) +int vo_draw_image(struct vo *vo, struct mp_image *mpi) { if (!vo->config_ok) return 0; if (vo->driver->buffer_frames) { - draw_image_pts(vo, mpi, pts); + vo->driver->draw_image(vo, mpi); return 0; } vo->frame_loaded = true; - vo->next_pts = pts; - vo->waiting_mpi = mpi; + vo->next_pts = mpi->pts; + assert(!vo->waiting_mpi); + vo->waiting_mpi = mp_image_new_ref(mpi); return 0; } @@ -211,6 +204,7 @@ void vo_skip_frame(struct vo *vo) { vo_control(vo, VOCTRL_SKIPFRAME, NULL); vo->frame_loaded = false; + mp_image_unrefp(&vo->waiting_mpi); } void vo_new_frame_imminent(struct vo *vo) @@ -218,8 +212,11 @@ void vo_new_frame_imminent(struct vo *vo) if (vo->driver->buffer_frames) vo_control(vo, VOCTRL_NEWFRAME, NULL); else { - draw_image_pts(vo, vo->waiting_mpi, vo->next_pts); - vo->waiting_mpi = NULL; + assert(vo->frame_loaded); + assert(vo->waiting_mpi); + assert(vo->waiting_mpi->pts == vo->next_pts); + vo->driver->draw_image(vo, vo->waiting_mpi); + mp_image_unrefp(&vo->waiting_mpi); } } @@ -262,6 +259,7 @@ void vo_seek_reset(struct vo *vo) vo_control(vo, VOCTRL_RESET, NULL); vo->frame_loaded = false; vo->hasframe = false; + mp_image_unrefp(&vo->waiting_mpi); } void vo_destroy(struct vo *vo) @@ -269,6 +267,7 @@ void vo_destroy(struct vo *vo) if (vo->registered_fd != -1) mp_input_rm_key_fd(vo->input_ctx, vo->registered_fd); vo->driver->uninit(vo); + talloc_free(vo->waiting_mpi); talloc_free(vo); } diff --git a/video/out/vo.h b/video/out/vo.h index 7b929f985d..e883293326 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -53,7 +53,7 @@ enum mp_voctrl { /* for vdpau hardware decoding */ VOCTRL_HWDEC_DECODER_RENDER, // pointer to hw state - VOCTRL_HWDEC_GET_SURFACE, // struct mp_image + VOCTRL_HWDEC_ALLOC_SURFACE, // struct mp_image** VOCTRL_NEWFRAME, VOCTRL_SKIPFRAME, @@ -285,7 +285,7 @@ int vo_config(struct vo *vo, uint32_t width, uint32_t height, void list_video_out(void); int vo_control(struct vo *vo, uint32_t request, void *data); -int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts); +int vo_draw_image(struct vo *vo, struct mp_image *mpi); int vo_redraw_frame(struct vo *vo); int vo_get_buffered_frame(struct vo *vo, bool eof); void vo_skip_frame(struct vo *vo); diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c index 6ae06fffec..7d846da92d 100644 --- a/video/out/vo_lavc.c +++ b/video/out/vo_lavc.c @@ -74,7 +74,7 @@ static int preinit(struct vo *vo, const char *arg) return 0; } -static void draw_image(struct vo *vo, mp_image_t *mpi, double pts); +static void draw_image(struct vo *vo, mp_image_t *mpi); static void uninit(struct vo *vo) { struct priv *vc = vo->priv; @@ -82,7 +82,7 @@ static void uninit(struct vo *vo) return; if (vc->lastipts >= 0 && vc->stream) - draw_image(vo, NULL, MP_NOPTS_VALUE); + draw_image(vo, NULL); if (vc->lastimg) { // palette hack @@ -284,7 +284,7 @@ static int encode_video(struct vo *vo, AVFrame *frame, AVPacket *packet) } } -static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) +static void draw_image(struct vo *vo, mp_image_t *mpi) { struct priv *vc = vo->priv; struct encode_lavc_context *ectx = vo->encode_lavc_ctx; @@ -294,6 +294,8 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) int64_t frameipts; double nextpts; + double pts = mpi ? mpi->pts : MP_NOPTS_VALUE; + if (!vc) return; if (!encode_lavc_start(ectx)) { @@ -540,7 +542,7 @@ const struct vo_driver video_out_lavc = { .control = control, .uninit = uninit, .check_events = check_events, - .draw_image_pts = draw_image, + .draw_image = draw_image, .draw_osd = draw_osd, .flip_page_timed = flip_page_timed, }; diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c index 661072b814..48080ba186 100644 --- a/video/out/vo_vdpau.c +++ b/video/out/vo_vdpau.c @@ -140,7 +140,8 @@ struct vdpctx { struct mp_osd_res osd_rect; struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES]; - int surface_num; + bool surface_in_use[MAX_VIDEO_SURFACES]; + int surface_num; // indexes output_surfaces int query_surface_num; VdpTime recent_vsync_time; float user_fps; @@ -332,15 +333,12 @@ static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface, struct vdpctx *vc = vo->priv; struct buffered_video_surface *bv = vc->buffered_video; - if (reserved_mpi) - reserved_mpi->usage_count++; - if (bv[NUM_BUFFERED_VIDEO - 1].mpi) - bv[NUM_BUFFERED_VIDEO - 1].mpi->usage_count--; + mp_image_unrefp(&bv[NUM_BUFFERED_VIDEO - 1].mpi); for (int i = NUM_BUFFERED_VIDEO - 1; i > 0; i--) bv[i] = bv[i - 1]; bv[0] = (struct buffered_video_surface){ - .mpi = reserved_mpi, + .mpi = reserved_mpi ? mp_image_new_ref(reserved_mpi) : NULL, .surface = surface, .pts = pts, }; @@ -358,8 +356,7 @@ static void forget_frames(struct vo *vo) vc->dropped_frame = false; for (int i = 0; i < NUM_BUFFERED_VIDEO; i++) { struct buffered_video_surface *p = vc->buffered_video + i; - if (p->mpi) - p->mpi->usage_count--; + mp_image_unrefp(&p->mpi); *p = (struct buffered_video_surface){ .surface = VDP_INVALID_HANDLE, }; @@ -1299,7 +1296,7 @@ static struct vdpau_render_state *get_surface(struct vo *vo, int number) return &vc->surface_render[number]; } -static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) +static void draw_image(struct vo *vo, mp_image_t *mpi) { struct vdpctx *vc = vo->priv; struct vdp_functions *vdp = vc->vdp; @@ -1329,7 +1326,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) else vc->top_field_first = 1; - add_new_video_surface(vo, rndr->surface, reserved_mpi, pts); + add_new_video_surface(vo, rndr->surface, reserved_mpi, mpi->pts); return; } @@ -1392,23 +1389,38 @@ static struct mp_image *get_window_screenshot(struct vo *vo) return image; } -static uint32_t get_decoder_surface(struct vo *vo, mp_image_t *mpi) +static void release_decoder_surface(void *ptr) +{ + bool *in_use_ptr = ptr; + *in_use_ptr = false; +} + +static struct mp_image *get_decoder_surface(struct vo *vo) { struct vdpctx *vc = vo->priv; - struct vdpau_render_state *rndr; if (!IMGFMT_IS_VDPAU(vc->image_format)) - return VO_FALSE; + return NULL; - rndr = get_surface(vo, mpi->number); - if (!rndr) { - mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] no surfaces available in " - "get_decoder_surface\n"); - // TODO: this probably breaks things forever, provide a dummy buffer? - return VO_FALSE; + for (int n = 0; n < MAX_VIDEO_SURFACES; n++) { + if (!vc->surface_in_use[n]) { + vc->surface_in_use[n] = true; + struct mp_image *res = + mp_image_new_custom_ref(&(struct mp_image){0}, + &vc->surface_in_use[n], + release_decoder_surface); + mp_image_setfmt(res, vc->image_format); + mp_image_set_size(res, vc->vid_width, vc->vid_height); + struct vdpau_render_state *rndr = get_surface(vo, n); + res->planes[0] = (void *)rndr; + return res; + } } - mpi->planes[0] = (void *)rndr; - return VO_TRUE; + + mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] no surfaces available in " + "get_decoder_surface\n"); + // TODO: this probably breaks things forever, provide a dummy buffer? + return NULL; } static int query_format(struct vo *vo, uint32_t format) @@ -1587,8 +1599,9 @@ static int control(struct vo *vo, uint32_t request, void *data) if (vc->dropped_frame) vo->want_redraw = true; return true; - case VOCTRL_HWDEC_GET_SURFACE: - return get_decoder_surface(vo, data); + case VOCTRL_HWDEC_ALLOC_SURFACE: + *(struct mp_image **)data = get_decoder_surface(vo); + return true; case VOCTRL_HWDEC_DECODER_RENDER: return decoder_render(vo, data); case VOCTRL_BORDER: @@ -1672,7 +1685,7 @@ const struct vo_driver video_out_vdpau = { .query_format = query_format, .config = config, .control = control, - .draw_image_pts = draw_image, + .draw_image = draw_image, .get_buffered_frame = set_next_frame_info, .draw_osd = draw_osd, .flip_page_timed = flip_page_timed,