Libav
vf_fieldorder.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Mark Himsley
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "libavutil/imgutils.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/pixdesc.h"
33 #include "avfilter.h"
34 #include "formats.h"
35 #include "internal.h"
36 #include "video.h"
37 
38 typedef struct {
39  const AVClass *class;
40  int dst_tff;
41  int line_size[4];
43 
45 {
48  int ret;
49 
52  if (ctx->inputs[0]) {
53  formats = NULL;
54  for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) {
55  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
56  if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL ||
58  desc->nb_components && !desc->log2_chroma_h &&
59  (ret = ff_add_format(&formats, pix_fmt)) < 0) {
60  ff_formats_unref(&formats);
61  return ret;
62  }
63  }
64  ff_formats_ref(formats, &ctx->inputs[0]->out_formats);
65  ff_formats_ref(formats, &ctx->outputs[0]->in_formats);
66  }
67 
68  return 0;
69 }
70 
71 static int config_input(AVFilterLink *inlink)
72 {
73  AVFilterContext *ctx = inlink->dst;
74  FieldOrderContext *s = ctx->priv;
75  int plane;
76 
79  for (plane = 0; plane < 4; plane++) {
80  s->line_size[plane] = av_image_get_linesize(inlink->format, inlink->w,
81  plane);
82  }
83 
84  return 0;
85 }
86 
87 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
88 {
89  AVFilterContext *ctx = inlink->dst;
90  FieldOrderContext *s = ctx->priv;
91  AVFilterLink *outlink = ctx->outputs[0];
92  int h, plane, line_step, line_size, line;
93  uint8_t *data;
94 
95  if (!frame->interlaced_frame ||
96  frame->top_field_first == s->dst_tff) {
98  "Skipping %s.\n",
99  frame->interlaced_frame ?
100  "frame with same field order" : "progressive frame");
101  return ff_filter_frame(outlink, frame);
102  }
103 
104  av_dlog(ctx,
105  "picture will move %s one line\n",
106  s->dst_tff ? "up" : "down");
107  h = frame->height;
108  for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
109  line_step = frame->linesize[plane];
110  line_size = s->line_size[plane];
111  data = frame->data[plane];
112  if (s->dst_tff) {
118  for (line = 0; line < h; line++) {
119  if (1 + line < frame->height) {
120  memcpy(data, data + line_step, line_size);
121  } else {
122  memcpy(data, data - line_step - line_step, line_size);
123  }
124  data += line_step;
125  }
126  } else {
132  data += (h - 1) * line_step;
133  for (line = h - 1; line >= 0 ; line--) {
134  if (line > 0) {
135  memcpy(data, data - line_step, line_size);
136  } else {
137  memcpy(data, data + line_step + line_step, line_size);
138  }
139  data -= line_step;
140  }
141  }
142  }
143  frame->top_field_first = s->dst_tff;
144 
145  return ff_filter_frame(outlink, frame);
146 }
147 
148 #define OFFSET(x) offsetof(FieldOrderContext, x)
149 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM
150 static const AVOption options[] = {
151  { "order", "output field order", OFFSET(dst_tff), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "order" },
152  { "bff", "bottom field first", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .unit = "order" },
153  { "tff", "top field first", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .unit = "order" },
154  { NULL },
155 };
156 
157 static const AVClass fieldorder_class = {
158  .class_name = "fieldorder",
159  .item_name = av_default_item_name,
160  .option = options,
161  .version = LIBAVUTIL_VERSION_INT,
162 };
163 
165  {
166  .name = "default",
167  .type = AVMEDIA_TYPE_VIDEO,
168  .config_props = config_input,
169  .filter_frame = filter_frame,
170  .needs_writable = 1,
171  },
172  { NULL }
173 };
174 
176  {
177  .name = "default",
178  .type = AVMEDIA_TYPE_VIDEO,
179  },
180  { NULL }
181 };
182 
184  .name = "fieldorder",
185  .description = NULL_IF_CONFIG_SMALL("Set the field order."),
186  .priv_size = sizeof(FieldOrderContext),
187  .priv_class = &fieldorder_class,
189  .inputs = avfilter_vf_fieldorder_inputs,
190  .outputs = avfilter_vf_fieldorder_outputs,
191 };