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_zoompan.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2013 Paul B Mahol
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 "
libavutil/eval.h
"
22
#include "
libavutil/opt.h
"
23
#include "
libavutil/pixdesc.h
"
24
#include "
avfilter.h
"
25
#include "
formats.h
"
26
#include "
internal.h
"
27
#include "
video.h
"
28
#include "
libswscale/swscale.h
"
29
30
static
const
char
*
const
var_names
[] = {
31
"in_w"
,
"iw"
,
32
"in_h"
,
"ih"
,
33
"out_w"
,
"ow"
,
34
"out_h"
,
"oh"
,
35
"in"
,
36
"on"
,
37
"duration"
,
38
"pduration"
,
39
"time"
,
40
"frame"
,
41
"zoom"
,
42
"pzoom"
,
43
"x"
,
"px"
,
44
"y"
,
"py"
,
45
"a"
,
46
"sar"
,
47
"dar"
,
48
"hsub"
,
49
"vsub"
,
50
NULL
51
};
52
53
enum
var_name
{
54
VAR_IN_W
,
VAR_IW
,
55
VAR_IN_H
,
VAR_IH
,
56
VAR_OUT_W
,
VAR_OW
,
57
VAR_OUT_H
,
VAR_OH
,
58
VAR_IN
,
59
VAR_ON
,
60
VAR_DURATION
,
61
VAR_PDURATION
,
62
VAR_TIME
,
63
VAR_FRAME
,
64
VAR_ZOOM
,
65
VAR_PZOOM
,
66
VAR_X
,
VAR_PX
,
67
VAR_Y
,
VAR_PY
,
68
VAR_A
,
69
VAR_SAR
,
70
VAR_DAR
,
71
VAR_HSUB
,
72
VAR_VSUB
,
73
VARS_NB
74
};
75
76
typedef
struct
ZPcontext {
77
const
AVClass
*
class
;
78
char
*
zoom_expr_str
;
79
char
*
x_expr_str
;
80
char
*
y_expr_str
;
81
char
*
duration_expr_str
;
82
int
w
, h;
83
double
x,
y
;
84
double
prev_zoom
;
85
int
prev_nb_frames
;
86
struct
SwsContext
*
sws
;
87
int64_t
frame_count
;
88
}
ZPContext
;
89
90
#define OFFSET(x) offsetof(ZPContext, x)
91
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
92
static
const
AVOption
zoompan_options
[] = {
93
{
"zoom"
,
"set the zoom expression"
,
OFFSET
(zoom_expr_str),
AV_OPT_TYPE_STRING
, {.str =
"1"
}, .flags =
FLAGS
},
94
{
"z"
,
"set the zoom expression"
,
OFFSET
(zoom_expr_str),
AV_OPT_TYPE_STRING
, {.str =
"1"
}, .flags =
FLAGS
},
95
{
"x"
,
"set the x expression"
,
OFFSET
(x_expr_str),
AV_OPT_TYPE_STRING
, {.str=
"0"
}, .flags =
FLAGS
},
96
{
"y"
,
"set the y expression"
,
OFFSET
(y_expr_str),
AV_OPT_TYPE_STRING
, {.str=
"0"
}, .flags =
FLAGS
},
97
{
"d"
,
"set the duration expression"
,
OFFSET
(duration_expr_str),
AV_OPT_TYPE_STRING
, {.str=
"90"
}, .flags =
FLAGS
},
98
{
"s"
,
"set the output image size"
,
OFFSET
(w),
AV_OPT_TYPE_IMAGE_SIZE
, {.str=
"hd720"
}, .flags =
FLAGS
},
99
{
NULL
}
100
};
101
102
AVFILTER_DEFINE_CLASS
(zoompan);
103
104
static
av_cold
int
init
(
AVFilterContext
*ctx)
105
{
106
ZPContext
*
s
= ctx->
priv
;
107
108
s->
prev_zoom
= 1;
109
return
0;
110
}
111
112
static
int
config_output
(
AVFilterLink
*outlink)
113
{
114
AVFilterContext
*ctx = outlink->
src
;
115
ZPContext
*
s
= ctx->
priv
;
116
117
outlink->
w
= s->
w
;
118
outlink->
h
= s->
h
;
119
120
return
0;
121
}
122
123
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*
in
)
124
{
125
AVFilterContext
*ctx = inlink->
dst
;
126
AVFilterLink
*outlink = ctx->
outputs
[0];
127
ZPContext
*
s
= ctx->
priv
;
128
double
var_values[
VARS_NB
], nb_frames, zoom, dx, dy;
129
const
AVPixFmtDescriptor
*desc =
av_pix_fmt_desc_get
(in->
format
);
130
AVFrame
*
out
;
131
int
i, k, x,
y
, w, h,
ret
= 0;
132
133
var_values[
VAR_IN_W
] = var_values[
VAR_IW
] = in->
width
;
134
var_values[
VAR_IN_H
] = var_values[
VAR_IH
] = in->
height
;
135
var_values[
VAR_OUT_W
] = var_values[
VAR_OW
] = s->
w
;
136
var_values[
VAR_OUT_H
] = var_values[
VAR_OH
] = s->
h
;
137
var_values[
VAR_IN
] = inlink->
frame_count
+ 1;
138
var_values[
VAR_ON
] = outlink->
frame_count
+ 1;
139
var_values[
VAR_PX
] = s->
x
;
140
var_values[
VAR_PY
] = s->
y
;
141
var_values[
VAR_X
] = 0;
142
var_values[
VAR_Y
] = 0;
143
var_values[
VAR_PZOOM
] = s->
prev_zoom
;
144
var_values[
VAR_ZOOM
] = 1;
145
var_values[
VAR_PDURATION
] = s->
prev_nb_frames
;
146
var_values[
VAR_A
] = (double) in->
width
/ in->
height
;
147
var_values[
VAR_SAR
] = inlink->
sample_aspect_ratio
.
num
?
148
(
double
) inlink->
sample_aspect_ratio
.
num
/ inlink->
sample_aspect_ratio
.
den
: 1;
149
var_values[
VAR_DAR
] = var_values[
VAR_A
] * var_values[
VAR_SAR
];
150
var_values[
VAR_HSUB
] = 1 << desc->
log2_chroma_w
;
151
var_values[
VAR_VSUB
] = 1 << desc->
log2_chroma_h
;
152
153
if
((ret =
av_expr_parse_and_eval
(&nb_frames, s->
duration_expr_str
,
154
var_names
, var_values,
155
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
156
goto
fail;
157
158
var_values[
VAR_DURATION
] = nb_frames;
159
for
(i = 0; i < nb_frames; i++) {
160
int
px[4];
161
int
py[4];
162
uint8_t
*input[4];
163
int64_t
pts
=
av_rescale_q
(in->
pts
, inlink->
time_base
,
164
outlink->
time_base
) + s->
frame_count
;
165
166
var_values[
VAR_TIME
] = pts *
av_q2d
(outlink->
time_base
);
167
var_values[
VAR_FRAME
] = i;
168
var_values[
VAR_ON
] = outlink->
frame_count
+ 1;
169
if
((ret =
av_expr_parse_and_eval
(&zoom, s->
zoom_expr_str
,
170
var_names
, var_values,
171
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
172
goto
fail;
173
174
zoom = av_clipd(zoom, 1, 10);
175
var_values[
VAR_ZOOM
] = zoom;
176
w = in->
width
* (1.0 / zoom);
177
h = in->
height
* (1.0 / zoom);
178
179
if
((ret =
av_expr_parse_and_eval
(&dx, s->
x_expr_str
,
180
var_names
, var_values,
181
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
182
goto
fail;
183
x = dx = av_clipd(dx, 0,
FFMAX
(in->
width
- w, 0));
184
var_values[
VAR_X
] = dx;
185
x &= ~((1 << desc->
log2_chroma_w
) - 1);
186
187
if
((ret =
av_expr_parse_and_eval
(&dy, s->
y_expr_str
,
188
var_names
, var_values,
189
NULL
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0)
190
goto
fail;
191
y = dy = av_clipd(dy, 0,
FFMAX
(in->
height
- h, 0));
192
var_values[
VAR_Y
] = dy;
193
y &= ~((1 << desc->
log2_chroma_h
) - 1);
194
195
out =
ff_get_video_buffer
(outlink, outlink->
w
, outlink->
h
);
196
if
(!out) {
197
ret =
AVERROR
(ENOMEM);
198
goto
fail;
199
}
200
201
px[1] = px[2] =
FF_CEIL_RSHIFT
(x, desc->
log2_chroma_w
);
202
px[0] = px[3] = x;
203
204
py[1] = py[2] =
FF_CEIL_RSHIFT
(y, desc->
log2_chroma_h
);
205
py[0] = py[3] =
y
;
206
207
s->
sws
=
sws_alloc_context
();
208
if
(!s->
sws
) {
209
ret =
AVERROR
(ENOMEM);
210
goto
fail;
211
}
212
213
for
(k = 0; in->
data
[k]; k++)
214
input[k] = in->
data
[k] + py[k] * in->
linesize
[k] + px[k];
215
216
av_opt_set_int
(s->
sws
,
"srcw"
, w, 0);
217
av_opt_set_int
(s->
sws
,
"srch"
, h, 0);
218
av_opt_set_int
(s->
sws
,
"src_format"
, in->
format
, 0);
219
av_opt_set_int
(s->
sws
,
"dstw"
, outlink->
w
, 0);
220
av_opt_set_int
(s->
sws
,
"dsth"
, outlink->
h
, 0);
221
av_opt_set_int
(s->
sws
,
"dst_format"
, outlink->
format
, 0);
222
av_opt_set_int
(s->
sws
,
"sws_flags"
,
SWS_BICUBIC
, 0);
223
224
if
((ret =
sws_init_context
(s->
sws
,
NULL
,
NULL
)) < 0)
225
goto
fail;
226
227
sws_scale
(s->
sws
, (
const
uint8_t
*
const
*)&input, in->
linesize
, 0, h, out->
data
, out->
linesize
);
228
229
out->
pts
=
pts
;
230
s->
frame_count
++;
231
232
ret =
ff_filter_frame
(outlink, out);
233
if
(ret < 0)
234
break
;
235
236
sws_freeContext
(s->
sws
);
237
s->
sws
=
NULL
;
238
}
239
240
s->
x
= dx;
241
s->
y
= dy;
242
s->
prev_zoom
= zoom;
243
s->
prev_nb_frames
= nb_frames;
244
245
fail:
246
sws_freeContext
(s->
sws
);
247
s->
sws
=
NULL
;
248
av_frame_free
(&in);
249
return
ret
;
250
}
251
252
static
int
query_formats
(
AVFilterContext
*ctx)
253
{
254
static
const
enum
AVPixelFormat
pix_fmts[] = {
255
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUV422P
,
256
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUV411P
,
257
AV_PIX_FMT_YUV410P
,
AV_PIX_FMT_YUV440P
,
258
AV_PIX_FMT_YUVA444P
,
AV_PIX_FMT_YUVA422P
,
259
AV_PIX_FMT_YUVA420P
,
260
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ440P
,
261
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ420P
,
262
AV_PIX_FMT_YUVJ411P
,
263
AV_PIX_FMT_GRAY8
,
264
AV_PIX_FMT_NONE
265
};
266
267
268
ff_set_common_formats
(ctx,
ff_make_format_list
(pix_fmts));
269
return
0;
270
}
271
272
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
273
{
274
ZPContext
*
s
= ctx->
priv
;
275
276
sws_freeContext
(s->
sws
);
277
s->
sws
=
NULL
;
278
}
279
280
static
const
AVFilterPad
inputs
[] = {
281
{
282
.
name
=
"default"
,
283
.type =
AVMEDIA_TYPE_VIDEO
,
284
.filter_frame =
filter_frame
,
285
},
286
{
NULL
}
287
};
288
289
static
const
AVFilterPad
outputs
[] = {
290
{
291
.
name
=
"default"
,
292
.type =
AVMEDIA_TYPE_VIDEO
,
293
.config_props =
config_output
,
294
},
295
{
NULL
}
296
};
297
298
AVFilter
ff_vf_zoompan
= {
299
.
name
=
"zoompan"
,
300
.description =
NULL_IF_CONFIG_SMALL
(
"Apply Zoom & Pan effect."
),
301
.priv_size =
sizeof
(
ZPContext
),
302
.priv_class = &zoompan_class,
303
.
init
=
init
,
304
.
uninit
=
uninit
,
305
.
query_formats
=
query_formats
,
306
.inputs = inputs,
307
.outputs = outputs,
308
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
309
};
Generated on Sun Mar 8 2015 02:35:08 for FFmpeg by
1.8.2