diff --git a/Changelog b/Changelog index 8a4eb5ad76..ffc591d93f 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest. version : - deflicker video filter +- doubleweave video filter version 3.3: - CrystalHD decoder moved to new decode API diff --git a/doc/filters.texi b/doc/filters.texi index 36efc3369a..ac32995dea 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14659,12 +14659,15 @@ Default is digital. Set background opacity. @end table -@section weave +@section weave, doubleweave The @code{weave} takes a field-based video input and join each two sequential fields into single frame, producing a new double height clip with half the frame rate and half the frame count. +The @code{doubleweave} works same as @code{weave} but without +halving frame rate and frame count. + It accepts the following option: @table @option diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 6de7cc0ff3..50c5132555 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -164,6 +164,7 @@ OBJS-$(CONFIG_DESHAKE_FILTER) += vf_deshake.o OBJS-$(CONFIG_DETELECINE_FILTER) += vf_detelecine.o OBJS-$(CONFIG_DILATION_FILTER) += vf_neighbor.o OBJS-$(CONFIG_DISPLACE_FILTER) += vf_displace.o framesync.o +OBJS-$(CONFIG_DOUBLEWEAVE_FILTER) += vf_weave.o OBJS-$(CONFIG_DRAWBOX_FILTER) += vf_drawbox.o OBJS-$(CONFIG_DRAWGRAPH_FILTER) += f_drawgraph.o OBJS-$(CONFIG_DRAWGRID_FILTER) += vf_drawbox.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 0e69f99509..f482adb3c5 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -175,6 +175,7 @@ static void register_all(void) REGISTER_FILTER(DETELECINE, detelecine, vf); REGISTER_FILTER(DILATION, dilation, vf); REGISTER_FILTER(DISPLACE, displace, vf); + REGISTER_FILTER(DOUBLEWEAVE, doubleweave, vf); REGISTER_FILTER(DRAWBOX, drawbox, vf); REGISTER_FILTER(DRAWGRAPH, drawgraph, vf); REGISTER_FILTER(DRAWGRID, drawgrid, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index 1f0b72a4fc..8daadc3779 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 6 -#define LIBAVFILTER_VERSION_MINOR 85 +#define LIBAVFILTER_VERSION_MINOR 86 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c index a5fc1b7403..6d3dd7c299 100644 --- a/libavfilter/vf_weave.c +++ b/libavfilter/vf_weave.c @@ -27,6 +27,7 @@ typedef struct WeaveContext { const AVClass *class; int first_field; + int double_weave; int nb_planes; int planeheight[4]; int linesize[4]; @@ -56,10 +57,12 @@ static int config_props_output(AVFilterLink *outlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); int ret; - outlink->time_base.num = inlink->time_base.num * 2; - outlink->time_base.den = inlink->time_base.den; - outlink->frame_rate.num = inlink->frame_rate.num; - outlink->frame_rate.den = inlink->frame_rate.den * 2; + if (!s->double_weave) { + outlink->time_base.num = inlink->time_base.num * 2; + outlink->time_base.den = inlink->time_base.den; + outlink->frame_rate.num = inlink->frame_rate.num; + outlink->frame_rate.den = inlink->frame_rate.den * 2; + } outlink->w = inlink->w; outlink->h = inlink->h * 2; @@ -96,22 +99,36 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); for (i = 0; i < s->nb_planes; i++) { - av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field, - out->linesize[i] * 2, - in->data[i], in->linesize[i], - s->linesize[i], s->planeheight[i]); - av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field, - out->linesize[i] * 2, - s->prev->data[i], s->prev->linesize[i], - s->linesize[i], s->planeheight[i]); + if (s->double_weave && !(inlink->frame_count_out & 1)) { + av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field, + out->linesize[i] * 2, + in->data[i], in->linesize[i], + s->linesize[i], s->planeheight[i]); + av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field, + out->linesize[i] * 2, + s->prev->data[i], s->prev->linesize[i], + s->linesize[i], s->planeheight[i]); + } else { + av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field, + out->linesize[i] * 2, + in->data[i], in->linesize[i], + s->linesize[i], s->planeheight[i]); + av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field, + out->linesize[i] * 2, + s->prev->data[i], s->prev->linesize[i], + s->linesize[i], s->planeheight[i]); + } } - out->pts = in->pts / 2; + out->pts = s->double_weave ? s->prev->pts : in->pts / 2; out->interlaced_frame = 1; out->top_field_first = !s->first_field; - av_frame_free(&in); + if (!s->double_weave) + av_frame_free(&in); av_frame_free(&s->prev); + if (s->double_weave) + s->prev = in; return ff_filter_frame(outlink, out); } @@ -149,3 +166,27 @@ AVFilter ff_vf_weave = { .inputs = weave_inputs, .outputs = weave_outputs, }; + +static av_cold int init(AVFilterContext *ctx) +{ + WeaveContext *s = ctx->priv; + + if (!strcmp(ctx->filter->name, "doubleweave")) + s->double_weave = 1; + + return 0; +} + +#define doubleweave_options weave_options +AVFILTER_DEFINE_CLASS(doubleweave); + +AVFilter ff_vf_doubleweave = { + .name = "doubleweave", + .description = NULL_IF_CONFIG_SMALL("Weave input video fields into double number of frames."), + .priv_size = sizeof(WeaveContext), + .priv_class = &doubleweave_class, + .init = init, + .uninit = uninit, + .inputs = weave_inputs, + .outputs = weave_outputs, +};