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.
This commit is contained in:
wm4 2012-11-05 14:25:04 +01:00
parent 1c412169ac
commit c54fc507da
43 changed files with 648 additions and 1240 deletions

View File

@ -25,24 +25,34 @@
#define MP_TALLOC_ELEMS(p) (talloc_get_size(p) / sizeof((p)[0]))
#define MP_GROW_ARRAY(p, nextidx) do { \
if ((nextidx) == MP_TALLOC_ELEMS(p)) \
p = talloc_realloc_size(NULL, p, talloc_get_size(p) * 2); } while (0)
(p) = talloc_realloc_size(NULL, p, talloc_get_size(p) * 2); } while (0)
#define MP_RESIZE_ARRAY(ctx, p, count) do { \
p = talloc_realloc_size((ctx), p, (count) * sizeof(p[0])); } while (0)
(p) = talloc_realloc_size((ctx), p, (count) * sizeof((p)[0])); } while (0)
#define MP_TARRAY_GROW(ctx, p, nextidx) \
do { \
size_t nextidx_ = (nextidx); \
size_t nelems_ = MP_TALLOC_ELEMS(p); \
if (nextidx_ >= nelems_) \
p = talloc_realloc_size((ctx), p, \
(nextidx_ + 1) * sizeof((p)[0]) * 2);\
(p) = talloc_realloc_size(ctx, p, \
(nextidx_ + 1) * sizeof((p)[0]) * 2);\
} while (0)
#define MP_TARRAY_APPEND(ctx, p, idxvar, ...) \
do { \
MP_TARRAY_GROW(ctx, p, idxvar); \
p[idxvar] = (MP_EXPAND_ARGS(__VA_ARGS__)); \
idxvar++; \
(p)[(idxvar)] = (MP_EXPAND_ARGS(__VA_ARGS__));\
(idxvar)++; \
} while (0)
// Doesn't actually free any memory, or do any other talloc calls.
#define MP_TARRAY_REMOVE_AT(p, idxvar, at) \
do { \
size_t at_ = (at); \
assert(at_ <= (idxvar)); \
memmove((p) + at_, (p) + at_ + 1, \
((idxvar) - at_ - 1) * sizeof((p)[0])); \
(idxvar)--; \
} while (0)
#define talloc_struct(ctx, type, ...) \

View File

@ -2442,6 +2442,28 @@ no_video:
return 0;
}
static bool filter_output_queued_frame(struct MPContext *mpctx)
{
struct sh_video *sh_video = mpctx->sh_video;
struct vo *video_out = mpctx->video_out;
struct mp_image *img = vf_chain_output_queued_frame(sh_video->vfilter);
if (img && video_out->config_ok)
vo_draw_image(video_out, img);
talloc_free(img);
return !!img;
}
static void filter_video(struct MPContext *mpctx, struct mp_image *frame)
{
struct sh_video *sh_video = mpctx->sh_video;
frame->pts = sh_video->pts;
vf_filter_frame(sh_video->vfilter, frame);
filter_output_queued_frame(mpctx);
}
static double update_video_nocorrect_pts(struct MPContext *mpctx)
{
struct sh_video *sh_video = mpctx->sh_video;
@ -2451,7 +2473,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
// In nocorrect-pts mode there is no way to properly time these frames
if (vo_get_buffered_frame(video_out, 0) >= 0)
break;
if (vf_output_queued_frame(sh_video->vfilter))
if (filter_output_queued_frame(mpctx))
break;
unsigned char *packet = NULL;
frame_time = sh_video->next_frame_time;
@ -2476,7 +2498,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
decoded_frame = decode_video(sh_video, sh_video->ds->current, packet,
in_size, framedrop_type, sh_video->pts);
if (decoded_frame) {
filter_video(sh_video, decoded_frame, sh_video->pts);
filter_video(mpctx, decoded_frame);
}
break;
}
@ -2528,9 +2550,7 @@ static double update_video(struct MPContext *mpctx)
while (1) {
if (vo_get_buffered_frame(video_out, false) >= 0)
break;
// XXX Time used in this call is not counted in any performance
// timer now
if (vf_output_queued_frame(sh_video->vfilter))
if (filter_output_queued_frame(mpctx))
break;
int in_size = 0;
unsigned char *buf = NULL;
@ -2557,11 +2577,11 @@ static double update_video(struct MPContext *mpctx)
mpctx->hrseek_framedrop = false;
int framedrop_type = mpctx->hrseek_framedrop ? 1 :
check_framedrop(mpctx, sh_video->frametime);
void *decoded_frame = decode_video(sh_video, pkt, buf, in_size,
framedrop_type, pts);
struct mp_image *decoded_frame =
decode_video(sh_video, pkt, buf, in_size, framedrop_type, pts);
if (decoded_frame) {
determine_frame_pts(mpctx);
filter_video(sh_video, decoded_frame, sh_video->pts);
filter_video(mpctx, decoded_frame);
} else if (!pkt) {
if (vo_get_buffered_frame(video_out, true) < 0)
return -1;

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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));

View File

