Libav
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavfilter
vf_select.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Stefano Sabatini
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
#include "
libavutil/eval.h
"
27
#include "
libavutil/fifo.h
"
28
#include "
libavutil/internal.h
"
29
#include "
libavutil/mathematics.h
"
30
#include "
libavutil/opt.h
"
31
#include "
avfilter.h
"
32
#include "
internal.h
"
33
#include "
video.h
"
34
35
static
const
char
*
const
var_names
[] = {
36
"E"
,
37
"PHI"
,
38
"PI"
,
39
40
"TB"
,
41
42
"pts"
,
43
"start_pts"
,
44
"prev_pts"
,
45
"prev_selected_pts"
,
46
47
"t"
,
48
"start_t"
,
49
"prev_t"
,
50
"prev_selected_t"
,
51
52
"pict_type"
,
53
"I"
,
54
"P"
,
55
"B"
,
56
"S"
,
57
"SI"
,
58
"SP"
,
59
"BI"
,
60
61
"interlace_type"
,
62
"PROGRESSIVE"
,
63
"TOPFIRST"
,
64
"BOTTOMFIRST"
,
65
66
"n"
,
67
"selected_n"
,
68
"prev_selected_n"
,
69
70
"key"
,
71
"pos"
,
72
73
NULL
74
};
75
76
enum
var_name
{
77
VAR_E
,
78
VAR_PHI
,
79
VAR_PI
,
80
81
VAR_TB
,
82
83
VAR_PTS
,
84
VAR_START_PTS
,
85
VAR_PREV_PTS
,
86
VAR_PREV_SELECTED_PTS
,
87
88
VAR_T
,
89
VAR_START_T
,
90
VAR_PREV_T
,
91
VAR_PREV_SELECTED_T
,
92
93
VAR_PICT_TYPE
,
94
VAR_PICT_TYPE_I
,
95
VAR_PICT_TYPE_P
,
96
VAR_PICT_TYPE_B
,
97
VAR_PICT_TYPE_S
,
98
VAR_PICT_TYPE_SI
,
99
VAR_PICT_TYPE_SP
,
100
VAR_PICT_TYPE_BI
,
101
102
VAR_INTERLACE_TYPE
,
103
VAR_INTERLACE_TYPE_P
,
104
VAR_INTERLACE_TYPE_T
,
105
VAR_INTERLACE_TYPE_B
,
106
107
VAR_N
,
108
VAR_SELECTED_N
,
109
VAR_PREV_SELECTED_N
,
110
111
VAR_KEY
,
112
113
VAR_VARS_NB
114
};
115
116
#define FIFO_SIZE 8
117
118
typedef
struct
{
119
const
AVClass
*
class
;
120
char
*
expr_str
;
121
AVExpr
*
expr
;
122
double
var_values[
VAR_VARS_NB
];
123
double
select
;
124
int
cache_frames
;
125
AVFifoBuffer
*
pending_frames
;
126
}
SelectContext
;
127
128
static
av_cold
int
init
(
AVFilterContext
*ctx)
129
{
130
SelectContext
*select = ctx->
priv
;
131
int
ret;
132
133
if
((ret =
av_expr_parse
(&select->
expr
, select->
expr_str
,
134
var_names
,
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx)) < 0) {
135
av_log
(ctx,
AV_LOG_ERROR
,
"Error while parsing expression '%s'\n"
,
136
select->
expr_str
);
137
return
ret;
138
}
139
140
select->
pending_frames
=
av_fifo_alloc
(
FIFO_SIZE
*
sizeof
(
AVFrame
*));
141
if
(!select->
pending_frames
) {
142
av_log
(ctx,
AV_LOG_ERROR
,
"Failed to allocate pending frames buffer.\n"
);
143
return
AVERROR
(ENOMEM);
144
}
145
return
0;
146
}
147
148
#define INTERLACE_TYPE_P 0
149
#define INTERLACE_TYPE_T 1
150
#define INTERLACE_TYPE_B 2
151
152
static
int
config_input
(
AVFilterLink
*inlink)
153
{
154
SelectContext
*select = inlink->
dst
->
priv
;
155
156
select->
var_values
[
VAR_E
] =
M_E
;
157
select->
var_values
[
VAR_PHI
] =
M_PHI
;
158
select->
var_values
[
VAR_PI
] = M_PI;
159
160
select->
var_values
[
VAR_N
] = 0.0;
161
select->
var_values
[
VAR_SELECTED_N
] = 0.0;
162
163
select->
var_values
[
VAR_TB
] =
av_q2d
(inlink->
time_base
);
164
165
select->
var_values
[
VAR_PREV_PTS
] =
NAN
;
166
select->
var_values
[
VAR_PREV_SELECTED_PTS
] =
NAN
;
167
select->
var_values
[
VAR_PREV_SELECTED_T
] =
NAN
;
168
select->
var_values
[
VAR_START_PTS
] =
NAN
;
169
select->
var_values
[
VAR_START_T
] =
NAN
;
170
171
select->
var_values
[
VAR_PICT_TYPE_I
] =
AV_PICTURE_TYPE_I
;
172
select->
var_values
[
VAR_PICT_TYPE_P
] =
AV_PICTURE_TYPE_P
;
173
select->
var_values
[
VAR_PICT_TYPE_B
] =
AV_PICTURE_TYPE_B
;
174
select->
var_values
[
VAR_PICT_TYPE_SI
] =
AV_PICTURE_TYPE_SI
;
175
select->
var_values
[
VAR_PICT_TYPE_SP
] =
AV_PICTURE_TYPE_SP
;
176
177
select->
var_values
[
VAR_INTERLACE_TYPE_P
] =
INTERLACE_TYPE_P
;
178
select->
var_values
[
VAR_INTERLACE_TYPE_T
] =
INTERLACE_TYPE_T
;
179
select->
var_values
[
VAR_INTERLACE_TYPE_B
] =
INTERLACE_TYPE_B
;;
180
181
return
0;
182
}
183
184
#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
185
#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
186
187
static
int
select_frame
(
AVFilterContext
*ctx,
AVFrame
*frame)
188
{
189
SelectContext
*select = ctx->
priv
;
190
AVFilterLink
*inlink = ctx->
inputs
[0];
191
double
res;
192
193
if
(
isnan
(select->
var_values
[
VAR_START_PTS
]))
194
select->
var_values
[
VAR_START_PTS
] =
TS2D
(frame->
pts
);
195
if
(
isnan
(select->
var_values
[
VAR_START_T
]))
196
select->
var_values
[
VAR_START_T
] =
TS2D
(frame->
pts
) *
av_q2d
(inlink->
time_base
);
197
198
select->
var_values
[
VAR_PTS
] =
TS2D
(frame->
pts
);
199
select->
var_values
[
VAR_T
] =
TS2D
(frame->
pts
) *
av_q2d
(inlink->
time_base
);
200
select->
var_values
[
VAR_PREV_PTS
] =
TS2D
(frame->
pts
);
201
202
select->
var_values
[
VAR_INTERLACE_TYPE
] =
203
!frame->
interlaced_frame
?
INTERLACE_TYPE_P
:
204
frame->
top_field_first
?
INTERLACE_TYPE_T
:
INTERLACE_TYPE_B
;
205
select->
var_values
[
VAR_PICT_TYPE
] = frame->
pict_type
;
206
207
res =
av_expr_eval
(select->
expr
, select->
var_values
,
NULL
);
208
av_log
(inlink->
dst
,
AV_LOG_DEBUG
,
209
"n:%d pts:%d t:%f interlace_type:%c key:%d pict_type:%c "
210
"-> select:%f\n"
,
211
(
int
)select->
var_values
[
VAR_N
],
212
(
int
)select->
var_values
[
VAR_PTS
],
213
select->
var_values
[
VAR_T
],
214
select->
var_values
[
VAR_INTERLACE_TYPE
] ==
INTERLACE_TYPE_P
?
'P'
:
215
select->
var_values
[
VAR_INTERLACE_TYPE
] ==
INTERLACE_TYPE_T
?
'T'
:
216
select->
var_values
[
VAR_INTERLACE_TYPE
] ==
INTERLACE_TYPE_B
?
'B'
:
'?'
,
217
(
int
)select->
var_values
[
VAR_KEY
],
218
av_get_picture_type_char
(select->
var_values
[
VAR_PICT_TYPE
]),
219
res);
220
221
select->
var_values
[
VAR_N
] += 1.0;
222
223
if
(res) {
224
select->
var_values
[
VAR_PREV_SELECTED_N
] = select->
var_values
[
VAR_N
];
225
select->
var_values
[
VAR_PREV_SELECTED_PTS
] = select->
var_values
[
VAR_PTS
];
226
select->
var_values
[
VAR_PREV_SELECTED_T
] = select->
var_values
[
VAR_T
];
227
select->
var_values
[
VAR_SELECTED_N
] += 1.0;
228
}
229
return
res;
230
}
231
232
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*frame)
233
{
234
SelectContext
*select = inlink->
dst
->
priv
;
235
236
select->
select
=
select_frame
(inlink->
dst
, frame);
237
if
(select->
select
) {
238
/* frame was requested through poll_frame */
239
if
(select->
cache_frames
) {
240
if
(!
av_fifo_space
(select->
pending_frames
)) {
241
av_log
(inlink->
dst
,
AV_LOG_ERROR
,
242
"Buffering limit reached, cannot cache more frames\n"
);
243
av_frame_free
(&frame);
244
}
else
245
av_fifo_generic_write
(select->
pending_frames
, &frame,
246
sizeof
(frame),
NULL
);
247
return
0;
248
}
249
return
ff_filter_frame
(inlink->
dst
->
outputs
[0], frame);
250
}
251
252
av_frame_free
(&frame);
253
return
0;
254
}
255
256
static
int
request_frame
(
AVFilterLink
*outlink)
257
{
258
AVFilterContext
*ctx = outlink->
src
;
259
SelectContext
*select = ctx->
priv
;
260
AVFilterLink
*inlink = outlink->
src
->
inputs
[0];
261
select->
select
= 0;
262
263
if
(
av_fifo_size
(select->
pending_frames
)) {
264
AVFrame
*frame;
265
266
av_fifo_generic_read
(select->
pending_frames
, &frame,
sizeof
(frame),
NULL
);
267
return
ff_filter_frame
(outlink, frame);
268
}
269
270
while
(!select->
select
) {
271
int
ret =
ff_request_frame
(inlink);
272
if
(ret < 0)
273
return
ret;
274
}
275
276
return
0;
277
}
278
279
static
int
poll_frame
(
AVFilterLink
*outlink)
280
{
281
SelectContext
*select = outlink->
src
->
priv
;
282
AVFilterLink
*inlink = outlink->
src
->
inputs
[0];
283
int
count, ret;
284
285
if
(!
av_fifo_size
(select->
pending_frames
)) {
286
if
((count =
ff_poll_frame
(inlink)) <= 0)
287
return
count;
288
/* request frame from input, and apply select condition to it */
289
select->
cache_frames
= 1;
290
while
(count-- &&
av_fifo_space
(select->
pending_frames
)) {
291
ret =
ff_request_frame
(inlink);
292
if
(ret < 0)
293
break
;
294
}
295
select->
cache_frames
= 0;
296
}
297
298
return
av_fifo_size
(select->
pending_frames
)/
sizeof
(
AVFrame
*);
299
}
300
301
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
302
{
303
SelectContext
*select = ctx->
priv
;
304
AVFrame
*frame;
305
306
av_expr_free
(select->
expr
);
307
select->
expr
=
NULL
;
308
309
while
(select->
pending_frames
&&
310
av_fifo_generic_read
(select->
pending_frames
, &frame,
sizeof
(frame),
NULL
) ==
sizeof
(frame))
311
av_frame_free
(&frame);
312
av_fifo_free
(select->
pending_frames
);
313
select->
pending_frames
=
NULL
;
314
}
315
316
#define OFFSET(x) offsetof(SelectContext, x)
317
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
318
static
const
AVOption
options
[] = {
319
{
"expr"
,
"An expression to use for selecting frames"
,
OFFSET
(expr_str),
AV_OPT_TYPE_STRING
, { .str =
"1"
}, .flags =
FLAGS
},
320
{
NULL
},
321
};
322
323
static
const
AVClass
select_class
= {
324
.
class_name
=
"select"
,
325
.item_name =
av_default_item_name
,
326
.option =
options
,
327
.version =
LIBAVUTIL_VERSION_INT
,
328
};
329
330
static
const
AVFilterPad
avfilter_vf_select_inputs
[] = {
331
{
332
.
name
=
"default"
,
333
.type =
AVMEDIA_TYPE_VIDEO
,
334
.get_video_buffer =
ff_null_get_video_buffer
,
335
.config_props =
config_input
,
336
.filter_frame =
filter_frame
,
337
},
338
{
NULL
}
339
};
340
341
static
const
AVFilterPad
avfilter_vf_select_outputs
[] = {
342
{
343
.
name
=
"default"
,
344
.type =
AVMEDIA_TYPE_VIDEO
,
345
.poll_frame =
poll_frame
,
346
.request_frame =
request_frame
,
347
},
348
{
NULL
}
349
};
350
351
AVFilter
ff_vf_select
= {
352
.
name
=
"select"
,
353
.description =
NULL_IF_CONFIG_SMALL
(
"Select frames to pass in output."
),
354
.init =
init
,
355
.uninit =
uninit
,
356
357
.priv_size =
sizeof
(
SelectContext
),
358
.priv_class = &select_class,
359
360
.
inputs
= avfilter_vf_select_inputs,
361
.
outputs
= avfilter_vf_select_outputs,
362
};
Generated on Sun Jun 1 2014 17:55:35 for Libav by
1.8.1.2