2 * Copyright (c) 2003 Rich Felker
3 * Copyright (c) 2012 Stefano Sabatini
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * field filter, based on libmpcodecs/vf_field.c by Rich Felker
27 #include "libavutil/opt.h"
28 #include "libavutil/pixdesc.h"
32 enum FieldType
{ FIELD_TYPE_TOP
= 0, FIELD_TYPE_BOTTOM
};
34 typedef struct FieldContext
{
36 int type
; ///< FieldType
37 int nb_planes
; ///< number of planes of the current format
40 #define OFFSET(x) offsetof(FieldContext, x)
41 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
43 static const AVOption field_options
[] = {
44 {"type", "set field type (top or bottom)", OFFSET(type
), AV_OPT_TYPE_INT
, {.i64
=FIELD_TYPE_TOP
}, 0, 1, FLAGS
, .unit
= "field_type" },
45 {"top", "select top field", 0, AV_OPT_TYPE_CONST
, {.i64
=FIELD_TYPE_TOP
}, INT_MIN
, INT_MAX
, FLAGS
, .unit
= "field_type"},
46 {"bottom", "select bottom field", 0, AV_OPT_TYPE_CONST
, {.i64
=FIELD_TYPE_BOTTOM
}, INT_MIN
, INT_MAX
, FLAGS
, .unit
= "field_type"},
50 AVFILTER_DEFINE_CLASS(field
);
52 static int config_props_output(AVFilterLink
*outlink
)
54 AVFilterContext
*ctx
= outlink
->src
;
55 FieldContext
*field
= ctx
->priv
;
56 AVFilterLink
*inlink
= ctx
->inputs
[0];
58 field
->nb_planes
= av_pix_fmt_count_planes(outlink
->format
);
60 outlink
->w
= inlink
->w
;
61 outlink
->h
= (inlink
->h
+ (field
->type
== FIELD_TYPE_TOP
)) / 2;
63 av_log(ctx
, AV_LOG_VERBOSE
, "w:%d h:%d type:%s -> w:%d h:%d\n",
64 inlink
->w
, inlink
->h
, field
->type
== FIELD_TYPE_BOTTOM
? "bottom" : "top",
65 outlink
->w
, outlink
->h
);
69 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*inpicref
)
71 FieldContext
*field
= inlink
->dst
->priv
;
72 AVFilterLink
*outlink
= inlink
->dst
->outputs
[0];
75 inpicref
->height
= outlink
->h
;
76 #if FF_API_INTERLACED_FRAME
77 FF_DISABLE_DEPRECATION_WARNINGS
78 inpicref
->interlaced_frame
= 0;
79 FF_ENABLE_DEPRECATION_WARNINGS
81 inpicref
->flags
&= ~AV_FRAME_FLAG_INTERLACED
;
83 for (i
= 0; i
< field
->nb_planes
; i
++) {
84 if (field
->type
== FIELD_TYPE_BOTTOM
)
85 inpicref
->data
[i
] = inpicref
->data
[i
] + inpicref
->linesize
[i
];
86 inpicref
->linesize
[i
] = 2 * inpicref
->linesize
[i
];
88 return ff_filter_frame(outlink
, inpicref
);
91 static const AVFilterPad field_inputs
[] = {
94 .type
= AVMEDIA_TYPE_VIDEO
,
95 .filter_frame
= filter_frame
,
99 static const AVFilterPad field_outputs
[] = {
102 .type
= AVMEDIA_TYPE_VIDEO
,
103 .config_props
= config_props_output
,
107 const FFFilter ff_vf_field
= {
109 .p
.description
= NULL_IF_CONFIG_SMALL("Extract a field from the input video."),
110 .p
.priv_class
= &field_class
,
111 .priv_size
= sizeof(FieldContext
),
112 FILTER_INPUTS(field_inputs
),
113 FILTER_OUTPUTS(field_outputs
),