@ -33,6 +33,7 @@
#include "video/img_format.h"
#include "video/mp_image.h"
#include "video/mp_image_pool.h"
#include "vf.h"
#include "video/memcpy_pic.h"
@ -177,182 +178,21 @@ void vf_mpi_clear(mp_image_t *mpi, int x0, int y0, int w, int h)
}
}
mp_image_t *vf_get_image(vf_instance_t *vf, unsigned int outfmt,
int mp_imgtype, int mp_imgflag, int w, int h)
// Get a new image for filter output, with size and pixel format according to
// the last vf_config call.
struct mp_image *vf_alloc_out_image(struct vf_instance *vf)
{
mp_image_t *mpi = NULL;
int w2;
int number = mp_imgtype >> 16;
assert(vf->fmt_out.configured);
return mp_image_pool_get(vf->out_pool, vf->fmt_out.fmt,
vf->fmt_out.w, vf->fmt_out.h);
}
assert(w == -1 || w >= vf->w);
assert(h == -1 || h >= vf->h);
assert(vf->w > 0);
assert(vf->h > 0);
if (w == -1)
w = vf->w;
if (h == -1)
h = vf->h;
w2 = (mp_imgflag & MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE) ? FFALIGN(w, 32) : w;
if (vf->put_image == vf_next_put_image) {
// passthru mode, if the filter uses the fallback/default put_image()
mpi = vf_get_image(vf->next,outfmt,mp_imgtype,mp_imgflag,w,h);
mpi->usage_count++;
return mpi;
}
// Note: we should call libvo first to check if it supports direct rendering
// and if not, then fallback to software buffers:
switch (mp_imgtype & 0xff) {
case MP_IMGTYPE_EXPORT:
if (!vf->imgctx.export_images[0])
vf->imgctx.export_images[0] = new_mp_image(w2, h);
mpi = vf->imgctx.export_images[0];
break;
case MP_IMGTYPE_STATIC:
if (!vf->imgctx.static_images[0])
vf->imgctx.static_images[0] = new_mp_image(w2, h);
mpi = vf->imgctx.static_images[0];
break;
case MP_IMGTYPE_TEMP:
if (!vf->imgctx.temp_images[0])
vf->imgctx.temp_images[0] = new_mp_image(w2, h);
mpi = vf->imgctx.temp_images[0];
break;
case MP_IMGTYPE_IPB:
if (!(mp_imgflag & MP_IMGFLAG_READABLE)) { // B frame:
if (!vf->imgctx.temp_images[0])
vf->imgctx.temp_images[0] = new_mp_image(w2, h);
mpi = vf->imgctx.temp_images[0];
break;
}
case MP_IMGTYPE_IP:
if (!vf->imgctx.static_images[vf->imgctx.static_idx])
vf->imgctx.static_images[vf->imgctx.static_idx] = new_mp_image(w2, h);
mpi = vf->imgctx.static_images[vf->imgctx.static_idx];
vf->imgctx.static_idx ^= 1;
break;
case MP_IMGTYPE_NUMBERED:
if (number == -1) {
int i;
for (i = 0; i < NUM_NUMBERED_MPI; i++)
if (!vf->imgctx.numbered_images[i] ||
!vf->imgctx.numbered_images[i]->usage_count)
break;
number = i;
}
if (number < 0 || number >= NUM_NUMBERED_MPI)
return NULL;
if (!vf->imgctx.numbered_images[number])
vf->imgctx.numbered_images[number] = new_mp_image(w2, h);
mpi = vf->imgctx.numbered_images[number];
mpi->number = number;
break;
}
if (mpi) {
int missing_palette = !(mpi->flags & MP_IMGFLAG_RGB_PALETTE) &&
(mp_imgflag & MP_IMGFLAG_RGB_PALETTE);
mpi->type = mp_imgtype;
mpi->w = vf->w;
mpi->h = vf->h;
// keep buffer allocation status & color flags only:
mpi->flags &= MP_IMGFLAG_ALLOCATED | MP_IMGFLAG_TYPE_DISPLAYED |
MP_IMGFLAGMASK_COLORS;
// accept restrictions, palette flags only:
mpi->flags |= mp_imgflag & (MP_IMGFLAGMASK_RESTRICTIONS |
MP_IMGFLAG_RGB_PALETTE);
if (mpi->width != w2 || mpi->height != h || missing_palette) {
if (mpi->flags & MP_IMGFLAG_ALLOCATED) {
if (mpi->width < w2 || mpi->height < h || missing_palette) {
// need to re-allocate buffer memory:
av_free(mpi->planes[0]);
if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
av_free(mpi->planes[1]);
for (int n = 0; n < MP_MAX_PLANES; n++)
mpi->planes[n] = NULL;
mpi->flags &= ~MP_IMGFLAG_ALLOCATED;
mp_msg(MSGT_VFILTER, MSGL_V,
"vf.c: have to REALLOCATE buffer memory :(\n");
}
}
mpi->width = w2;
mpi->chroma_width = (w2 + (1 << mpi->chroma_x_shift) - 1) >>
mpi->chroma_x_shift;
mpi->height = h;
mpi->chroma_height = (h + (1 << mpi->chroma_y_shift) - 1) >>
mpi->chroma_y_shift;
}
if (!mpi->bpp)
mp_image_setfmt(mpi, outfmt);
if (!(mpi->flags & MP_IMGFLAG_ALLOCATED) &&
mpi->type > MP_IMGTYPE_EXPORT) {
// check libvo first!
if (vf->get_image)
vf->get_image(vf, mpi);
if (!(mpi->flags & MP_IMGFLAG_DIRECT)) {
// non-direct and not yet allocated image. allocate it!
if (!mpi->bpp) { // no way we can allocate this
mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
"vf_get_image: Tried to allocate a format that "
"can not be allocated!\n");
return NULL;
}
// check if codec prefer aligned stride:
if (mp_imgflag & MP_IMGFLAG_PREFER_ALIGNED_STRIDE) {
int align = (mpi->flags & MP_IMGFLAG_PLANAR &&
mpi->flags & MP_IMGFLAG_YUV) ?
(16 << mpi->chroma_x_shift) - 1 : 32; // OK?
w2 = FFALIGN(w, align);
if (mpi->width != w2) {
// we have to change width... check if we CAN co it:
int flags = vf->query_format(vf, outfmt);
// should not fail
if (!(flags & (VFCAP_CSP_SUPPORTED |
VFCAP_CSP_SUPPORTED_BY_HW)))
mp_msg(MSGT_DECVIDEO, MSGL_WARN,
"??? vf_get_image{vf->query_format(outfmt)} "
"failed!\n");
if (flags & VFCAP_ACCEPT_STRIDE) {
mpi->width = w2;
mpi->chroma_width =
(w2 + (1 << mpi->chroma_x_shift) - 1) >>
mpi->chroma_x_shift;
}
}
}
mp_image_alloc_planes(mpi);
vf_mpi_clear(mpi, 0, 0, mpi->width, mpi->height);
}
}
if (!(mpi->flags & MP_IMGFLAG_TYPE_DISPLAYED)) {
mp_msg(MSGT_DECVIDEO, MSGL_V,
"*** [%s] %s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
vf->info->name,
(mpi->type == MP_IMGTYPE_EXPORT) ? "Exporting" :
((mpi->flags & MP_IMGFLAG_DIRECT) ?
"Direct Rendering" : "Allocating"),
mpi->width, mpi->height, mpi->bpp,
(mpi->flags & MP_IMGFLAG_YUV) ? "YUV" :
((mpi->flags & MP_IMGFLAG_SWAPPED) ? "BGR" : "RGB"),
(mpi->flags & MP_IMGFLAG_PLANAR) ? "planar" : "packed",
mpi->bpp * mpi->width * mpi->height / 8);
mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "(imgfmt: %x, planes: %p,%p,%p "
"strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n",
mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
mpi->stride[0], mpi->stride[1], mpi->stride[2],
mpi->chroma_width, mpi->chroma_height,
mpi->chroma_x_shift, mpi->chroma_y_shift);
mpi->flags |= MP_IMGFLAG_TYPE_DISPLAYED;
}
mpi->qscale = NULL;
mpi->usage_count++;
}
return mpi;
void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img)
{
assert(vf->fmt_out.configured);
assert(vf->fmt_out.fmt == img->imgfmt);
assert(vf->fmt_out.w == img->w && vf->fmt_out.h == img->h);
mp_image_pool_make_writeable(vf->out_pool, img);
}
//============================================================================
@ -362,6 +202,14 @@ static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt)
return vf_next_query_format(vf, fmt);
}
static struct mp_image *vf_default_filter(struct vf_instance *vf,
struct mp_image *mpi)
{
assert(!vf->filter_ext);
return mpi;
}
struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
const vf_info_t *const *filter_list,
vf_instance_t *next, const char *name,
@ -378,16 +226,15 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
if (!strcmp(filter_list[i]->name, name))
break;
}
vf = calloc(1, sizeof *vf);
vf = talloc_zero(NULL, struct vf_instance);
vf->opts = opts;
vf->info = filter_list[i];
vf->next = next;
vf->config = vf_next_config;
vf->control = vf_next_control;
vf->query_format = vf_default_query_format;
vf->put_image = vf_next_put_image;
vf->default_caps = VFCAP_ACCEPT_STRIDE;
vf->default_reqs = 0;
vf->filter = vf_default_filter;
vf->out_pool = talloc_steal(vf, mp_image_pool_new(16));
if (vf->info->opts) { // vf_vo get some special argument
const m_struct_t *st = vf->info->opts;
void *vf_priv = m_struct_alloc(st);
@ -404,7 +251,7 @@ struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
*retcode = vf->info->vf_open(vf, (char *)args);
if (*retcode > 0)
return vf;
free(vf);
talloc_free(vf);
return NULL;
}
@ -530,6 +377,7 @@ void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src)
dst->pict_type = src->pict_type;
dst->fields = src->fields;
dst->qscale_type = src->qscale_type;
dst->pts = src->pts;
if (dst->width == src->width && dst->height == src->height) {
dst->qstride = src->qstride;
dst->qscale = src->qscale;
@ -542,60 +390,84 @@ void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src)
}
}
void vf_queue_frame(vf_instance_t *vf, int (*func)(vf_instance_t *))
// Used by filters to add a filtered frame to the output queue.
// Ownership of img is transferred from caller to the filter chain.
void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img)
{
vf->continue_buffered_image = func;
if (img)
MP_TARRAY_APPEND(vf, vf->out_queued, vf->num_out_queued, img);
}
// Output the next buffered image (if any) from the filter chain.
// The queue could be kept as a simple stack/list instead avoiding the
// looping here, but there's currently no good context variable where
// that could be stored so this was easier to implement.
int vf_output_queued_frame(vf_instance_t *vf)
static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf)
{
while (1) {
int ret;
vf_instance_t *current;
vf_instance_t *last = NULL;
int (*tmp)(vf_instance_t *);
for (current = vf; current; current = current->next)
if (current->continue_buffered_image)
last = current;
if (!last)
return 0;
tmp = last->continue_buffered_image;
last->continue_buffered_image = NULL;
ret = tmp(last);
if (ret)
return ret;
struct mp_image *res = NULL;
if (vf->num_out_queued) {
res = vf->out_queued[0];
MP_TARRAY_REMOVE_AT(vf->out_queued, vf->num_out_queued, 0);
}
return res;
}
// Input a frame into the filter chain.
// Return >= 0 on success, < 0 on failure (even if output frames were produced)
int vf_filter_frame(struct vf_instance *vf, struct mp_image *img)
{
assert(vf->fmt_in.configured);
assert(img->w == vf->fmt_in.w && img->h == vf->fmt_in.h);
assert(img->imgfmt == vf->fmt_in.fmt);
if (vf->filter_ext) {
return vf->filter_ext(vf, img);
} else {
vf_add_output_frame(vf, vf->filter(vf, img));
return 0;
}
}
// Output the next queued image (if any) from the full filter chain.
struct mp_image *vf_chain_output_queued_frame(struct vf_instance *vf)
{
while (1) {
struct vf_instance *last = NULL;
for (struct vf_instance * cur = vf; cur; cur = cur->next) {
if (cur->num_out_queued)
last = cur;
}
if (!last)
return NULL;
struct mp_image *img = vf_dequeue_output_frame(last);
if (!last->next)
return img;
vf_filter_frame(last->next, img);
}
}
static void vf_forget_frames(struct vf_instance *vf)
{
for (int n = 0; n < vf->num_out_queued; n++)
talloc_free(vf->out_queued[n]);
vf->num_out_queued = 0;
}
/**
* \brief Video config() function wrapper
*
* Blocks config() calls with different size or format for filters
* with VFCAP_CONSTANT
*
* First call is redirected to vf->config.
*
* In following calls, it verifies that the configuration parameters
* are unchanged, and returns either success or error.
*
*/
int vf_config_wrapper(struct vf_instance *vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt)
{
vf->fmt.have_configured = 1;
vf->fmt.orig_height = height;
vf->fmt.orig_width = width;
vf->fmt.orig_fmt = outfmt;
vf_forget_frames(vf);
mp_image_pool_clear(vf->out_pool);
vf->fmt_in = vf->fmt_out = (struct vf_format){0};
int r = vf->config(vf, width, height, d_width, d_height, flags, outfmt);
if (!r)
vf->fmt.have_configured = 0;
if (r) {
vf->fmt_in = (struct vf_format) {
.configured = 1,
.w = width,
.h = height,
.fmt = outfmt,
};
vf->fmt_out = vf->next ? vf->next->fmt_in : (struct vf_format){0};
}
return r;
}
@ -604,7 +476,6 @@ int vf_next_config(struct vf_instance *vf,
unsigned int voflags, unsigned int outfmt)
{
struct MPOpts *opts = vf->opts;
int miss;
int flags = vf->next->query_format(vf->next, outfmt);
if (!flags) {
// hmm. colorspace mismatch!!!
@ -623,19 +494,6 @@ int vf_next_config(struct vf_instance *vf,
return 0; // FAIL
}
}
mp_msg(MSGT_VFILTER, MSGL_V, "REQ: flags=0x%X req=0x%X \n",
flags, vf->default_reqs);
miss = vf->default_reqs - (flags & vf->default_reqs);
if (miss & VFCAP_ACCEPT_STRIDE) {
// vf requires stride support but vf->next doesn't support it!
// let's insert the 'expand' filter, it does the job for us:
vf_instance_t *vf2 = vf_open_filter(opts, vf->next, "expand", NULL);
if (!vf2)
return 0; // shouldn't happen!
vf->next = vf2;
}
vf->next->w = width;
vf->next->h = height;
return vf_config_wrapper(vf->next, width, height, d_width, d_height,
voflags, outfmt);
}
@ -653,11 +511,6 @@ int vf_next_query_format(struct vf_instance *vf, unsigned int fmt)
return flags;
}
int vf_next_put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
return vf->next->put_image(vf->next, mpi, pts);
}
//============================================================================
vf_instance_t *append_filters(vf_instance_t *last,
@ -688,13 +541,8 @@ void vf_uninit_filter(vf_instance_t *vf)
{
if (vf->uninit)
vf->uninit(vf);
free_mp_image(vf->imgctx.static_images[0]);
free_mp_image(vf->imgctx.static_images[1]);
free_mp_image(vf->imgctx.temp_images[0]);
free_mp_image(vf->imgctx.export_images[0]);
for (int i = 0; i < NUM_NUMBERED_MPI; i++)
free_mp_image(vf->imgctx.numbered_images[i]);
free(vf);
vf_forget_frames(vf);
talloc_free(vf);
}
void vf_uninit_filter_chain(vf_instance_t *vf)

View File

@ -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,

View File

@ -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,

View File

@ -101,7 +101,7 @@ static void update_sub(struct vf_priv_s *p, double pts)
}
static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height,
int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) {
int logo_x, int logo_y, int logo_w, int logo_h, int band, int show) {
int y, x;
int interp, dist;
uint8_t *xdst, *xsrc;
@ -124,8 +124,6 @@ static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int
topright = src+logo_y1*srcStride+logo_x2-1;
botleft = src+(logo_y2-1)*srcStride+logo_x1;
if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride);
dst += (logo_y1+1)*dstStride;
src += (logo_y1+1)*srcStride;
@ -175,55 +173,26 @@ static int config(struct vf_instance *vf,
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
// ok, we can do pp in-place (or pp disabled):
mpi->priv =
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
mpi->type, mpi->flags, mpi->w, mpi->h);
mpi->planes[0]=vf->dmpi->planes[0];
mpi->stride[0]=vf->dmpi->stride[0];
mpi->width=vf->dmpi->width;
if(mpi->flags&MP_IMGFLAG_PLANAR){
mpi->planes[1]=vf->dmpi->planes[1];
mpi->planes[2]=vf->dmpi->planes[2];
mpi->stride[1]=vf->dmpi->stride[1];
mpi->stride[2]=vf->dmpi->stride[2];
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
struct mp_image *dmpi = mpi;
if (!mp_image_is_writeable(mpi)) {
dmpi = vf_alloc_out_image(vf);
mp_image_copy_attributes(dmpi, mpi);
}
mpi->flags|=MP_IMGFLAG_DIRECT;
}
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
mp_image_t *dmpi;
if(mpi->flags&MP_IMGFLAG_DIRECT) {
vf->dmpi = mpi->priv;
mpi->priv = NULL;
} else {
// no DR, so get a new image! hope we'll get DR buffer:
vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
mpi->w,mpi->h);
}
dmpi= vf->dmpi;
if (vf->priv->timed_rect)
update_sub(vf->priv, pts);
update_sub(vf->priv, dmpi->pts);
delogo(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h,
vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show,
mpi->flags&MP_IMGFLAG_DIRECT);
vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show);
delogo(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2,
vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
mpi->flags&MP_IMGFLAG_DIRECT);
vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show);
delogo(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2,
vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
mpi->flags&MP_IMGFLAG_DIRECT);
vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show);
vf_clone_mpi_attributes(dmpi, mpi);
return vf_next_put_image(vf,dmpi, pts);
if (dmpi != mpi)
talloc_free(mpi);
return dmpi;
}
static void uninit(struct vf_instance *vf){
@ -323,8 +292,7 @@ load_error:
static int vf_open(vf_instance_t *vf, char *args){
vf->config=config;
vf->put_image=put_image;
vf->get_image=get_image;
vf->filter=filter;
vf->query_format=query_format;
vf->uninit=uninit;

View File

@ -46,6 +46,7 @@ struct vf_priv_s
unsigned int *csdata;
int *history;
struct vf_detc_pts_buf ptsbuf;
struct mp_image *buffer;
};
/*
@ -258,19 +259,23 @@ static int match(struct vf_priv_s *p, int *diffs,
return m;
}
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
mp_image_t *dmpi, *tmpi=0;
int n, m, f, newphase;
struct vf_priv_s *p=vf->priv;
unsigned int checksum;
double d;
dmpi=vf_get_image(vf->next, mpi->imgfmt,
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
mpi->width, mpi->height);
vf_clone_mpi_attributes(dmpi, mpi);
if (!p->buffer || p->buffer->w != mpi->w || p->buffer->h != mpi->h ||
p->buffer->imgfmt != mpi->imgfmt)
{
mp_image_unrefp(&p->buffer);
p->buffer = mp_image_alloc(mpi->imgfmt, mpi->w, mpi->h);
talloc_steal(vf, p->buffer);
}
struct mp_image *dmpi = p->buffer;
double pts = mpi->pts;
newphase=p->phase;
@ -360,26 +365,24 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
case 0:
imgop(copyop, dmpi, mpi, 0);
vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1);
talloc_free(mpi);
return 0;
case 4:
if(p->deghost>0)
{
tmpi=vf_get_image(vf->next, mpi->imgfmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
MP_IMGFLAG_READABLE,
mpi->width, mpi->height);
vf_clone_mpi_attributes(tmpi, mpi);
imgop(copyop, dmpi, mpi, 0);
vf_make_out_image_writeable(vf, mpi);
imgop(copyop, tmpi, mpi, 0);
imgop(deghost_plane, tmpi, dmpi, p->deghost);
imgop(copyop, dmpi, mpi, 0);
return vf_next_put_image(vf, tmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0));
imgop(deghost_plane, mpi, dmpi, p->deghost);
mpi->pts = vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0);
return mpi;
}
}
imgop(copyop, dmpi, mpi, 0);
return vf_next_put_image(vf, dmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0));
mpi->pts = vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0);
return mpi;
}
static int analyze(struct vf_priv_s *p)
@ -613,10 +616,9 @@ static int vf_open(vf_instance_t *vf, char *args)
return 0;
}
vf->put_image=put_image;
vf->filter=filter;
vf->uninit=uninit;
vf->query_format=query_format;
vf->default_reqs=VFCAP_ACCEPT_STRIDE;
if(!(vf->priv=p=calloc(1, sizeof(struct vf_priv_s))))
goto nomem;

View File

@ -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;
vf->priv->filter.inpic.pts = mpi->pts;
if (vf->priv->out_cnt >= 2) {
// more than one out pic
int ret = vf->priv->filter.put_image(&vf->priv->filter);
if (ret <= 0)
return ret;
struct mp_image *out[FILTER_MAX_OUTCNT] = {0};
vf->priv->outbuffermpi = mpi;
vf->priv->outbufferlen = ret;
vf->priv->outbufferpos = 0;
return continue_put_image(vf);
} else {
// efficient case: exactly one out pic
mp_image_t *dmpi =
vf_get_image(vf->next, vf->priv->outfmt,
MP_IMGTYPE_TEMP,
MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
vf->priv->out_width, vf->priv->out_height);
set_imgprop(&vf->priv->filter.outpic[0], dmpi);
int ret = vf->priv->filter.put_image(&vf->priv->filter);
if (ret <= 0)
return ret;
// pass through qscale if we can
vf_clone_mpi_attributes(dmpi, mpi);
return vf_next_put_image(vf, dmpi, vf->priv->filter.outpic[0].pts);
for (int n = 0; n < vf->priv->out_cnt; n++) {
out[n] = vf_alloc_out_image(vf);
mp_image_copy_attributes(out[n], mpi);
set_imgprop(&vf->priv->filter.outpic[n], out[n]);
}
// more than one out pic
int ret = vf->priv->filter.put_image(&vf->priv->filter);
if (ret < 0)
ret = 0;
assert(ret <= vf->priv->out_cnt);
for (int n = 0; n < ret; n++) {
out[n]->pts = vf->priv->filter.outpic[n].pts;
vf_add_output_frame(vf, out[n]);
}
for (int n = ret; n < FILTER_MAX_OUTCNT; n++) {
talloc_free(out[n]);
}
talloc_free(mpi);
return 0;
}
//===========================================================================//
@ -319,7 +276,7 @@ static int vf_open(vf_instance_t *vf, char *args)
vf->priv->cfg_dllname);
return 0;
}
vf_dlopen_getcontext_func *func =
(vf_dlopen_getcontext_func *) DLLSymbol(vf->priv->dll, "vf_dlopen_getcontext");
if (!func) {
@ -352,7 +309,7 @@ static int vf_open(vf_instance_t *vf, char *args)
return 0;
}
vf->put_image = put_image;
vf->filter_ext = filter;
vf->query_format = query_format;
vf->config = config;
vf->uninit = uninit;

View File

@ -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));

View File

@ -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;

View File

@ -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));

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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))))
{

View File

@ -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;
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
// no DR, so get a new image! hope we'll get DR buffer:
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
MP_IMGFLAG_PREFER_ALIGNED_STRIDE | MP_IMGFLAG_READABLE,
// MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
// mpi->w,mpi->h);
(mpi->width+7)&(~7),(mpi->height+7)&(~7));
vf->dmpi->w=mpi->w; vf->dmpi->h=mpi->h; // display w;h
bool non_local = vf->priv->pp & 0xFFFF;
struct mp_image *dmpi = mpi;
if (!mp_image_is_writeable(mpi) || non_local) {
dmpi = vf_alloc_out_image(vf);
mp_image_copy_attributes(dmpi, mpi);
}
if(vf->priv->pp || !(mpi->flags&MP_IMGFLAG_DIRECT)){
// apparently this is required
assert(mpi->stride[0] >= ((mpi->w+7)&(~7)));
// do the postprocessing! (or copy if no DR)
pp_postprocess((const uint8_t **)mpi->planes, mpi->stride,
vf->dmpi->planes,vf->dmpi->stride,
dmpi->planes,dmpi->stride,
(mpi->w+7)&(~7),mpi->h,
mpi->qscale, mpi->qstride,
vf->priv->ppMode[ vf->priv->pp ], vf->priv->context,
@ -138,8 +122,10 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
#else
mpi->pict_type);
#endif
}
return vf_next_put_image(vf,vf->dmpi, pts);
if (dmpi != mpi)
talloc_free(mpi);
return dmpi;
}
//===========================================================================//
@ -162,8 +148,7 @@ static int vf_open(vf_instance_t *vf, char *args){
vf->query_format=query_format;
vf->control=control;
vf->config=config;
vf->get_image=get_image;
vf->put_image=put_image;
vf->filter=filter;
vf->uninit=uninit;
vf->default_caps=VFCAP_ACCEPT_STRIDE|VFCAP_POSTPROC;
vf->priv=malloc(sizeof(struct vf_priv_s));

View File

@ -75,55 +75,25 @@ static void init_pullup(struct vf_instance *vf, mp_image_t *mpi)
vf->priv->qbuf = malloc(c->w[3]);
}
#if 0
static void get_image(struct vf_instance *vf, mp_image_t *mpi)
{
struct pullup_context *c = vf->priv->ctx;
struct pullup_buffer *b;
if (mpi->type == MP_IMGTYPE_STATIC) return;
if (!vf->priv->init) init_pullup(vf, mpi);
b = pullup_get_buffer(c, 2);
if (!b) return; /* shouldn't happen... */
mpi->priv = b;
mpi->planes[0] = b->planes[0];
mpi->planes[1] = b->planes[1];
mpi->planes[2] = b->planes[2];
mpi->stride[0] = c->stride[0];
mpi->stride[1] = c->stride[1];
mpi->stride[2] = c->stride[2];
mpi->flags |= MP_IMGFLAG_DIRECT;
}
#endif
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
struct pullup_context *c = vf->priv->ctx;
struct pullup_buffer *b;
struct pullup_frame *f;
mp_image_t *dmpi;
int ret;
int p;
int i;
double pts = mpi->pts;
struct mp_image *dmpi = NULL;
if (!vf->priv->init) init_pullup(vf, mpi);
if (mpi->flags & MP_IMGFLAG_DIRECT) {
b = mpi->priv;
mpi->priv = 0;
} else {
if (1) {
b = pullup_get_buffer(c, 2);
if (!b) {
mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n");
f = pullup_get_frame(c);
pullup_release_frame(f);
return 0;
goto skip;
}
memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
c->stride[0], mpi->stride[0]);
@ -174,21 +144,23 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
/* Fake yes for first few frames (buffer depth) to keep from
* breaking A/V sync with G1's bad architecture... */
if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
//if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
if (!f)
goto skip;
if (f->length < 2) {
pullup_release_frame(f);
f = pullup_get_frame(c);
if (!f) return 0;
if (!f) goto skip;
if (f->length < 2) {
pullup_release_frame(f);
if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
return 0;
goto skip;
f = pullup_get_frame(c);
if (!f) return 0;
if (!f) goto skip;
if (f->length < 2) {
pullup_release_frame(f);
return 0;
goto skip;
}
}
}
@ -210,66 +182,42 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
}
#endif
/* If the frame isn't already exportable... */
while (!f->buffer) {
dmpi = vf_get_image(vf->next, mpi->imgfmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
mpi->width, mpi->height);
/* FIXME: Is it ok to discard dmpi if it's not direct? */
if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) {
pullup_pack_frame(c, f);
break;
}
/* Direct render fields into output buffer */
my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0],
mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0],
f->ofields[1]->planes[0] + c->stride[0],
mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
if (mpi->flags & MP_IMGFLAG_PLANAR) {
my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1],
mpi->chroma_width, mpi->chroma_height/2,
dmpi->stride[1]*2, c->stride[1]*2);
my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1],
f->ofields[1]->planes[1] + c->stride[1],
mpi->chroma_width, mpi->chroma_height/2,
dmpi->stride[1]*2, c->stride[1]*2);
my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2],
mpi->chroma_width, mpi->chroma_height/2,
dmpi->stride[2]*2, c->stride[2]*2);
my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2],
f->ofields[1]->planes[2] + c->stride[2],
mpi->chroma_width, mpi->chroma_height/2,
dmpi->stride[2]*2, c->stride[2]*2);
}
pullup_release_frame(f);
if (mpi->qscale) {
dmpi->qscale = vf->priv->qbuf;
dmpi->qstride = mpi->qstride;
dmpi->qscale_type = mpi->qscale_type;
}
return vf_next_put_image(vf, dmpi, f->pts);
}
dmpi = vf_get_image(vf->next, mpi->imgfmt,
MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
mpi->width, mpi->height);
/* If the frame isn't already exportable... */
if (!f->buffer)
pullup_pack_frame(c, f);
dmpi->planes[0] = f->buffer->planes[0];
dmpi->planes[1] = f->buffer->planes[1];
dmpi->planes[2] = f->buffer->planes[2];
// NOTE: the copy could probably be avoided by changing or using the
// pullup internal buffer management. But right now just do the
// safe thing and always copy. Code outside the filter might
// hold a buffer reference even if the filter chain is destroyed.
dmpi = vf_alloc_out_image(vf);
mp_image_copy_attributes(dmpi, mpi);
dmpi->stride[0] = c->stride[0];
dmpi->stride[1] = c->stride[1];
dmpi->stride[2] = c->stride[2];
struct mp_image data = *dmpi;
data.planes[0] = f->buffer->planes[0];
data.planes[1] = f->buffer->planes[1];
data.planes[2] = f->buffer->planes[2];
data.stride[0] = c->stride[0];
data.stride[1] = c->stride[1];
data.stride[2] = c->stride[2];
mp_image_copy(dmpi, &data);
dmpi->pts = f->pts;
// Warning: entirely bogus memory management of qscale
if (mpi->qscale) {
dmpi->qscale = vf->priv->qbuf;
dmpi->qstride = mpi->qstride;
dmpi->qscale_type = mpi->qscale_type;
}
ret = vf_next_put_image(vf, dmpi, f->pts);
pullup_release_frame(f);
return ret;
skip:
talloc_free(mpi);
return dmpi;
}
static int query_format(struct vf_instance *vf, unsigned int fmt)
@ -302,12 +250,10 @@ static int vf_open(vf_instance_t *vf, char *args)
{
struct vf_priv_s *p;
struct pullup_context *c;
//vf->get_image = get_image;
vf->put_image = put_image;
vf->filter = filter;
vf->config = config;
vf->query_format = query_format;
vf->uninit = uninit;
vf->default_reqs = VFCAP_ACCEPT_STRIDE;
vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
p->ctx = c = pullup_alloc_context();
p->fakecount = 1;

View File

@ -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;

View File

@ -408,31 +408,15 @@ static void scale(struct SwsContext *sws1, struct SwsContext *sws2, uint8_t *src
}
}
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
mp_image_t *dmpi=mpi->priv;
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
struct mp_image *dmpi = vf_alloc_out_image(vf);
mp_image_copy_attributes(dmpi, mpi);
// printf("vf_scale::put_image(): processing whole frame! dmpi=%p flag=%d\n",
// dmpi, (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK));
scale(vf->priv->ctx, vf->priv->ctx, mpi->planes,mpi->stride,0,mpi->h,dmpi->planes,dmpi->stride, vf->priv->interlaced);
if(!dmpi){
// hope we'll get DR buffer:
dmpi=vf_get_image(vf->next,vf->priv->fmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
vf->priv->w, vf->priv->h);
scale(vf->priv->ctx, vf->priv->ctx, mpi->planes,mpi->stride,0,mpi->h,dmpi->planes,dmpi->stride, vf->priv->interlaced);
}
if(vf->priv->w==mpi->w && vf->priv->h==mpi->h){
// just conversion, no scaling -> keep postprocessing data
// this way we can apply pp filter to non-yv12 source using scaler
vf_clone_mpi_attributes(dmpi, mpi);
}
if(vf->priv->palette) dmpi->planes[1]=vf->priv->palette; // export palette!
return vf_next_put_image(vf,dmpi, pts);
talloc_free(mpi);
return dmpi;
}
static int control(struct vf_instance *vf, int request, void* data){
@ -588,7 +572,7 @@ static void uninit(struct vf_instance *vf){
static int vf_open(vf_instance_t *vf, char *args){
vf->config=config;
vf->put_image=put_image;
vf->filter=filter;
vf->query_format=query_format;
vf->control= control;
vf->uninit=uninit;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -29,49 +29,16 @@
#include "video/mp_image.h"
#include "vf.h"
//===========================================================================//
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
mp_image_t *dmpi= vf_get_image(vf->next, mpi->imgfmt,
mpi->type, mpi->flags, mpi->w, mpi->h);
mpi->planes[0]=dmpi->planes[0];
mpi->planes[1]=dmpi->planes[2];
mpi->planes[2]=dmpi->planes[1];
mpi->stride[0]=dmpi->stride[0];
mpi->stride[1]=dmpi->stride[2];
mpi->stride[2]=dmpi->stride[1];
mpi->width=dmpi->width;
mpi->flags|=MP_IMGFLAG_DIRECT;
mpi->priv=(void*)dmpi;
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
struct mp_image old = *mpi;
mpi->planes[1] = old.planes[2];
mpi->stride[1] = old.stride[2];
mpi->planes[2] = old.planes[1];
mpi->stride[2] = old.stride[1];
return mpi;
}
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
mp_image_t *dmpi;
if(mpi->flags&MP_IMGFLAG_DIRECT){
dmpi=(mp_image_t*)mpi->priv;
} else {
dmpi=vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h);
assert(mpi->flags&MP_IMGFLAG_PLANAR);
dmpi->planes[0]=mpi->planes[0];
dmpi->planes[1]=mpi->planes[2];
dmpi->planes[2]=mpi->planes[1];
dmpi->stride[0]=mpi->stride[0];
dmpi->stride[1]=mpi->stride[2];
dmpi->stride[2]=mpi->stride[1];
dmpi->width=mpi->width;
}
vf_clone_mpi_attributes(dmpi, mpi);
return vf_next_put_image(vf,dmpi, pts);
}
//===========================================================================//
static int query_format(struct vf_instance *vf, unsigned int fmt){
switch(fmt)
{
@ -88,8 +55,7 @@ static int query_format(struct vf_instance *vf, unsigned int fmt){
}
static int vf_open(vf_instance_t *vf, char *args){
vf->put_image=put_image;
vf->get_image=get_image;
vf->filter=filter;
vf->query_format=query_format;
return 1;
}

View File

@ -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) );

