aboutsummaryrefslogtreecommitdiffhomepage
path: root/video
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2012-11-05 14:25:04 +0100
committerGravatar wm4 <wm4@nowhere>2013-01-13 20:04:10 +0100
commitc54fc507da8edcc2c5d3bc3f50b0881d1c1406d7 (patch)
tree530d112301256e1c3ea50d7bb416b7ba2109130b /video
parent1c412169aca2f0ad38380b0c89f2485e6a256766 (diff)
video/filter: change filter API, use refcounting, remove filter DR
Change the entire filter API to use reference counted images instead of vf_get_image(). Remove filter "direct rendering". This was useful for vf_expand and (in rare cases) vf_sub: DR allowed these filters to pass a cropped image to the filters before them. Then, on filtering, the image was "uncropped", so that black bars could be added around the image without copying. This means that in some cases, vf_expand will be slower (-vf gradfun,expand for example). Note that another form of DR used for in-place filters has been replaced by simpler logic. Instead of trying to do DR, filters can check if the image is writeable (with mp_image_is_writeable()), and do true in-place if that's the case. This affects filters like vf_gradfun and vf_sub. Everything has to support strides now. If something doesn't, making a copy of the image data is required.
Diffstat (limited to 'video')
-rw-r--r--video/decode/dec_video.c15
-rw-r--r--video/decode/dec_video.h1
-rw-r--r--video/decode/lavc.h5
-rw-r--r--video/decode/vd.c3
-rw-r--r--video/decode/vd_lavc.c59
-rw-r--r--video/filter/vf.c334
-rw-r--r--video/filter/vf.h57
-rw-r--r--video/filter/vf_crop.c17
-rw-r--r--video/filter/vf_delogo.c62
-rw-r--r--video/filter/vf_divtc.c42
-rw-r--r--video/filter/vf_dlopen.c115
-rw-r--r--video/filter/vf_down3dright.c17
-rw-r--r--video/filter/vf_dsize.c1
-rw-r--r--video/filter/vf_eq.c37
-rw-r--r--video/filter/vf_expand.c106
-rw-r--r--video/filter/vf_flip.c61
-rw-r--r--video/filter/vf_format.c1
-rw-r--r--video/filter/vf_gradfun.c50
-rw-r--r--video/filter/vf_hqdn3d.c15
-rw-r--r--video/filter/vf_ilpack.c14
-rw-r--r--video/filter/vf_mirror.c16
-rw-r--r--video/filter/vf_noformat.c1
-rw-r--r--video/filter/vf_noise.c46
-rw-r--r--video/filter/vf_phase.c15
-rw-r--r--video/filter/vf_pp.c57
-rw-r--r--video/filter/vf_pullup.c134
-rw-r--r--video/filter/vf_rotate.c23
-rw-r--r--video/filter/vf_scale.c32
-rw-r--r--video/filter/vf_screenshot.c55
-rw-r--r--video/filter/vf_softpulldown.c55
-rw-r--r--video/filter/vf_stereo3d.c19
-rw-r--r--video/filter/vf_sub.c104
-rw-r--r--video/filter/vf_swapuv.c52
-rw-r--r--video/filter/vf_unsharp.c41
-rw-r--r--video/filter/vf_vo.c12
-rw-r--r--video/filter/vf_yadif.c50
-rw-r--r--video/mp_image.h4
-rw-r--r--video/out/vo.c29
-rw-r--r--video/out/vo.h4
-rw-r--r--video/out/vo_lavc.c10
-rw-r--r--video/out/vo_vdpau.c61
41 files changed, 605 insertions, 1227 deletions
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c
index 9ec5e3db65..8730703216 100644
--- a/video/decode/dec_video.c
+++ b/video/decode/dec_video.c
@@ -104,7 +104,6 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value)
void get_detected_video_colorspace(struct sh_video *sh, struct mp_csp_details *csp)
{
struct MPOpts *opts = sh->opts;
- struct vf_instance *vf = sh->vfilter;
csp->format = opts->requested_colorspace;
csp->levels_in = opts->requested_input_range;
@@ -113,7 +112,7 @@ void get_detected_video_colorspace(struct sh_video *sh, struct mp_csp_details *c
if (csp->format == MP_CSP_AUTO)
csp->format = sh->colorspace;
if (csp->format == MP_CSP_AUTO)
- csp->format = mp_csp_guess_colorspace(vf->w, vf->h);
+ csp->format = mp_csp_guess_colorspace(sh->disp_w, sh->disp_h);
if (csp->levels_in == MP_CSP_LEVELS_AUTO)
csp->levels_in = sh->color_range;
@@ -400,8 +399,10 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
}
#endif
- if (!mpi || drop_frame)
+ if (!mpi || drop_frame) {
+ talloc_free(mpi);
return NULL; // error / skipped frame
+ }
if (field_dominance == 0)
mpi->fields |= MP_IMGFIELD_TOP_FIRST;
@@ -432,11 +433,3 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
sh_video->num_sorted_pts_problems++;
return mpi;
}
-
-int filter_video(sh_video_t *sh_video, void *frame, double pts)
-{
- mp_image_t *mpi = frame;
- vf_instance_t *vf = sh_video->vfilter;
- // apply video filters and call the leaf vo/ve
- return vf->put_image(vf, mpi, pts);
-}
diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h
index 9eb90a5d5a..c7c535c68e 100644
--- a/video/decode/dec_video.h
+++ b/video/decode/dec_video.h
@@ -33,7 +33,6 @@ struct demux_packet;
void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
unsigned char *start, int in_size, int drop_frame,
double pts);
-int filter_video(sh_video_t *sh_video, void *frame, double pts);
int get_video_quality_max(sh_video_t *sh_video);
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index c4d24aad94..a355f61310 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -8,13 +8,9 @@
#include "demux/stheader.h"
#include "video/mp_image.h"
-#define MAX_NUM_MPI 50
-
typedef struct ffmpeg_ctx {
AVCodecContext *avctx;
AVFrame *pic;
- struct mp_image *last_mpi;
- struct mp_image hwdec_mpi[MAX_NUM_MPI];
struct hwdec *hwdec;
enum PixelFormat pix_fmt;
int do_hw_dr1, do_dr1;
@@ -28,6 +24,7 @@ typedef struct ffmpeg_ctx {
int rawvideo_fmt;
AVCodec *software_fallback;
struct FramePool *dr1_buffer_pool;
+ struct mp_image_pool *non_dr1_pool;
} vd_ffmpeg_ctx;
int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame);
diff --git a/video/decode/vd.c b/video/decode/vd.c
index e030cf4bd0..e3cb70ad1b 100644
--- a/video/decode/vd.c
+++ b/video/decode/vd.c
@@ -190,9 +190,6 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt)
"VO Config (%dx%d->%dx%d,flags=%d,0x%X)\n", sh->disp_w,
sh->disp_h, screen_size_x, screen_size_y, vocfg_flags, out_fmt);
- vf->w = sh->disp_w;
- vf->h = sh->disp_h;
-
if (vf_config_wrapper
(vf, sh->disp_w, sh->disp_h, screen_size_x, screen_size_y, vocfg_flags,
out_fmt) == 0) {
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 3ee8cc7932..7fd7437a3b 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -41,6 +41,7 @@
#include "vd.h"
#include "video/img_format.h"
+#include "video/mp_image_pool.h"
#include "video/filter/vf.h"
#include "demux/stheader.h"
#include "demux/demux_packet.h"
@@ -244,6 +245,7 @@ static int init(sh_video_t *sh)
ctx = sh->context = talloc_zero(NULL, vd_ffmpeg_ctx);
ctx->rawvideo_fmt = PIX_FMT_NONE;
+ ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16));
if (sh->codec->dll) {
lavc_codec = avcodec_find_decoder_by_name(sh->codec->dll);
@@ -478,7 +480,6 @@ static void uninit_avctx(sh_video_t *sh)
av_freep(&avctx);
avcodec_free_frame(&ctx->pic);
- mp_image_unrefp(&ctx->last_mpi);
mp_buffer_pool_free(&ctx->dr1_buffer_pool);
}
@@ -518,7 +519,7 @@ static int init_vo(sh_video_t *sh)
width != sh->disp_w || height != sh->disp_h ||
avctx->pix_fmt != ctx->pix_fmt || !ctx->vo_initialized)
{
- mp_image_unrefp(&ctx->last_mpi);
+ mp_image_pool_clear(ctx->non_dr1_pool);
ctx->vo_initialized = 0;
mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] aspect_ratio: %f\n", aspect);
@@ -579,22 +580,6 @@ static void draw_slice_hwdec(struct AVCodecContext *s,
vf->control(vf, VFCTRL_HWDEC_DECODER_RENDER, state_ptr);
}
-static struct mp_image *get_image_hwdec(vd_ffmpeg_ctx *ctx)
-{
- for (int n = 0; n < MAX_NUM_MPI; n++) {
- struct mp_image *cur = &ctx->hwdec_mpi[n];
- if (cur->usage_count == 0) {
- *cur = (struct mp_image) {
- .number = n,
- .imgfmt = ctx->best_csp,
- .usage_count = 1,
- };
- return cur;
- }
- }
- return NULL;
-}
-
static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
{
sh_video_t *sh = avctx->opaque;
@@ -620,12 +605,12 @@ static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
assert(IMGFMT_IS_HWACCEL(ctx->best_csp));
- struct mp_image *mpi = get_image_hwdec(ctx);
- if (!mpi)
- return -1;
+ struct mp_image *mpi = NULL;
struct vf_instance *vf = sh->vfilter;
- vf->control(vf, VFCTRL_HWDEC_GET_SURFACE, mpi);
+ vf->control(vf, VFCTRL_HWDEC_ALLOC_SURFACE, &mpi);
+ if (!mpi)
+ return -1;
for (int i = 0; i < 4; i++)
pic->data[i] = mpi->planes[i];
@@ -647,9 +632,8 @@ static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
assert(pic->type == FF_BUFFER_TYPE_USER);
assert(mpi);
- assert(mpi->usage_count > 0);
- mpi->usage_count--;
+ talloc_free(mpi);
for (int i = 0; i < 4; i++)
pic->data[i] = NULL;
@@ -726,13 +710,14 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, void *data,
return -1;
struct mp_image *mpi = NULL;
- if (ctx->do_hw_dr1 && pic->opaque)
+ if (ctx->do_hw_dr1 && pic->opaque) {
mpi = pic->opaque; // reordered frame
+ assert(mpi);
+ mpi = mp_image_new_ref(mpi);
+ }
if (!mpi) {
struct mp_image new = {0};
- new.type = MP_IMGTYPE_EXPORT;
- new.flags = MP_IMGFLAG_PRESERVE;
mp_image_set_size(&new, avctx->width, avctx->height);
mp_image_setfmt(&new, ctx->best_csp);
for (int i = 0; i < 4; i++) {
@@ -741,23 +726,17 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, void *data,
}
if (ctx->do_dr1 && pic->opaque) {
struct FrameBuffer *fb = pic->opaque;
- mp_image_unrefp(&ctx->last_mpi);
- mp_buffer_ref(fb); // reference for last_mpi
- ctx->last_mpi = mp_image_new_external_ref(&new, fb, fb_ref,
- fb_unref, fb_is_unique);
+ mp_buffer_ref(fb); // initial reference for mpi
+ mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref,
+ fb_is_unique);
} else {
- if (!ctx->last_mpi)
- ctx->last_mpi = mp_image_alloc(ctx->best_csp, new.w, new.h);
- mp_image_make_writeable(&ctx->last_mpi);
- assert(ctx->last_mpi->w == new.w && ctx->last_mpi->h == new.h);
- assert(ctx->last_mpi->imgfmt == new.imgfmt);
- mp_image_copy(ctx->last_mpi, &new);
+ mpi = mp_image_pool_get(ctx->non_dr1_pool, new.imgfmt,
+ new.w, new.h);
+ mp_image_copy(mpi, &new);
}
- mpi = ctx->last_mpi;
}
- if (!mpi->planes[0])
- return 0; // ?
+ assert(mpi->planes[0]);
assert(mpi->imgfmt == pixfmt2imgfmt(avctx->pix_fmt));
diff --git a/video/filter/vf.c b/video/filter/vf.c
index 417d5be1a3..4da167641a 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -33,6 +33,7 @@
#include "video/img_format.h"
#include "video/mp_image.h"
+#include "video/mp_image_pool.h"
#include "vf.h"
#include "video/memcpy_pic.h"
@@ -177,182 +178,21 @@ void vf_mpi_clear(mp_image_t *mpi, int x0, int y0, int w, int h)
}
}
-mp_image_t *vf_get_image(vf_instance_t *vf, unsigned int outfmt,
- int mp_imgtype, int mp_imgflag, int w, int h)
+// Get a new image for filter output, with size and pixel format according to
+// the last vf_config call.
+struct mp_image *vf_alloc_out_image(struct vf_instance *vf)
{
- mp_image_t *mpi = NULL;
- int w2;
- int number = mp_imgtype >> 16;
-
- assert(w == -1 || w >= vf->w);
- assert(h == -1 || h >= vf->h);
- assert(vf->w > 0);
- assert(vf->h > 0);
-
- if (w == -1)
- w = vf->w;
- if (h == -1)
- h = vf->h;
-
- w2 = (mp_imgflag & MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE) ? FFALIGN(w, 32) : w;
-
- if (vf->put_image == vf_next_put_image) {
- // passthru mode, if the filter uses the fallback/default put_image()
- mpi = vf_get_image(vf->next,outfmt,mp_imgtype,mp_imgflag,w,h);
- mpi->usage_count++;
- return mpi;
- }
-
- // Note: we should call libvo first to check if it supports direct rendering
- // and if not, then fallback to software buffers:
- switch (mp_imgtype & 0xff) {
- case MP_IMGTYPE_EXPORT:
- if (!vf->imgctx.export_images[0])
- vf->imgctx.export_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.export_images[0];
- break;
- case MP_IMGTYPE_STATIC:
- if (!vf->imgctx.static_images[0])
- vf->imgctx.static_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.static_images[0];
- break;
- case MP_IMGTYPE_TEMP:
- if (!vf->imgctx.temp_images[0])
- vf->imgctx.temp_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.temp_images[0];
- break;
- case MP_IMGTYPE_IPB:
- if (!(mp_imgflag & MP_IMGFLAG_READABLE)) { // B frame:
- if (!vf->imgctx.temp_images[0])
- vf->imgctx.temp_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.temp_images[0];
- break;
- }
- case MP_IMGTYPE_IP:
- if (!vf->imgctx.static_images[vf->imgctx.static_idx])
- vf->imgctx.static_images[vf->imgctx.static_idx] = new_mp_image(w2, h);
- mpi = vf->imgctx.static_images[vf->imgctx.static_idx];
- vf->imgctx.static_idx ^= 1;
- break;
- case MP_IMGTYPE_NUMBERED:
- if (number == -1) {
- int i;
- for (i = 0; i < NUM_NUMBERED_MPI; i++)
- if (!vf->imgctx.numbered_images[i] ||
- !vf->imgctx.numbered_images[i]->usage_count)
- break;
- number = i;
- }
- if (number < 0 || number >= NUM_NUMBERED_MPI)
- return NULL;
- if (!vf->imgctx.numbered_images[number])
- vf->imgctx.numbered_images[number] = new_mp_image(w2, h);
- mpi = vf->imgctx.numbered_images[number];
- mpi->number = number;
- break;
- }
- if (mpi) {
- int missing_palette = !(mpi->flags & MP_IMGFLAG_RGB_PALETTE) &&
- (mp_imgflag & MP_IMGFLAG_RGB_PALETTE);
- mpi->type = mp_imgtype;
- mpi->w = vf->w;
- mpi->h = vf->h;
- // keep buffer allocation status & color flags only:
- mpi->flags &= MP_IMGFLAG_ALLOCATED | MP_IMGFLAG_TYPE_DISPLAYED |
- MP_IMGFLAGMASK_COLORS;
- // accept restrictions, palette flags only:
- mpi->flags |= mp_imgflag & (MP_IMGFLAGMASK_RESTRICTIONS |
- MP_IMGFLAG_RGB_PALETTE);
- if (mpi->width != w2 || mpi->height != h || missing_palette) {
- if (mpi->flags & MP_IMGFLAG_ALLOCATED) {
- if (mpi->width < w2 || mpi->height < h || missing_palette) {
- // need to re-allocate buffer memory:
- av_free(mpi->planes[0]);
- if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
- av_free(mpi->planes[1]);
- for (int n = 0; n < MP_MAX_PLANES; n++)
- mpi->planes[n] = NULL;
- mpi->flags &= ~MP_IMGFLAG_ALLOCATED;
- mp_msg(MSGT_VFILTER, MSGL_V,
- "vf.c: have to REALLOCATE buffer memory :(\n");
- }
- }
- mpi->width = w2;
- mpi->chroma_width = (w2 + (1 << mpi->chroma_x_shift) - 1) >>
- mpi->chroma_x_shift;
- mpi->height = h;
- mpi->chroma_height = (h + (1 << mpi->chroma_y_shift) - 1) >>
- mpi->chroma_y_shift;
- }
- if (!mpi->bpp)
- mp_image_setfmt(mpi, outfmt);
- if (!(mpi->flags & MP_IMGFLAG_ALLOCATED) &&
- mpi->type > MP_IMGTYPE_EXPORT) {
- // check libvo first!
- if (vf->get_image)
- vf->get_image(vf, mpi);
-
- if (!(mpi->flags & MP_IMGFLAG_DIRECT)) {
- // non-direct and not yet allocated image. allocate it!
- if (!mpi->bpp) { // no way we can allocate this
- mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
- "vf_get_image: Tried to allocate a format that "
- "can not be allocated!\n");
- return NULL;
- }
-
- // check if codec prefer aligned stride:
- if (mp_imgflag & MP_IMGFLAG_PREFER_ALIGNED_STRIDE) {
- int align = (mpi->flags & MP_IMGFLAG_PLANAR &&
- mpi->flags & MP_IMGFLAG_YUV) ?
- (16 << mpi->chroma_x_shift) - 1 : 32; // OK?
- w2 = FFALIGN(w, align);
- if (mpi->width != w2) {
- // we have to change width... check if we CAN co it:
- int flags = vf->query_format(vf, outfmt);
- // should not fail
- if (!(flags & (VFCAP_CSP_SUPPORTED |
- VFCAP_CSP_SUPPORTED_BY_HW)))
- mp_msg(MSGT_DECVIDEO, MSGL_WARN,
- "??? vf_get_image{vf->query_format(outfmt)} "
- "failed!\n");
- if (flags & VFCAP_ACCEPT_STRIDE) {
- mpi->width = w2;
- mpi->chroma_width =
- (w2 + (1 << mpi->chroma_x_shift) - 1) >>
- mpi->chroma_x_shift;
- }
- }
- }
+ assert(vf->fmt_out.configured);
+ return mp_image_pool_get(vf->out_pool, vf->fmt_out.fmt,
+ vf->fmt_out.w, vf->fmt_out.h);
+}
- mp_image_alloc_planes(mpi);
- vf_mpi_clear(mpi, 0, 0, mpi->width, mpi->height);
- }
- }
- if (!(mpi->flags & MP_IMGFLAG_TYPE_DISPLAYED)) {
- mp_msg(MSGT_DECVIDEO, MSGL_V,
- "*** [%s] %s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
- vf->info->name,
- (mpi->type == MP_IMGTYPE_EXPORT) ? "Exporting" :
- ((mpi->flags & MP_IMGFLAG_DIRECT) ?
- "Direct Rendering" : "Allocating"),
- mpi->width, mpi->height, mpi->bpp,
- (mpi->flags & MP_IMGFLAG_YUV) ? "YUV" :
- ((mpi->flags & MP_IMGFLAG_SWAPPED) ? "BGR" : "RGB"),
- (mpi->flags & MP_IMGFLAG_PLANAR) ? "planar" : "packed",
- mpi->bpp * mpi->width * mpi->height / 8);
- mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "(imgfmt: %x, planes: %p,%p,%p "
- "strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n",
- mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
- mpi->stride[0], mpi->stride[1], mpi->stride[2],
- mpi->chroma_width, mpi->chroma_height,
- mpi->chroma_x_shift, mpi->chroma_y_shift);
- mpi->flags |= MP_IMGFLAG_TYPE_DISPLAYED;
- }
- mpi->qscale = NULL;
- mpi->usage_count++;
- }
- return mpi;
+void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img)
+{
+ assert(vf->fmt_out.configured);
+ assert(vf->fmt_out.fmt == img->imgfmt);
+ assert(vf->fmt_out.w == img->w && vf->fmt_out.h == img->h);
+ mp_image_pool_make_writeable(vf->out_pool, img);
}
//============================================================================
@@ -362,6 +202,14 @@ static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt)
return vf_next_query_format(vf, fmt);
}
+
+static struct mp_image *vf_default_filter(struct vf_instance *vf,
+ struct mp_image *mpi)
+{
+ assert(!vf->filter_ext);
+ return mpi;
+}
+
struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
const vf_info_t *const *filter_list,
vf_instance_t *next, const char *name,
@@ -378,16 +226,15 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
if (!strcmp(filter_list[i]->name, name))
break;
}
- vf = calloc(1, sizeof *vf);
+ vf = talloc_zero(NULL, struct vf_instance);
vf->opts = opts;
vf->info = filter_list[i];
vf->next = next;
vf->config = vf_next_config;
vf->control = vf_next_control;
vf->query_format = vf_default_query_format;
- vf->put_image = vf_next_put_image;
- vf->default_caps = VFCAP_ACCEPT_STRIDE;
- vf->default_reqs = 0;
+ vf->filter = vf_default_filter;
+ vf->out_pool = talloc_steal(vf, mp_image_pool_new(16));
if (vf->info->opts) { // vf_vo get some special argument
const m_struct_t *st = vf->info->opts;
void *vf_priv = m_struct_alloc(st);
@@ -404,7 +251,7 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
*retcode = vf->info->vf_open(vf, (char *)args);
if (*retcode > 0)
return vf;
- free(vf);
+ talloc_free(vf);
return NULL;
}
@@ -530,6 +377,7 @@ void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src)
dst->pict_type = src->pict_type;
dst->fields = src->fields;
dst->qscale_type = src->qscale_type;
+ dst->pts = src->pts;
if (dst->width == src->width && dst->height == src->height) {
dst->qstride = src->qstride;
dst->qscale = src->qscale;
@@ -542,60 +390,84 @@ void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src)
}
}
-void vf_queue_frame(vf_instance_t *vf, int (*func)(vf_instance_t *))
+// Used by filters to add a filtered frame to the output queue.
+// Ownership of img is transferred from caller to the filter chain.
+void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img)
{
- vf->continue_buffered_image = func;
+ if (img)
+ MP_TARRAY_APPEND(vf, vf->out_queued, vf->num_out_queued, img);
}
-// Output the next buffered image (if any) from the filter chain.
-// The queue could be kept as a simple stack/list instead avoiding the
-// looping here, but there's currently no good context variable where
-// that could be stored so this was easier to implement.
+static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf)
+{
+ 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;
+ }
+}
-int vf_output_queued_frame(vf_instance_t *vf)
+// 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) {
- 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;
+ 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 0;
- tmp = last->continue_buffered_image;
- last->continue_buffered_image = NULL;
- ret = tmp(last);
- if (ret)
- return ret;
+ 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];
- }
- 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);
+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);
}
- 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_clone_mpi_attributes(dmpi, mpi);
+ vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show);
- 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, 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(copyop, dmpi, mpi, 0);
+ vf_make_out_image_writeable(vf, mpi);
+
+ 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 <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <assert.h>
#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;
-
- 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;
-
- 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);
+ vf->priv->filter.inpic.pts = mpi->pts;
+
+ struct mp_image *out[FILTER_MAX_OUTCNT] = {0};
+
+ 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; p<mpi->num_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 <string.h>
#include <inttypes.h>
#include <errno.h>
+#include <assert.h>
#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;
+
+ bool non_local = vf->priv->pp & 0xFFFF;
-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
+ 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);
+
+ // 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);
+
+ struct mp_image data = *dmpi;
- dmpi->planes[0] = f->buffer->planes[0];
- dmpi->planes[1] = f->buffer->planes[1];
- dmpi->planes[2] = f->buffer->planes[2];
+ data.planes[0] = f->buffer->planes[0];
+ data.planes[1] = f->buffer->planes[1];
+ data.planes[2] = f->buffer->planes[2];
- dmpi->stride[0] = c->stride[0];
- dmpi->stride[1] = c->stride[1];
- dmpi->stride[2] = c->stride[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 (width<height) vf->priv->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;
-
-// printf("vf_scale::put_image(): processing whole frame! dmpi=%p flag=%d\n",
-// dmpi, (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK));
-
- 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);
- }
+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);
- if(vf->priv->palette) dmpi->planes[1]=vf->priv->palette; // export palette!
+ scale(vf->priv->ctx, vf->priv->ctx, mpi->planes,mpi->stride,0,mpi->h,dmpi->planes,dmpi->stride, vf->priv->interlaced);
- 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 <libswscale/swscale.h>
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 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 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 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;
-
- 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);
+ vf->priv->buffered_pts = mpi->pts;
+
+ 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,