Browse code

avfilter: add doubleweave filter

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2017/04/22 20:07:33
Showing 6 changed files
... ...
@@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
3 3
 
4 4
 version <next>:
5 5
 - deflicker video filter
6
+- doubleweave video filter
6 7
 
7 8
 version 3.3:
8 9
 - CrystalHD decoder moved to new decode API
... ...
@@ -14659,12 +14659,15 @@ Default is digital.
14659 14659
 Set background opacity.
14660 14660
 @end table
14661 14661
 
14662
-@section weave
14662
+@section weave, doubleweave
14663 14663
 
14664 14664
 The @code{weave} takes a field-based video input and join
14665 14665
 each two sequential fields into single frame, producing a new double
14666 14666
 height clip with half the frame rate and half the frame count.
14667 14667
 
14668
+The @code{doubleweave} works same as @code{weave} but without
14669
+halving frame rate and frame count.
14670
+
14668 14671
 It accepts the following option:
14669 14672
 
14670 14673
 @table @option
... ...
@@ -164,6 +164,7 @@ OBJS-$(CONFIG_DESHAKE_FILTER)                += vf_deshake.o
164 164
 OBJS-$(CONFIG_DETELECINE_FILTER)             += vf_detelecine.o
165 165
 OBJS-$(CONFIG_DILATION_FILTER)               += vf_neighbor.o
166 166
 OBJS-$(CONFIG_DISPLACE_FILTER)               += vf_displace.o framesync.o
167
+OBJS-$(CONFIG_DOUBLEWEAVE_FILTER)            += vf_weave.o
167 168
 OBJS-$(CONFIG_DRAWBOX_FILTER)                += vf_drawbox.o
168 169
 OBJS-$(CONFIG_DRAWGRAPH_FILTER)              += f_drawgraph.o
169 170
 OBJS-$(CONFIG_DRAWGRID_FILTER)               += vf_drawbox.o
... ...
@@ -175,6 +175,7 @@ static void register_all(void)
175 175
     REGISTER_FILTER(DETELECINE,     detelecine,     vf);
176 176
     REGISTER_FILTER(DILATION,       dilation,       vf);
177 177
     REGISTER_FILTER(DISPLACE,       displace,       vf);
178
+    REGISTER_FILTER(DOUBLEWEAVE,    doubleweave,    vf);
178 179
     REGISTER_FILTER(DRAWBOX,        drawbox,        vf);
179 180
     REGISTER_FILTER(DRAWGRAPH,      drawgraph,      vf);
180 181
     REGISTER_FILTER(DRAWGRID,       drawgrid,       vf);
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFILTER_VERSION_MAJOR   6
33
-#define LIBAVFILTER_VERSION_MINOR  85
33
+#define LIBAVFILTER_VERSION_MINOR  86
34 34
 #define LIBAVFILTER_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
... ...
@@ -27,6 +27,7 @@
27 27
 typedef struct WeaveContext {
28 28
     const AVClass *class;
29 29
     int first_field;
30
+    int double_weave;
30 31
     int nb_planes;
31 32
     int planeheight[4];
32 33
     int linesize[4];
... ...
@@ -56,10 +57,12 @@ static int config_props_output(AVFilterLink *outlink)
56 56
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
57 57
     int ret;
58 58
 
59
-    outlink->time_base.num = inlink->time_base.num * 2;
60
-    outlink->time_base.den = inlink->time_base.den;
61
-    outlink->frame_rate.num = inlink->frame_rate.num;
62
-    outlink->frame_rate.den = inlink->frame_rate.den * 2;
59
+    if (!s->double_weave) {
60
+        outlink->time_base.num = inlink->time_base.num * 2;
61
+        outlink->time_base.den = inlink->time_base.den;
62
+        outlink->frame_rate.num = inlink->frame_rate.num;
63
+        outlink->frame_rate.den = inlink->frame_rate.den * 2;
64
+    }
63 65
     outlink->w = inlink->w;
64 66
     outlink->h = inlink->h * 2;
65 67
 
... ...
@@ -96,22 +99,36 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
96 96
     av_frame_copy_props(out, in);
97 97
 
98 98
     for (i = 0; i < s->nb_planes; i++) {
99
-        av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field,
100
-                            out->linesize[i] * 2,
101
-                            in->data[i], in->linesize[i],
102
-                            s->linesize[i], s->planeheight[i]);
103
-        av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field,
104
-                            out->linesize[i] * 2,
105
-                            s->prev->data[i], s->prev->linesize[i],
106
-                            s->linesize[i], s->planeheight[i]);
99
+        if (s->double_weave && !(inlink->frame_count_out & 1)) {
100
+            av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field,
101
+                                out->linesize[i] * 2,
102
+                                in->data[i], in->linesize[i],
103
+                                s->linesize[i], s->planeheight[i]);
104
+            av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field,
105
+                                out->linesize[i] * 2,
106
+                                s->prev->data[i], s->prev->linesize[i],
107
+                                s->linesize[i], s->planeheight[i]);
108
+        } else {
109
+            av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field,
110
+                                out->linesize[i] * 2,
111
+                                in->data[i], in->linesize[i],
112
+                                s->linesize[i], s->planeheight[i]);
113
+            av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field,
114
+                                out->linesize[i] * 2,
115
+                                s->prev->data[i], s->prev->linesize[i],
116
+                                s->linesize[i], s->planeheight[i]);
117
+        }
107 118
     }
108 119
 
109
-    out->pts = in->pts / 2;
120
+    out->pts = s->double_weave ? s->prev->pts : in->pts / 2;
110 121
     out->interlaced_frame = 1;
111 122
     out->top_field_first = !s->first_field;
112 123
 
113
-    av_frame_free(&in);
124
+    if (!s->double_weave)
125
+        av_frame_free(&in);
114 126
     av_frame_free(&s->prev);
127
+    if (s->double_weave)
128
+        s->prev = in;
115 129
     return ff_filter_frame(outlink, out);
116 130
 }
117 131
 
... ...
@@ -149,3 +166,27 @@ AVFilter ff_vf_weave = {
149 149
     .inputs        = weave_inputs,
150 150
     .outputs       = weave_outputs,
151 151
 };
152
+
153
+static av_cold int init(AVFilterContext *ctx)
154
+{
155
+    WeaveContext *s = ctx->priv;
156
+
157
+    if (!strcmp(ctx->filter->name, "doubleweave"))
158
+        s->double_weave = 1;
159
+
160
+    return 0;
161
+}
162
+
163
+#define doubleweave_options weave_options
164
+AVFILTER_DEFINE_CLASS(doubleweave);
165
+
166
+AVFilter ff_vf_doubleweave = {
167
+    .name          = "doubleweave",
168
+    .description   = NULL_IF_CONFIG_SMALL("Weave input video fields into double number of frames."),
169
+    .priv_size     = sizeof(WeaveContext),
170
+    .priv_class    = &doubleweave_class,
171
+    .init          = init,
172
+    .uninit        = uninit,
173
+    .inputs        = weave_inputs,
174
+    .outputs       = weave_outputs,
175
+};