View File

@ -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;

View File

@ -394,11 +394,11 @@ static int config(struct vf_instance *vf,
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}
static int continue_buffered_image(struct vf_instance *vf);
static int continue_buffered_image(struct vf_instance *vf, struct mp_image *mpi);
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
static int filter_image(struct vf_instance *vf, struct mp_image *mpi)
{
int tff;
if(vf->priv->parity < 0) {
if (mpi->fields & MP_IMGFIELD_ORDERED)
tff = !!(mpi->fields & MP_IMGFIELD_TOP_FIRST);
@ -414,47 +414,47 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
if (vf->priv->buffered_pts == MP_NOPTS_VALUE)
delta = 1001.0/60000.0; // delta = field time distance
else
delta = (pts - vf->priv->buffered_pts) / 2;
delta = (mpi->pts - vf->priv->buffered_pts) / 2;
if (delta <= 0.0 || delta >= 0.5)
delta = 0.0;
vf->priv->buffered_pts_delta = delta;
}
vf->priv->buffered_mpi = mpi;
vf->priv->buffered_tff = tff;
vf->priv->buffered_i = 0;
vf->priv->buffered_pts = pts;
vf->priv->buffered_pts = mpi->pts;
if(vf->priv->do_deinterlace == 0)
return vf_next_put_image(vf, mpi, pts);
else if(vf->priv->do_deinterlace == 1){
vf->priv->do_deinterlace= 2;
return 0;
}else
return continue_buffered_image(vf);
if (vf->priv->do_deinterlace == 0) {
vf_add_output_frame(vf, mpi);
mpi = NULL;
} else if (vf->priv->do_deinterlace == 1) {
vf->priv->do_deinterlace = 2;
} else {
while (continue_buffered_image(vf, mpi)) {
}
}
talloc_free(mpi);
return 0;
}
static int continue_buffered_image(struct vf_instance *vf)
static int continue_buffered_image(struct vf_instance *vf, struct mp_image *mpi)
{
mp_image_t *mpi = vf->priv->buffered_mpi;
int tff = vf->priv->buffered_tff;
double pts = vf->priv->buffered_pts;
int i;
int ret=0;
mp_image_t *dmpi;
pts += (vf->priv->buffered_i - 0.5 * (vf->priv->mode&1)) * vf->priv->buffered_pts_delta;
for(i = vf->priv->buffered_i; i<=(vf->priv->mode&1); i++){
dmpi=vf_get_image(vf->next,mpi->imgfmt,
MP_IMGTYPE_TEMP,
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
mpi->width,mpi->height);
vf_clone_mpi_attributes(dmpi, mpi);
struct mp_image *dmpi = vf_alloc_out_image(vf);
mp_image_copy_attributes(dmpi, mpi);
filter(vf->priv, dmpi->planes, dmpi->stride, mpi->w, mpi->h, i ^ tff ^ 1, tff);
if (i < (vf->priv->mode & 1))
vf_queue_frame(vf, continue_buffered_image);
ret |= vf_next_put_image(vf, dmpi, pts);
ret = 1; // more images to come
vf_add_output_frame(vf, dmpi);
break;
}
vf->priv->buffered_i = 1;
@ -502,7 +502,7 @@ static int control(struct vf_instance *vf, int request, void* data){
static int vf_open(vf_instance_t *vf, char *args){
vf->config=config;
vf->put_image=put_image;
vf->filter_ext=filter_image;
vf->query_format=query_format;
vf->uninit=uninit;
vf->priv=malloc(sizeof(struct vf_priv_s));

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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,