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 /* #define DEBUG */
27 
28 #include "libavutil/imgutils.h"
29 #include "libavutil/pixdesc.h"
30 #include "avfilter.h"
31 
32 typedef struct
33 {
34  unsigned int dst_tff;
35  int line_size[4];
37 
38 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
39 {
40  FieldOrderContext *fieldorder = ctx->priv;
41 
42  const char *tff = "tff";
43  const char *bff = "bff";
44 
45  if (!args) {
46  fieldorder->dst_tff = 1;
47  } else if (sscanf(args, "%u", &fieldorder->dst_tff) == 1) {
48  fieldorder->dst_tff = !!fieldorder->dst_tff;
49  } else if (!strcmp(tff, args)) {
50  fieldorder->dst_tff = 1;
51  } else if (!strcmp(bff, args)) {
52  fieldorder->dst_tff = 0;
53  } else {
54  av_log(ctx, AV_LOG_ERROR, "Invalid argument '%s'.\n", args);
55  return AVERROR(EINVAL);
56  }
57 
58  av_log(ctx, AV_LOG_INFO, "output field order: %s\n",
59  fieldorder->dst_tff ? tff : bff);
60 
61  return 0;
62 }
63 
65 {
66  AVFilterFormats *formats;
67  enum PixelFormat pix_fmt;
68  int ret;
69 
72  if (ctx->inputs[0]) {
73  formats = NULL;
74  for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++)
77  && av_pix_fmt_descriptors[pix_fmt].nb_components
78  && !av_pix_fmt_descriptors[pix_fmt].log2_chroma_h
79  && (ret = avfilter_add_format(&formats, pix_fmt)) < 0) {
80  avfilter_formats_unref(&formats);
81  return ret;
82  }
83  avfilter_formats_ref(formats, &ctx->inputs[0]->out_formats);
84  avfilter_formats_ref(formats, &ctx->outputs[0]->in_formats);
85  }
86 
87  return 0;
88 }
89 
90 static int config_input(AVFilterLink *inlink)
91 {
92  AVFilterContext *ctx = inlink->dst;
93  FieldOrderContext *fieldorder = ctx->priv;
94  int plane;
95 
98  for (plane = 0; plane < 4; plane++) {
99  fieldorder->line_size[plane] = av_image_get_linesize(
100  inlink->format,
101  inlink->w,
102  plane);
103  }
104 
105  return 0;
106 }
107 
108 static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int w, int h)
109 {
110  AVFilterContext *ctx = inlink->dst;
111  AVFilterLink *outlink = ctx->outputs[0];
112 
113  return avfilter_get_video_buffer(outlink, perms, w, h);
114 }
115 
116 static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
117 {
118  AVFilterContext *ctx = inlink->dst;
119  AVFilterLink *outlink = ctx->outputs[0];
120 
121  AVFilterBufferRef *outpicref;
122 
123  outpicref = avfilter_ref_buffer(inpicref, ~0);
124  outlink->out_buf = outpicref;
125 
126  avfilter_start_frame(outlink, outpicref);
127 }
128 
129 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
130 {
131  AVFilterContext *ctx = inlink->dst;
132  FieldOrderContext *fieldorder = ctx->priv;
133  AVFilterLink *outlink = ctx->outputs[0];
134 
135  AVFilterBufferRef *inpicref = inlink->cur_buf;
136 
141  if ( !inpicref->video->interlaced
142  || inpicref->video->top_field_first == fieldorder->dst_tff) {
143  avfilter_draw_slice(outlink, y, h, slice_dir);
144  }
145 }
146 
147 static void end_frame(AVFilterLink *inlink)
148 {
149  AVFilterContext *ctx = inlink->dst;
150  FieldOrderContext *fieldorder = ctx->priv;
151  AVFilterLink *outlink = ctx->outputs[0];
152 
153  AVFilterBufferRef *inpicref = inlink->cur_buf;
154  AVFilterBufferRef *outpicref = outlink->out_buf;
155 
156  int h, plane, line_step, line_size, line;
157  uint8_t *cpy_src, *cpy_dst;
158 
159  if ( inpicref->video->interlaced
160  && inpicref->video->top_field_first != fieldorder->dst_tff) {
161  av_dlog(ctx,
162  "picture will move %s one line\n",
163  fieldorder->dst_tff ? "up" : "down");
164  h = inpicref->video->h;
165  for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) {
166  line_step = inpicref->linesize[plane];
167  line_size = fieldorder->line_size[plane];
168  cpy_src = inpicref->data[plane];
169  cpy_dst = outpicref->data[plane];
170  if (fieldorder->dst_tff) {
176  for (line = 0; line < h; line++) {
177  if (1 + line < outpicref->video->h) {
178  memcpy(cpy_dst, cpy_src + line_step, line_size);
179  } else {
180  memcpy(cpy_dst, cpy_src - line_step - line_step, line_size);
181  }
182  cpy_src += line_step;
183  cpy_dst += line_step;
184  }
185  } else {
191  cpy_src += (h - 1) * line_step;
192  cpy_dst += (h - 1) * line_step;
193  for (line = h - 1; line >= 0 ; line--) {
194  if (line > 0) {
195  memcpy(cpy_dst, cpy_src - line_step, line_size);
196  } else {
197  memcpy(cpy_dst, cpy_src + line_step + line_step, line_size);
198  }
199  cpy_src -= line_step;
200  cpy_dst -= line_step;
201  }
202  }
203  }
204  outpicref->video->top_field_first = fieldorder->dst_tff;
205  avfilter_draw_slice(outlink, 0, h, 1);
206  } else {
207  av_dlog(ctx,
208  "not interlaced or field order already correct\n");
209  }
210 
211  avfilter_end_frame(outlink);
212  avfilter_unref_buffer(inpicref);
213 }
214 
216  .name = "fieldorder",
217  .description = NULL_IF_CONFIG_SMALL("Set the field order."),
218  .init = init,
219  .priv_size = sizeof(FieldOrderContext),
221  .inputs = (AVFilterPad[]) {{ .name = "default",
222  .type = AVMEDIA_TYPE_VIDEO,
223  .config_props = config_input,
224  .start_frame = start_frame,
225  .get_video_buffer = get_video_buffer,
226  .draw_slice = draw_slice,
227  .end_frame = end_frame,
228  .min_perms = AV_PERM_READ,
229  .rej_perms = AV_PERM_REUSE2|AV_PERM_PRESERVE,},
230  { .name = NULL}},
231  .outputs = (AVFilterPad[]) {{ .name = "default",
232  .type = AVMEDIA_TYPE_VIDEO, },
233  { .name = NULL}},
234 };
AVFilterBufferRef * avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: avfilter.c:289
AVFilterBufferRefVideoProps * video
video buffer specific properties
Definition: avfilter.h:141
int linesize[8]
number of bytes per line
Definition: avfilter.h:127
misc image utilities
enum PixelFormat pix_fmt
Definition: v4l.c:65
number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of...
Definition: pixfmt.h:160
static int query_formats(AVFilterContext *ctx)
Definition: vf_fieldorder.c:64
static void end_frame(AVFilterLink *inlink)
#define AV_PERM_READ
can read from the buffer
Definition: avfilter.h:81
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:547
static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
#define av_cold
Definition: attributes.h:71
int top_field_first
field order
Definition: avfilter.h:111
void avfilter_end_frame(AVFilterLink *link)
Notifie the next filter that the current frame has finished.
Definition: avfilter.c:430
int avfilter_add_format(AVFilterFormats **avff, int fmt)
Add fmt to the list of media formats contained in *avff.
Definition: formats.c:107
static int flags
Definition: log.c:34
A filter pad used for either input or output.
Definition: avfilter.h:312
int line_size[4]
bytes of pixel data per line for each plane
Definition: vf_fieldorder.c:35
int h
image height
Definition: avfilter.h:108
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:191
void * priv
private data for use by the filter
Definition: avfilter.h:553
Definition: graph2dot.c:39
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:140
const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB]
The array of all the pixel format descriptors.
Definition: pixdesc.c:119
int av_image_get_linesize(enum PixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane...
Definition: imgutils.c:47
AVFilter avfilter_vf_fieldorder
#define PIX_FMT_BITSTREAM
All values of a component are bit-wise packed end to end.
Definition: pixdesc.h:88
void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
Send a slice to the next filter.
Definition: avfilter.c:447
#define av_dlog(pctx,...)
av_dlog macros Useful to print debug messages that shouldn't get compiled in normally.
Definition: log.h:158
void avfilter_unref_buffer(AVFilterBufferRef *ref)
Remove a reference to a buffer.
Definition: avfilter.c:73
A reference to an AVFilterBuffer.
Definition: avfilter.h:124
#define PIX_FMT_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:89
NULL
Definition: eval.c:50
void avfilter_formats_ref(AVFilterFormats *formats, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:139
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:111
Filter definition.
Definition: avfilter.h:497
AVFilterBufferRef * avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
Add a new reference to a buffer.
Definition: avfilter.c:47
void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
Notify the next filter of the start of a frame.
Definition: avfilter.c:400
const char * name
filter name
Definition: avfilter.h:498
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:551
#define AV_PERM_PRESERVE
nobody else can overwrite the buffer
Definition: avfilter.h:83
PixelFormat
Pixel format.
Definition: pixfmt.h:62
static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
static AVFilterBufferRef * get_video_buffer(AVFilterLink *inlink, int perms, int w, int h)
int interlaced
is frame interlaced
Definition: avfilter.h:110
unsigned int dst_tff
output bff/tff
Definition: vf_fieldorder.c:34
#define AV_PERM_REUSE2
can output the buffer multiple times, modified each time
Definition: avfilter.h:85
static int config_input(AVFilterLink *inlink)
Definition: vf_fieldorder.c:90
void avfilter_formats_unref(AVFilterFormats **ref)
If *ref is non-NULL, remove *ref as a reference to the format list it currently points to...
Definition: formats.c:155
uint8_t * data[8]
picture/audio data for each plane
Definition: avfilter.h:126
A list of supported formats for one end of a filter link.
Definition: avfilter.h:220
An instance of a filter.
Definition: avfilter.h:538
#define AV_LOG_INFO
Definition: log.h:119
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
Definition: vf_fieldorder.c:38