FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
vf_decimate.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2003 Rich Felker
3
* Copyright (c) 2012 Stefano Sabatini
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
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
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License along
18
* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
*/
21
22
/**
23
* @file decimate filter, ported from libmpcodecs/vf_decimate.c by
24
* Rich Felker.
25
*/
26
27
#include "
libavutil/pixdesc.h
"
28
#include "
libavutil/timestamp.h
"
29
#include "
libavcodec/dsputil.h
"
30
#include "
avfilter.h
"
31
#include "
internal.h
"
32
#include "
formats.h
"
33
#include "
video.h
"
34
35
typedef
struct
{
36
int
lo
, hi;
///< lower and higher threshold number of differences
37
///< values for 8x8 blocks
38
39
float
frac
;
///< threshold of changed pixels over the total fraction
40
41
int
max_drop_count;
///< if positive: maximum number of sequential frames to drop
42
///< if negative: minimum number of frames between two drops
43
44
int
drop_count;
///< if positive: number of frames sequentially dropped
45
///< if negative: number of sequential frames which were not dropped
46
47
int
hsub,
vsub
;
///< chroma subsampling values
48
AVFilterBufferRef
*
ref
;
///< reference picture
49
DSPContext
dspctx
;
///< context providing optimized diff routines
50
AVCodecContext
*
avctx
;
///< codec context required for the DSPContext
51
}
DecimateContext
;
52
53
/**
54
* Return 1 if the two planes are different, 0 otherwise.
55
*/
56
static
int
diff_planes
(
AVFilterContext
*ctx,
57
uint8_t
*cur,
uint8_t
*ref,
int
linesize,
58
int
w,
int
h)
59
{
60
DecimateContext
*decimate = ctx->
priv
;
61
DSPContext
*dspctx = &decimate->
dspctx
;
62
63
int
x, y;
64
int
d,
c
= 0;
65
int
t
= (w/16)*(h/16)*decimate->
frac
;
66
DCTELEM
block
[8*8];
67
68
/* compute difference for blocks of 8x8 bytes */
69
for
(y = 0; y < h-7; y += 4) {
70
for
(x = 8; x < w-7; x += 4) {
71
dspctx->
diff_pixels
(block,
72
cur+x+y*linesize,
73
ref+x+y*linesize, linesize);
74
d = dspctx->
sum_abs_dctelem
(block);
75
if
(d > decimate->
hi
)
76
return
1;
77
if
(d > decimate->
lo
) {
78
c++;
79
if
(c > t)
80
return
1;
81
}
82
}
83
}
84
return
0;
85
}
86
87
/**
88
* Tell if the frame should be decimated, for example if it is no much
89
* different with respect to the reference frame ref.
90
*/
91
static
int
decimate_frame
(
AVFilterContext
*ctx,
92
AVFilterBufferRef
*cur,
AVFilterBufferRef
*ref)
93
{
94
DecimateContext
*decimate = ctx->
priv
;
95
int
plane;
96
97
if
(decimate->
max_drop_count
> 0 &&
98
decimate->
drop_count
>= decimate->
max_drop_count
)
99
return
0;
100
if
(decimate->
max_drop_count
< 0 &&
101
(decimate->
drop_count
-1) > decimate->
max_drop_count
)
102
return
0;
103
104
for
(plane = 0; ref->
data
[plane] && ref->
linesize
[plane]; plane++) {
105
int
vsub = plane == 1 || plane == 2 ? decimate->
vsub
: 0;
106
int
hsub = plane == 1 || plane == 2 ? decimate->
hsub
: 0;
107
if
(
diff_planes
(ctx,
108
cur->
data
[plane], ref->
data
[plane], ref->
linesize
[plane],
109
ref->
video
->
w
>>hsub, ref->
video
->
h
>>vsub))
110
return
0;
111
}
112
113
return
1;
114
}
115
116
static
av_cold
int
init
(
AVFilterContext
*ctx,
const
char
*args)
117
{
118
DecimateContext
*decimate = ctx->
priv
;
119
120
/* set default values */
121
decimate->
drop_count
= decimate->
max_drop_count
= 0;
122
decimate->
lo
= 64*5;
123
decimate->
hi
= 64*12;
124
decimate->
frac
= 0.33;
125
126
if
(args) {
127
char
c1
,
c2
,
c3
,
c4
;
128
int
n = sscanf(args,
"%d%c%d%c%d%c%f%c"
,
129
&decimate->
max_drop_count
, &c1,
130
&decimate->
hi
, &c2, &decimate->
lo
, &c3,
131
&decimate->
frac
, &c4);
132
if
(n != 1 &&
133
(n != 3 || c1 !=
':'
) &&
134
(n != 5 || c1 !=
':'
|| c2 !=
':'
) &&
135
(n != 7 || c1 !=
':'
|| c2 !=
':'
|| c3 !=
':'
)) {
136
av_log
(ctx,
AV_LOG_ERROR
,
137
"Invalid syntax for argument '%s': "
138
"must be in the form 'max:hi:lo:frac'\n"
, args);
139
return
AVERROR
(EINVAL);
140
}
141
}
142
143
av_log
(ctx,
AV_LOG_VERBOSE
,
"max_drop_count:%d hi:%d lo:%d frac:%f\n"
,
144
decimate->
max_drop_count
, decimate->
hi
, decimate->
lo
, decimate->
frac
);
145
146
decimate->
avctx
=
avcodec_alloc_context3
(
NULL
);
147
if
(!decimate->
avctx
)
148
return
AVERROR
(ENOMEM);
149
dsputil_init
(&decimate->
dspctx
, decimate->
avctx
);
150
151
return
0;
152
}
153
154
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
155
{
156
DecimateContext
*decimate = ctx->
priv
;
157
avfilter_unref_bufferp
(&decimate->
ref
);
158
avcodec_close
(decimate->
avctx
);
159
av_freep
(&decimate->
avctx
);
160
}
161
162
static
int
query_formats
(
AVFilterContext
*ctx)
163
{
164
static
const
enum
AVPixelFormat
pix_fmts[] = {
165
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUV422P
,
166
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUV411P
,
167
AV_PIX_FMT_YUV410P
,
AV_PIX_FMT_YUV440P
,
168
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ422P
,
169
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ440P
,
170
AV_PIX_FMT_YUVA420P
,
171
AV_PIX_FMT_NONE
172
};
173
174
ff_set_common_formats
(ctx,
ff_make_format_list
(pix_fmts));
175
176
return
0;
177
}
178
179
static
int
config_input
(
AVFilterLink
*inlink)
180
{
181
AVFilterContext
*ctx = inlink->
dst
;
182
DecimateContext
*decimate = ctx->
priv
;
183
const
AVPixFmtDescriptor
*pix_desc =
av_pix_fmt_desc_get
(inlink->
format
);
184
decimate->
hsub
= pix_desc->
log2_chroma_w
;
185
decimate->
vsub
= pix_desc->
log2_chroma_h
;
186
187
return
0;
188
}
189
190
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*cur)
191
{
192
DecimateContext
*decimate = inlink->
dst
->
priv
;
193
AVFilterLink
*outlink = inlink->
dst
->
outputs
[0];
194
int
ret;
195
196
if
(decimate->
ref
&&
decimate_frame
(inlink->
dst
, cur, decimate->
ref
)) {
197
decimate->
drop_count
=
FFMAX
(1, decimate->
drop_count
+1);
198
}
else
{
199
avfilter_unref_buffer
(decimate->
ref
);
200
decimate->
ref
= cur;
201
decimate->
drop_count
=
FFMIN
(-1, decimate->
drop_count
-1);
202
203
if
(ret =
ff_filter_frame
(outlink,
avfilter_ref_buffer
(cur, ~
AV_PERM_WRITE
)) < 0)
204
return
ret;
205
}
206
207
av_log
(inlink->
dst
,
AV_LOG_DEBUG
,
208
"%s pts:%s pts_time:%s drop_count:%d\n"
,
209
decimate->
drop_count
> 0 ?
"drop"
:
"keep"
,
210
av_ts2str
(cur->
pts
),
av_ts2timestr
(cur->
pts
, &inlink->
time_base
),
211
decimate->
drop_count
);
212
213
if
(decimate->
drop_count
> 0)
214
avfilter_unref_buffer
(cur);
215
216
return
0;
217
}
218
219
static
int
request_frame
(
AVFilterLink
*outlink)
220
{
221
DecimateContext
*decimate = outlink->
src
->
priv
;
222
AVFilterLink
*inlink = outlink->
src
->
inputs
[0];
223
int
ret;
224
225
do
{
226
ret =
ff_request_frame
(inlink);
227
}
while
(decimate->
drop_count
> 0 && ret >= 0);
228
229
return
ret;
230
}
231
232
static
const
AVFilterPad
decimate_inputs
[] = {
233
{
234
.
name
=
"default"
,
235
.type =
AVMEDIA_TYPE_VIDEO
,
236
.get_video_buffer =
ff_null_get_video_buffer
,
237
.config_props =
config_input
,
238
.filter_frame =
filter_frame
,
239
.min_perms =
AV_PERM_READ
|
AV_PERM_PRESERVE
,
240
},
241
{
NULL
}
242
};
243
244
static
const
AVFilterPad
decimate_outputs
[] = {
245
{
246
.
name
=
"default"
,
247
.type =
AVMEDIA_TYPE_VIDEO
,
248
.request_frame =
request_frame
,
249
},
250
{
NULL
}
251
};
252
253
AVFilter
avfilter_vf_decimate
= {
254
.
name
=
"decimate"
,
255
.description =
NULL_IF_CONFIG_SMALL
(
"Remove near-duplicate frames."
),
256
.init =
init
,
257
.uninit =
uninit
,
258
259
.priv_size =
sizeof
(
DecimateContext
),
260
.
query_formats
=
query_formats
,
261
.
inputs
= decimate_inputs,
262
.
outputs
= decimate_outputs,
263
};
Generated on Sat May 25 2013 03:58:45 for FFmpeg by
1.8.2