vf_idet.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <float.h> /* FLT_MAX */
22 
23 #include "libavutil/cpu.h"
24 #include "libavutil/common.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/pixdesc.h"
27 #include "avfilter.h"
28 #include "internal.h"
29 
30 #define HIST_SIZE 4
31 
32 typedef enum {
33  TFF,
34  BFF,
37 } Type;
38 
39 typedef struct {
40  const AVClass *class;
43 
45  int prestat[4];
46  int poststat[4];
47 
49 
53  int (*filter_line)(const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w);
54 
56 } IDETContext;
57 
58 #define OFFSET(x) offsetof(IDETContext, x)
59 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
60 
61 static const AVOption idet_options[] = {
62  { "intl_thres", "set interlacing threshold", OFFSET(interlace_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 1.04}, -1, FLT_MAX, FLAGS },
63  { "prog_thres", "set progressive threshold", OFFSET(progressive_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 1.5}, -1, FLT_MAX, FLAGS },
64  { NULL }
65 };
66 
68 
69 static const char *type2str(Type type)
70 {
71  switch(type) {
72  case TFF : return "Top Field First ";
73  case BFF : return "Bottom Field First";
74  case PROGRSSIVE : return "Progressive ";
75  case UNDETERMINED: return "Undetermined ";
76  }
77  return NULL;
78 }
79 
80 static int filter_line_c(const uint8_t *a, const uint8_t *b, const uint8_t *c, int w)
81 {
82  int x;
83  int ret=0;
84 
85  for(x=0; x<w; x++){
86  int v = (*a++ + *c++) - 2 * *b++;
87  ret += FFABS(v);
88  }
89 
90  return ret;
91 }
92 
93 static int filter_line_c_16bit(const uint16_t *a, const uint16_t *b, const uint16_t *c, int w)
94 {
95  int x;
96  int ret=0;
97 
98  for(x=0; x<w; x++){
99  int v = (*a++ + *c++) - 2 * *b++;
100  ret += FFABS(v);
101  }
102 
103  return ret;
104 }
105 
106 static void filter(AVFilterContext *ctx)
107 {
108  IDETContext *idet = ctx->priv;
109  int y, i;
110  int64_t alpha[2]={0};
111  int64_t delta=0;
112  Type type, best_type;
113  int match = 0;
114 
115  for (i = 0; i < idet->csp->nb_components; i++) {
116  int w = idet->cur->width;
117  int h = idet->cur->height;
118  int refs = idet->cur->linesize[i];
119 
120  if (i && i<3) {
121  w >>= idet->csp->log2_chroma_w;
122  h >>= idet->csp->log2_chroma_h;
123  }
124 
125  for (y = 2; y < h - 2; y++) {
126  uint8_t *prev = &idet->prev->data[i][y*refs];
127  uint8_t *cur = &idet->cur ->data[i][y*refs];
128  uint8_t *next = &idet->next->data[i][y*refs];
129  alpha[ y &1] += idet->filter_line(cur-refs, prev, cur+refs, w);
130  alpha[(y^1)&1] += idet->filter_line(cur-refs, next, cur+refs, w);
131  delta += idet->filter_line(cur-refs, cur, cur+refs, w);
132  }
133  }
134 
135  if (alpha[0] > idet->interlace_threshold * alpha[1]){
136  type = TFF;
137  }else if(alpha[1] > idet->interlace_threshold * alpha[0]){
138  type = BFF;
139  }else if(alpha[1] > idet->progressive_threshold * delta){
140  type = PROGRSSIVE;
141  }else{
142  type = UNDETERMINED;
143  }
144 
145  memmove(idet->history+1, idet->history, HIST_SIZE-1);
146  idet->history[0] = type;
147  best_type = UNDETERMINED;
148  for(i=0; i<HIST_SIZE; i++){
149  if(idet->history[i] != UNDETERMINED){
150  if(best_type == UNDETERMINED)
151  best_type = idet->history[i];
152 
153  if(idet->history[i] == best_type) {
154  match++;
155  }else{
156  match=0;
157  break;
158  }
159  }
160  }
161  if(idet->last_type == UNDETERMINED){
162  if(match ) idet->last_type = best_type;
163  }else{
164  if(match>2) idet->last_type = best_type;
165  }
166 
167  if (idet->last_type == TFF){
168  idet->cur->top_field_first = 1;
169  idet->cur->interlaced_frame = 1;
170  }else if(idet->last_type == BFF){
171  idet->cur->top_field_first = 0;
172  idet->cur->interlaced_frame = 1;
173  }else if(idet->last_type == PROGRSSIVE){
174  idet->cur->interlaced_frame = 0;
175  }
176 
177  idet->prestat [ type] ++;
178  idet->poststat[idet->last_type] ++;
179  av_log(ctx, AV_LOG_DEBUG, "Single frame:%s, Multi frame:%s\n", type2str(type), type2str(idet->last_type));
180 }
181 
182 static int filter_frame(AVFilterLink *link, AVFrame *picref)
183 {
184  AVFilterContext *ctx = link->dst;
185  IDETContext *idet = ctx->priv;
186 
187  if (idet->prev)
188  av_frame_free(&idet->prev);
189  idet->prev = idet->cur;
190  idet->cur = idet->next;
191  idet->next = picref;
192 
193  if (!idet->cur)
194  return 0;
195 
196  if (!idet->prev)
197  idet->prev = av_frame_clone(idet->cur);
198 
199  if (!idet->csp)
200  idet->csp = av_pix_fmt_desc_get(link->format);
201  if (idet->csp->comp[0].depth_minus1 / 8 == 1)
202  idet->filter_line = (void*)filter_line_c_16bit;
203 
204  filter(ctx);
205 
206  return ff_filter_frame(ctx->outputs[0], av_frame_clone(idet->cur));
207 }
208 
210 {
211  AVFilterContext *ctx = link->src;
212  IDETContext *idet = ctx->priv;
213 
214  do {
215  int ret;
216 
217  if ((ret = ff_request_frame(link->src->inputs[0])))
218  return ret;
219  } while (!idet->cur);
220 
221  return 0;
222 }
223 
224 static av_cold void uninit(AVFilterContext *ctx)
225 {
226  IDETContext *idet = ctx->priv;
227 
228  av_log(ctx, AV_LOG_INFO, "Single frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
229  idet->prestat[TFF],
230  idet->prestat[BFF],
231  idet->prestat[PROGRSSIVE],
232  idet->prestat[UNDETERMINED]
233  );
234  av_log(ctx, AV_LOG_INFO, "Multi frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
235  idet->poststat[TFF],
236  idet->poststat[BFF],
237  idet->poststat[PROGRSSIVE],
238  idet->poststat[UNDETERMINED]
239  );
240 
241  av_frame_free(&idet->prev);
242  av_frame_free(&idet->cur );
243  av_frame_free(&idet->next);
244 }
245 
247 {
248  static const enum AVPixelFormat pix_fmts[] = {
269  };
270 
272 
273  return 0;
274 }
275 
276 static av_cold int init(AVFilterContext *ctx)
277 {
278  IDETContext *idet = ctx->priv;
279 
280  idet->last_type = UNDETERMINED;
281  memset(idet->history, UNDETERMINED, HIST_SIZE);
282 
283  idet->filter_line = filter_line_c;
284 
285  return 0;
286 }
287 
288 
289 static const AVFilterPad idet_inputs[] = {
290  {
291  .name = "default",
292  .type = AVMEDIA_TYPE_VIDEO,
293  .filter_frame = filter_frame,
294  },
295  { NULL }
296 };
297 
298 static const AVFilterPad idet_outputs[] = {
299  {
300  .name = "default",
301  .type = AVMEDIA_TYPE_VIDEO,
302  .request_frame = request_frame,
303  },
304  { NULL }
305 };
306 
308  .name = "idet",
309  .description = NULL_IF_CONFIG_SMALL("Interlace detect Filter."),
310 
311  .priv_size = sizeof(IDETContext),
312  .init = init,
313  .uninit = uninit,
315  .inputs = idet_inputs,
316  .outputs = idet_outputs,
317  .priv_class = &idet_class,
318 };
static void filter(AVFilterContext *ctx)
Definition: vf_idet.c:106
float v
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:1778
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
int prestat[4]
Definition: vf_idet.c:45
AVOption.
Definition: opt.h:251
static const char * type2str(Type type)
Definition: vf_idet.c:69
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:151
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:73
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:117
external API header
static int query_formats(AVFilterContext *ctx)
Definition: vf_idet.c:246
static const AVFilterPad idet_inputs[]
Definition: vf_idet.c:289
#define FLAGS
Definition: vf_idet.c:59
float interlace_threshold
Definition: vf_idet.c:41
const AVPixFmtDescriptor * csp
Definition: vf_idet.c:55
planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:128
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:66
output residual component w
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
static const AVFilterPad idet_outputs[]
Definition: vf_idet.c:298
float progressive_threshold
Definition: vf_idet.c:42
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:532
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:105
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:86
uint8_t
it can be given away to ff_start_frame *A reference passed to ff_filter_frame(or the deprecated ff_start_frame) is given away and must no longer be used.*A reference created with avfilter_ref_buffer belongs to the code that created it.*A reference obtained with ff_get_video_buffer or ff_get_audio_buffer belongs to the code that requested it.*A reference given as return value by the get_video_buffer or get_audio_buffer method is given away and must no longer be used.Link reference fields---------------------The AVFilterLink structure has a few AVFilterBufferRef fields.The cur_buf and out_buf were used with the deprecated start_frame/draw_slice/end_frame API and should no longer be used.src_buf
#define av_cold
Definition: attributes.h:78
float delta
AVOptions.
AVFilter avfilter_vf_idet
Definition: vf_idet.c:307
#define b
Definition: input.c:42
#define AV_NE(be, le)
Definition: common.h:44
static const AVOption idet_options[]
Definition: vf_idet.c:61
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range ...
Definition: pixfmt.h:104
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_...
Definition: pixfmt.h:81
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:270
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:545
int poststat[4]
Definition: vf_idet.c:46
Definition: vf_idet.c:34
A filter pad used for either input or output.
Discrete Time axis x
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:157
uint16_t depth_minus1
number of bits in the component minus 1
Definition: pixdesc.h:43
static double alpha(void *priv, double x, double y)
Definition: vf_geq.c:86
int width
width and height of the video frame
Definition: frame.h:122
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:75
uint8_t history[HIST_SIZE]
Definition: vf_idet.c:48
planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
Definition: pixfmt.h:133
AVFrame * next
Definition: vf_idet.c:51
AVFILTER_DEFINE_CLASS(idet)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
Definition: avfilter.h:545
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:153
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
Definition: pixfmt.h:131
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a link
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:72
static int filter_line_c(const uint8_t *a, const uint8_t *b, const uint8_t *c, int w)
Definition: vf_idet.c:80
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:57
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_...
Definition: pixfmt.h:80
ret
Definition: avfilter.c:821
#define FFABS(a)
Definition: common.h:53
Type
Definition: vf_idet.c:32
#define HIST_SIZE
Definition: vf_idet.c:30
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
Definition: pixfmt.h:150
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_idet.c:224
AVFrame * av_frame_clone(AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:317
NULL
Definition: eval.c:55
planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
Definition: pixfmt.h:129
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip please avoid problems through this extra level of scrutiny For cosmetics only commits you should e g by running git config global user name My Name git config global user email my email which is either set in your personal configuration file through git config core editor or set by one of the following environment VISUAL or EDITOR Log messages should be concise but descriptive Explain why you made a what you did will be obvious from the changes themselves most of the time Saying just bug fix or is bad Remember that people of varying skill levels look at and educate themselves while reading through your code Don t include filenames in log Git provides that information Possibly make the commit message have a descriptive first an empty line and then a full description The first line will be used to name the patch by git format patch Renaming moving copying files or contents of making those normal commits mv cp path file otherpath otherfile git add[-A] git commit Do not rename or copy files of which you are not the maintainer without discussing it on the mailing list first Reverting broken commits git revert< commit > git revert will generate a revert commit This will not make the faulty commit disappear from the history git reset< commit > git reset will uncommit the changes till< commit > rewriting the current branch history git commit amend allows to amend the last commit details quickly git rebase i origin master will replay local commits over the main repository allowing to merge or remove some of them in the process Note that the commit amend and rebase rewrite history
Definition: git-howto.txt:153
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:55
#define OFFSET(x)
Definition: vf_idet.c:58
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:74
Describe the class of an AVClass context structure.
Definition: log.h:50
Filter definition.
Definition: avfilter.h:436
Y , 16bpp, big-endian.
Definition: pixfmt.h:101
synthesis window for stochastic i
const char * name
filter name
Definition: avfilter.h:437
#define type
Type last_type
Definition: vf_idet.c:44
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
static int request_frame(AVFilterLink *link)
Definition: vf_idet.c:209
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:132
int(* filter_line)(const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w)
Definition: vf_idet.c:53
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
Y , 8bpp.
Definition: pixfmt.h:76
AVFrame * cur
Definition: vf_idet.c:50
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
common internal and external API header
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
static double c[64]
planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:130
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_...
Definition: pixfmt.h:82
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:75
function y
Definition: D.m:1
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:275
static int filter_frame(AVFilterLink *link, AVFrame *picref)
Definition: vf_idet.c:182
Y , 16bpp, little-endian.
Definition: pixfmt.h:102
static int filter_line_c_16bit(const uint16_t *a, const uint16_t *b, const uint16_t *c, int w)
Definition: vf_idet.c:93
An instance of a filter.
Definition: avfilter.h:524
static av_cold int init(AVFilterContext *ctx)
Definition: vf_idet.c:276
int height
Definition: frame.h:122
#define AV_LOG_INFO
Definition: log.h:156
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:103
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:319
internal API functions
Definition: vf_idet.c:33
AVFrame * prev
Definition: vf_idet.c:52
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
Definition: pixfmt.h:156
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
Definition: pixfmt.h:152