FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
vf_crop.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2007 Bobby Bingham
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
/**
22
* @file
23
* video crop filter
24
*/
25
26
#include <stdio.h>
27
28
#include "
avfilter.h
"
29
#include "
formats.h
"
30
#include "
internal.h
"
31
#include "
video.h
"
32
#include "
libavutil/eval.h
"
33
#include "
libavutil/avstring.h
"
34
#include "
libavutil/internal.h
"
35
#include "
libavutil/libm.h
"
36
#include "
libavutil/imgutils.h
"
37
#include "
libavutil/mathematics.h
"
38
#include "
libavutil/opt.h
"
39
40
static
const
char
*
const
var_names
[] = {
41
"in_w"
,
"iw"
,
///< width of the input video
42
"in_h"
,
"ih"
,
///< height of the input video
43
"out_w"
,
"ow"
,
///< width of the cropped video
44
"out_h"
,
"oh"
,
///< height of the cropped video
45
"a"
,
46
"sar"
,
47
"dar"
,
48
"hsub"
,
49
"vsub"
,
50
"x"
,
51
"y"
,
52
"n"
,
///< number of frame
53
"pos"
,
///< position in the file
54
"t"
,
///< timestamp expressed in seconds
55
NULL
56
};
57
58
enum
var_name
{
59
VAR_IN_W
,
VAR_IW
,
60
VAR_IN_H
,
VAR_IH
,
61
VAR_OUT_W
,
VAR_OW
,
62
VAR_OUT_H
,
VAR_OH
,
63
VAR_A
,
64
VAR_SAR
,
65
VAR_DAR
,
66
VAR_HSUB
,
67
VAR_VSUB
,
68
VAR_X
,
69
VAR_Y
,
70
VAR_N
,
71
VAR_POS
,
72
VAR_T
,
73
VAR_VARS_NB
74
};
75
76
typedef
struct
CropContext
{
77
const
AVClass
*
class
;
78
int
x
;
///< x offset of the non-cropped area with respect to the input area
79
int
y
;
///< y offset of the non-cropped area with respect to the input area
80
int
w
;
///< width of the cropped area
81
int
h
;
///< height of the cropped area
82
83
AVRational
out_sar
;
///< output sample aspect ratio
84
int
keep_aspect
;
///< keep display aspect ratio when cropping
85
86
int
max_step
[4];
///< max pixel step for each plane, expressed as a number of bytes
87
int
hsub
,
vsub
;
///< chroma subsampling
88
char
*
x_expr
, *
y_expr
, *
w_expr
, *
h_expr
;
89
AVExpr
*
x_pexpr
, *
y_pexpr
;
/* parsed expressions for x and y */
90
double
var_values
[
VAR_VARS_NB
];
91
}
CropContext
;
92
93
static
int
query_formats
(
AVFilterContext
*ctx)
94
{
95
AVFilterFormats
*
formats
=
NULL
;
96
int
fmt
;
97
98
for
(fmt = 0;
av_pix_fmt_desc_get
(fmt); fmt++) {
99
const
AVPixFmtDescriptor
*desc =
av_pix_fmt_desc_get
(fmt);
100
if
(!(desc->
flags
& (
AV_PIX_FMT_FLAG_HWACCEL
|
AV_PIX_FMT_FLAG_BITSTREAM
)) &&
101
!((desc->
log2_chroma_w
|| desc->
log2_chroma_h
) && !(desc->
flags
&
AV_PIX_FMT_FLAG_PLANAR
)))
102
ff_add_format
(&formats, fmt);
103
}
104
105
ff_set_common_formats
(ctx, formats);
106
return
0;
107
}
108
109
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
110
{
111
CropContext
*
s
= ctx->
priv
;
112
113
av_expr_free
(s->
x_pexpr
);
114
s->
x_pexpr
=
NULL
;
115
av_expr_free
(s->
y_pexpr
);
116
s->
y_pexpr
=
NULL
;
117
}
118
119
static
inline
int
normalize_double
(
int
*
n
,
double
d)
120
{
121
int
ret
= 0;
122
123
if
(
isnan
(d)) {
124
ret =
AVERROR
(EINVAL);
125
}
else
if
(d > INT_MAX || d < INT_MIN) {
126
*n = d > INT_MAX ? INT_MAX : INT_MIN;
127
ret =
AVERROR
(EINVAL);
128
}
else
129
*n =
round
(d);
130
131
return
ret
;
132
}
133
134
static
int
config_input
(
AVFilterLink
*link)
135
{
136
AVFilterContext
*ctx = link->
dst
;
137
CropContext
*
s
= ctx->
priv
;
138
const
AVPixFmtDescriptor
*pix_desc =
av_pix_fmt_desc_get
(link->
format
);
139
int
ret
;
140
const
char
*expr;
141
double
res;
142
143
s->
var_values
[
VAR_IN_W
] = s->
var_values
[
VAR_IW
] = ctx->
inputs
[0]->
w
;
144
s->
var_values
[
VAR_IN_H
] = s->
var_values
[
VAR_IH
] = ctx->
inputs
[0]->
h
;
145
s->
var_values
[
VAR_A
] = (float) link->
w
/ link->
h
;
146
s->
var_values
[
VAR_SAR
] = link->
sample_aspect_ratio
.
num
?
av_q2d
(link->
sample_aspect_ratio
) : 1;
147
s->
var_values
[
VAR_DAR
] = s->
var_values
[
VAR_A
] * s->
var_values
[
VAR_SAR
];
148
s->
var_values
[
VAR_HSUB
] = 1<<pix_desc->
log2_chroma_w
;
149
s->
var_values
[
VAR_VSUB
] = 1<<pix_desc->
log2_chroma_h
;
150
s->
var_values
[
VAR_X
] =
NAN
;
151
s->
var_values
[
VAR_Y
] =
NAN
;
152
s->
var_values
[
VAR_OUT_W
] = s->
var_values
[
VAR_OW
] =
NAN
;
153
s->
var_values
[
VAR_OUT_H
] = s->
var_values
[
VAR_OH
] =
NAN
;
154
s->
var_values
[
VAR_N
] = 0;
155
s->
var_values
[
VAR_T
] =
NAN
;
156
s->
var_values
[
VAR_POS
] =
NAN
;
157
158
av_image_fill_max_pixsteps
(s->
max_step
,
NULL
, pix_desc);
159
s->
hsub
= pix_desc->
log2_chroma_w
;
160
s->
vsub
= pix_desc->
log2_chroma_h
;
161
162
if
((ret =
av_expr_parse_and_eval
(&res, (expr = s->
w_expr
),
163
var_names
, s->
var_values
,
164
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
165
goto
fail_expr;
166
s->
var_values
[
VAR_OUT_W
] = s->
var_values
[
VAR_OW
] = res;
167
if
((ret =
av_expr_parse_and_eval
(&res, (expr = s->
h_expr
),
168
var_names
, s->
var_values
,
169
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
170
goto
fail_expr;
171
s->
var_values
[
VAR_OUT_H
] = s->
var_values
[
VAR_OH
] = res;
172
/* evaluate again ow as it may depend on oh */
173
if
((ret =
av_expr_parse_and_eval
(&res, (expr = s->
w_expr
),
174
var_names
, s->
var_values
,
175
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
176
goto
fail_expr;
177
178
s->
var_values
[
VAR_OUT_W
] = s->
var_values
[
VAR_OW
] = res;
179
if
(
normalize_double
(&s->
w
, s->
var_values
[
VAR_OUT_W
]) < 0 ||
180
normalize_double
(&s->
h
, s->
var_values
[
VAR_OUT_H
]) < 0) {
181
av_log
(ctx,
AV_LOG_ERROR
,
182
"Too big value or invalid expression for out_w/ow or out_h/oh. "
183
"Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n"
,
184
s->
w_expr
, s->
h_expr
);
185
return
AVERROR
(EINVAL);
186
}
187
s->
w
&= ~((1 << s->
hsub
) - 1);
188
s->
h
&= ~((1 << s->
vsub
) - 1);
189
190
av_expr_free
(s->
x_pexpr
);
191
av_expr_free
(s->
y_pexpr
);
192
s->
x_pexpr
= s->
y_pexpr
=
NULL
;
193
if
((ret =
av_expr_parse
(&s->
x_pexpr
, s->
x_expr
,
var_names
,
194
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0 ||
195
(ret =
av_expr_parse
(&s->
y_pexpr
, s->
y_expr
,
var_names
,
196
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
197
return
AVERROR
(EINVAL);
198
199
if
(s->
keep_aspect
) {
200
AVRational
dar =
av_mul_q
(link->
sample_aspect_ratio
,
201
(
AVRational
){ link->
w
, link->
h
});
202
av_reduce
(&s->
out_sar
.
num
, &s->
out_sar
.
den
,
203
dar.num * s->
h
, dar.den * s->
w
, INT_MAX);
204
}
else
205
s
->out_sar = link->sample_aspect_ratio;
206
207
av_log
(ctx,
AV_LOG_VERBOSE
,
"w:%d h:%d sar:%d/%d -> w:%d h:%d sar:%d/%d\n"
,
208
link->w, link->h, link->sample_aspect_ratio.num, link->sample_aspect_ratio.den,
209
s
->w,
s
->h,
s
->out_sar.num,
s
->out_sar.den);
210
211
if
(
s
->w <= 0 ||
s
->h <= 0 ||
212
s
->w > link->w ||
s
->h > link->h) {
213
av_log
(ctx,
AV_LOG_ERROR
,
214
"Invalid too big or non positive size for width '%d' or height '%d'\n"
,
215
s
->w,
s
->h);
216
return
AVERROR
(EINVAL);
217
}
218
219
/* set default, required in the case the first computed value for x/y is NAN */
220
s
->x = (link->w -
s
->w) / 2;
221
s
->y = (link->h -
s
->h) / 2;
222
s
->x &= ~((1 <<
s
->hsub) - 1);
223
s
->y &= ~((1 <<
s
->vsub) - 1);
224
return
0;
225
226
fail_expr:
227
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error when evaluating the expression '%s'\n"
, expr);
228
return
ret
;
229
}
230
231
static
int
config_output
(
AVFilterLink
*link)
232
{
233
CropContext
*
s
= link->
src
->
priv
;
234
235
link->
w
= s->
w
;
236
link->
h
= s->
h
;
237
link->
sample_aspect_ratio
= s->
out_sar
;
238
239
return
0;
240
}
241
242
static
int
filter_frame
(
AVFilterLink
*link,
AVFrame
*
frame
)
243
{
244
AVFilterContext
*ctx = link->
dst
;
245
CropContext
*
s
= ctx->
priv
;
246
const
AVPixFmtDescriptor
*desc =
av_pix_fmt_desc_get
(link->
format
);
247
int
i;
248
249
frame->
width
= s->
w
;
250
frame->
height
= s->
h
;
251
252
s->
var_values
[
VAR_N
] = link->
frame_count
;
253
s->
var_values
[
VAR_T
] = frame->
pts
==
AV_NOPTS_VALUE
?
254
NAN
: frame->
pts
*
av_q2d
(link->
time_base
);
255
s->
var_values
[
VAR_POS
] =
av_frame_get_pkt_pos
(frame) == -1 ?
256
NAN
:
av_frame_get_pkt_pos
(frame);
257
s->
var_values
[
VAR_X
] =
av_expr_eval
(s->
x_pexpr
, s->
var_values
,
NULL
);
258
s->
var_values
[
VAR_Y
] =
av_expr_eval
(s->
y_pexpr
, s->
var_values
,
NULL
);
259
s->
var_values
[
VAR_X
] =
av_expr_eval
(s->
x_pexpr
, s->
var_values
,
NULL
);
260
261
normalize_double
(&s->
x
, s->
var_values
[
VAR_X
]);
262
normalize_double
(&s->
y
, s->
var_values
[
VAR_Y
]);
263
264
if
(s->
x
< 0)
265
s->
x
= 0;
266
if
(s->
y
< 0)
267
s->
y
= 0;
268
if
((
unsigned
)s->
x
+ (
unsigned
)s->
w
> link->
w
)
269
s->
x
= link->
w
- s->
w
;
270
if
((
unsigned
)s->
y
+ (
unsigned
)s->
h
> link->
h
)
271
s->
y
= link->
h
- s->
h
;
272
s->
x
&= ~((1 << s->
hsub
) - 1);
273
s->
y
&= ~((1 << s->
vsub
) - 1);
274
275
av_dlog
(ctx,
"n:%d t:%f pos:%f x:%d y:%d x+w:%d y+h:%d\n"
,
276
(
int
)s->
var_values
[
VAR_N
], s->
var_values
[
VAR_T
], s->
var_values
[
VAR_POS
],
277
s->
x
, s->
y
, s->
x
+s->
w
, s->
y
+s->
h
);
278
279
frame->
data
[0] += s->
y
* frame->
linesize
[0];
280
frame->
data
[0] += s->
x
* s->
max_step
[0];
281
282
if
(!(desc->
flags
&
AV_PIX_FMT_FLAG_PAL
|| desc->
flags
&
AV_PIX_FMT_FLAG_PSEUDOPAL
)) {
283
for
(i = 1; i < 3; i ++) {
284
if
(frame->
data
[i]) {
285
frame->
data
[i] += (s->
y
>> s->
vsub
) * frame->
linesize
[i];
286
frame->
data
[i] += (s->
x
* s->
max_step
[i]) >> s->
hsub
;
287
}
288
}
289
}
290
291
/* alpha plane */
292
if
(frame->
data
[3]) {
293
frame->
data
[3] += s->
y
* frame->
linesize
[3];
294
frame->
data
[3] += s->
x
* s->
max_step
[3];
295
}
296
297
return
ff_filter_frame
(link->
dst
->
outputs
[0], frame);
298
}
299
300
#define OFFSET(x) offsetof(CropContext, x)
301
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
302
303
static
const
AVOption
crop_options
[] = {
304
{
"out_w"
,
"set the width crop area expression"
,
OFFSET
(w_expr),
AV_OPT_TYPE_STRING
, {.str =
"iw"
}, CHAR_MIN, CHAR_MAX,
FLAGS
},
305
{
"w"
,
"set the width crop area expression"
,
OFFSET
(w_expr),
AV_OPT_TYPE_STRING
, {.str =
"iw"
}, CHAR_MIN, CHAR_MAX,
FLAGS
},
306
{
"out_h"
,
"set the height crop area expression"
,
OFFSET
(h_expr),
AV_OPT_TYPE_STRING
, {.str =
"ih"
}, CHAR_MIN, CHAR_MAX,
FLAGS
},
307
{
"h"
,
"set the height crop area expression"
,
OFFSET
(h_expr),
AV_OPT_TYPE_STRING
, {.str =
"ih"
}, CHAR_MIN, CHAR_MAX,
FLAGS
},
308
{
"x"
,
"set the x crop area expression"
,
OFFSET
(x_expr),
AV_OPT_TYPE_STRING
, {.str =
"(in_w-out_w)/2"
}, CHAR_MIN, CHAR_MAX,
FLAGS
},
309
{
"y"
,
"set the y crop area expression"
,
OFFSET
(y_expr),
AV_OPT_TYPE_STRING
, {.str =
"(in_h-out_h)/2"
}, CHAR_MIN, CHAR_MAX,
FLAGS
},
310
{
"keep_aspect"
,
"keep aspect ratio"
,
OFFSET
(keep_aspect),
AV_OPT_TYPE_INT
, {.i64=0}, 0, 1,
FLAGS
},
311
{
NULL
}
312
};
313
314
AVFILTER_DEFINE_CLASS
(crop);
315
316
static
const
AVFilterPad
avfilter_vf_crop_inputs
[] = {
317
{
318
.
name
=
"default"
,
319
.type =
AVMEDIA_TYPE_VIDEO
,
320
.filter_frame =
filter_frame
,
321
.config_props =
config_input
,
322
},
323
{
NULL
}
324
};
325
326
static
const
AVFilterPad
avfilter_vf_crop_outputs
[] = {
327
{
328
.
name
=
"default"
,
329
.type =
AVMEDIA_TYPE_VIDEO
,
330
.config_props =
config_output
,
331
},
332
{
NULL
}
333
};
334
335
AVFilter
ff_vf_crop
= {
336
.
name
=
"crop"
,
337
.description =
NULL_IF_CONFIG_SMALL
(
"Crop the input video."
),
338
.priv_size =
sizeof
(
CropContext
),
339
.priv_class = &crop_class,
340
.
query_formats
=
query_formats
,
341
.
uninit
=
uninit
,
342
.
inputs
= avfilter_vf_crop_inputs,
343
.
outputs
= avfilter_vf_crop_outputs,
344
};
Generated on Sun Mar 8 2015 02:35:06 for FFmpeg by
1.8.2