Browse code

separatefields filter

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

Paul B Mahol authored on 2013/04/10 00:35:23
Showing 6 changed files
... ...
@@ -16,6 +16,7 @@ version <next>:
16 16
   filtergraph description to be read from a file
17 17
 - OpenCL support
18 18
 - audio phaser filter
19
+- separatefields filter
19 20
 
20 21
 
21 22
 version 1.2:
... ...
@@ -4896,6 +4896,16 @@ scale='min(500\, iw*3/2):-1'
4896 4896
 @end example
4897 4897
 @end itemize
4898 4898
 
4899
+@section separatefields
4900
+
4901
+The @code{separatefields} takes a frame-based video input and splits
4902
+each frame into its components fields, producing a new half height clip
4903
+with twice the frame rate and twice the frame count.
4904
+
4905
+This filter use field-dominance information in frame to decide which
4906
+of each pair of fields to place first in the output.
4907
+If it gets it wrong use @ref{setfield} filter before @code{separatefields} filter.
4908
+
4899 4909
 @section setdar, setsar
4900 4910
 
4901 4911
 The @code{setdar} filter sets the Display Aspect Ratio for the filter
... ...
@@ -4970,6 +4980,7 @@ To set a display aspect ratio of 16:9, and specify a maximum integer value of
4970 4970
 setdar=ratio='16:9':max=1000
4971 4971
 @end example
4972 4972
 
4973
+@anchor{setfield}
4973 4974
 @section setfield
4974 4975
 
4975 4976
 Force field for the output video frame.
... ...
@@ -148,6 +148,7 @@ OBJS-$(CONFIG_PERMS_FILTER)                  += f_perms.o
148 148
 OBJS-$(CONFIG_PIXDESCTEST_FILTER)            += vf_pixdesctest.o
149 149
 OBJS-$(CONFIG_PP_FILTER)                     += vf_pp.o
150 150
 OBJS-$(CONFIG_REMOVELOGO_FILTER)             += bbox.o lswsutils.o lavfutils.o vf_removelogo.o
151
+OBJS-$(CONFIG_SEPARATEFIELDS_FILTER)         += vf_separatefields.o
151 152
 OBJS-$(CONFIG_SCALE_FILTER)                  += vf_scale.o
152 153
 OBJS-$(CONFIG_SELECT_FILTER)                 += f_select.o
153 154
 OBJS-$(CONFIG_SENDCMD_FILTER)                += f_sendcmd.o
... ...
@@ -146,6 +146,7 @@ void avfilter_register_all(void)
146 146
     REGISTER_FILTER(SCALE,          scale,          vf);
147 147
     REGISTER_FILTER(SELECT,         select,         vf);
148 148
     REGISTER_FILTER(SENDCMD,        sendcmd,        vf);
149
+    REGISTER_FILTER(SEPARATEFIELDS, separatefields, vf);
149 150
     REGISTER_FILTER(SETDAR,         setdar,         vf);
150 151
     REGISTER_FILTER(SETFIELD,       setfield,       vf);
151 152
     REGISTER_FILTER(SETPTS,         setpts,         vf);
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/avutil.h"
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  3
32
-#define LIBAVFILTER_VERSION_MINOR  49
33
-#define LIBAVFILTER_VERSION_MICRO 101
32
+#define LIBAVFILTER_VERSION_MINOR  50
33
+#define LIBAVFILTER_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 36
                                                LIBAVFILTER_VERSION_MINOR, \
37 37
new file mode 100644
... ...
@@ -0,0 +1,110 @@
0
+/*
1
+ * Copyright (c) 2013 Paul B Mahol
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/pixdesc.h"
21
+#include "avfilter.h"
22
+#include "internal.h"
23
+
24
+typedef struct {
25
+    int nb_planes;
26
+    int64_t frame_count;
27
+    double ts_unit;
28
+} SeparateFieldsContext;
29
+
30
+static int config_props_output(AVFilterLink *outlink)
31
+{
32
+    AVFilterContext *ctx = outlink->src;
33
+    SeparateFieldsContext *sf = ctx->priv;
34
+    AVFilterLink *inlink = ctx->inputs[0];
35
+
36
+    sf->nb_planes = av_pix_fmt_count_planes(inlink->format);;
37
+
38
+    if (inlink->h & 1) {
39
+        av_log(ctx, AV_LOG_ERROR, "height must be even\n");
40
+        return AVERROR_INVALIDDATA;
41
+    }
42
+
43
+    outlink->frame_rate.num = inlink->frame_rate.num * 2;
44
+    outlink->frame_rate.den = inlink->frame_rate.den;
45
+    outlink->w = inlink->w;
46
+    outlink->h = inlink->h / 2;
47
+    sf->ts_unit = av_q2d(av_inv_q(av_mul_q(outlink->frame_rate, inlink->time_base)));
48
+
49
+    return 0;
50
+}
51
+
52
+static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
53
+{
54
+    AVFilterContext *ctx = inlink->dst;
55
+    SeparateFieldsContext *sf = ctx->priv;
56
+    AVFilterLink *outlink = ctx->outputs[0];
57
+    AVFrame *second;
58
+    int i, ret;
59
+
60
+    inpicref->height = outlink->h;
61
+    inpicref->interlaced_frame = 0;
62
+
63
+    second = av_frame_clone(inpicref);
64
+    if (!second)
65
+        return AVERROR(ENOMEM);
66
+
67
+    for (i = 0; i < sf->nb_planes; i++) {
68
+        if (!inpicref->top_field_first)
69
+            inpicref->data[i] = inpicref->data[i] + inpicref->linesize[i];
70
+        else
71
+            second->data[i] = second->data[i] + second->linesize[i];
72
+        inpicref->linesize[i] *= 2;
73
+        second->linesize[i]   *= 2;
74
+    }
75
+
76
+    inpicref->pts = sf->frame_count++ * sf->ts_unit;
77
+    second->pts   = sf->frame_count++ * sf->ts_unit;
78
+
79
+    ret = ff_filter_frame(outlink, inpicref);
80
+    if (ret < 0)
81
+        return ret;
82
+    return ff_filter_frame(outlink, second);
83
+}
84
+
85
+static const AVFilterPad separatefields_inputs[] = {
86
+    {
87
+        .name             = "default",
88
+        .type             = AVMEDIA_TYPE_VIDEO,
89
+        .filter_frame     = filter_frame,
90
+    },
91
+    { NULL }
92
+};
93
+
94
+static const AVFilterPad separatefields_outputs[] = {
95
+    {
96
+        .name          = "default",
97
+        .type          = AVMEDIA_TYPE_VIDEO,
98
+        .config_props  = config_props_output,
99
+    },
100
+    { NULL }
101
+};
102
+
103
+AVFilter avfilter_vf_separatefields = {
104
+    .name          = "separatefields",
105
+    .description   = NULL_IF_CONFIG_SMALL("Split input video frames into fields."),
106
+    .priv_size     = sizeof(SeparateFieldsContext),
107
+    .inputs        = separatefields_inputs,
108
+    .outputs       = separatefields_outputs,
109
+};