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_extractplanes.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/avstring.h
"
22
#include "
libavutil/imgutils.h
"
23
#include "
libavutil/opt.h
"
24
#include "
libavutil/pixdesc.h
"
25
#include "
avfilter.h
"
26
#include "
drawutils.h
"
27
#include "
internal.h
"
28
29
#define PLANE_R 0x01
30
#define PLANE_G 0x02
31
#define PLANE_B 0x04
32
#define PLANE_A 0x08
33
#define PLANE_Y 0x10
34
#define PLANE_U 0x20
35
#define PLANE_V 0x40
36
37
typedef
struct
{
38
const
AVClass
*
class
;
39
int
requested_planes
;
40
int
map[4];
41
int
linesize[4];
42
int
is_packed_rgb
;
43
int
depth
;
44
int
step
;
45
}
ExtractPlanesContext
;
46
47
#define OFFSET(x) offsetof(ExtractPlanesContext, x)
48
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
49
static
const
AVOption
extractplanes_options
[] = {
50
{
"planes"
,
"set planes"
,
OFFSET
(requested_planes),
AV_OPT_TYPE_FLAGS
, {.i64=1}, 1, 0xff,
FLAGS
,
"flags"
},
51
{
"y"
,
"set luma plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_Y
}, 0, 0,
FLAGS
,
"flags"
},
52
{
"u"
,
"set u plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_U
}, 0, 0,
FLAGS
,
"flags"
},
53
{
"v"
,
"set v plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_V
}, 0, 0,
FLAGS
,
"flags"
},
54
{
"r"
,
"set red plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_R
}, 0, 0,
FLAGS
,
"flags"
},
55
{
"g"
,
"set green plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_G
}, 0, 0,
FLAGS
,
"flags"
},
56
{
"b"
,
"set blue plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_B
}, 0, 0,
FLAGS
,
"flags"
},
57
{
"a"
,
"set alpha plane"
, 0,
AV_OPT_TYPE_CONST
, {.i64=
PLANE_A
}, 0, 0,
FLAGS
,
"flags"
},
58
{ NULL }
59
};
60
61
AVFILTER_DEFINE_CLASS
(extractplanes);
62
63
static
int
query_formats
(
AVFilterContext
*ctx)
64
{
65
static
const
enum
AVPixelFormat
in_pixfmts[] = {
66
AV_PIX_FMT_YUV410P
,
67
AV_PIX_FMT_YUV411P
,
68
AV_PIX_FMT_YUV440P
,
69
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUVA420P
,
70
AV_PIX_FMT_YUV422P
,
AV_PIX_FMT_YUVA422P
,
71
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ422P
,
72
AV_PIX_FMT_YUVJ440P
,
AV_PIX_FMT_YUVJ444P
,
73
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUVA444P
,
74
AV_PIX_FMT_YUV420P16LE
,
AV_PIX_FMT_YUVA420P16LE
,
75
AV_PIX_FMT_YUV420P16BE
,
AV_PIX_FMT_YUVA420P16BE
,
76
AV_PIX_FMT_YUV422P16LE
,
AV_PIX_FMT_YUVA422P16LE
,
77
AV_PIX_FMT_YUV422P16BE
,
AV_PIX_FMT_YUVA422P16BE
,
78
AV_PIX_FMT_YUV444P16LE
,
AV_PIX_FMT_YUVA444P16LE
,
79
AV_PIX_FMT_YUV444P16BE
,
AV_PIX_FMT_YUVA444P16BE
,
80
AV_PIX_FMT_GRAY8
,
AV_PIX_FMT_GRAY8A
,
81
AV_PIX_FMT_GRAY16LE
,
AV_PIX_FMT_GRAY16BE
,
82
AV_PIX_FMT_RGB24
,
AV_PIX_FMT_BGR24
,
83
AV_PIX_FMT_RGBA
,
AV_PIX_FMT_BGRA
,
84
AV_PIX_FMT_ARGB
,
AV_PIX_FMT_ABGR
,
85
AV_PIX_FMT_RGB48LE
,
AV_PIX_FMT_BGR48LE
,
86
AV_PIX_FMT_RGB48BE
,
AV_PIX_FMT_BGR48BE
,
87
AV_PIX_FMT_RGBA64LE
,
AV_PIX_FMT_BGRA64LE
,
88
AV_PIX_FMT_RGBA64BE
,
AV_PIX_FMT_BGRA64BE
,
89
AV_PIX_FMT_GBRP
,
AV_PIX_FMT_GBRAP
,
90
AV_PIX_FMT_GBRP16LE
,
AV_PIX_FMT_GBRP16BE
,
91
AV_PIX_FMT_GBRAP16LE
,
AV_PIX_FMT_GBRAP16BE
,
92
AV_PIX_FMT_NONE
,
93
};
94
static
const
enum
AVPixelFormat
out8_pixfmts[] = {
AV_PIX_FMT_GRAY8
,
AV_PIX_FMT_NONE
};
95
static
const
enum
AVPixelFormat
out16le_pixfmts[] = {
AV_PIX_FMT_GRAY16LE
,
AV_PIX_FMT_NONE
};
96
static
const
enum
AVPixelFormat
out16be_pixfmts[] = {
AV_PIX_FMT_GRAY16BE
,
AV_PIX_FMT_NONE
};
97
const
enum
AVPixelFormat
*out_pixfmts;
98
const
AVPixFmtDescriptor
*desc;
99
AVFilterFormats
*avff;
100
int
i,
depth
= 0, be = 0;
101
102
if
(!ctx->
inputs
[0]->
in_formats
||
103
!ctx->
inputs
[0]->
in_formats
->
nb_formats
) {
104
return
AVERROR
(EAGAIN);
105
}
106
107
if
(!ctx->
inputs
[0]->
out_formats
)
108
ff_formats_ref
(
ff_make_format_list
(in_pixfmts), &ctx->
inputs
[0]->
out_formats
);
109
110
avff = ctx->
inputs
[0]->
in_formats
;
111
desc =
av_pix_fmt_desc_get
(avff->
formats
[0]);
112
depth = desc->
comp
[0].
depth_minus1
;
113
be = desc->
flags
&
AV_PIX_FMT_FLAG_BE
;
114
for
(i = 1; i < avff->
nb_formats
; i++) {
115
desc =
av_pix_fmt_desc_get
(avff->
formats
[i]);
116
if
(depth != desc->
comp
[0].
depth_minus1
||
117
be != (desc->
flags
&
AV_PIX_FMT_FLAG_BE
)) {
118
return
AVERROR
(EAGAIN);
119
}
120
}
121
122
if
(depth == 7)
123
out_pixfmts = out8_pixfmts;
124
else
if
(be)
125
out_pixfmts = out16be_pixfmts;
126
else
127
out_pixfmts = out16le_pixfmts;
128
129
for
(i = 0; i < ctx->
nb_outputs
; i++)
130
ff_formats_ref
(
ff_make_format_list
(out_pixfmts), &ctx->
outputs
[i]->
in_formats
);
131
return
0;
132
}
133
134
static
int
config_input
(
AVFilterLink
*inlink)
135
{
136
AVFilterContext
*ctx = inlink->
dst
;
137
ExtractPlanesContext
*e = ctx->
priv
;
138
const
AVPixFmtDescriptor
*desc =
av_pix_fmt_desc_get
(inlink->
format
);
139
int
plane_avail,
ret
, i;
140
uint8_t
rgba_map[4];
141
142
plane_avail = ((desc->
flags
&
AV_PIX_FMT_FLAG_RGB
) ?
PLANE_R
|
PLANE_G
|
PLANE_B
:
143
PLANE_Y
|
144
((desc->
nb_components
> 2) ?
PLANE_U
|
PLANE_V
: 0)) |
145
((desc->
flags
&
AV_PIX_FMT_FLAG_ALPHA
) ?
PLANE_A
: 0);
146
if
(e->
requested_planes
& ~plane_avail) {
147
av_log
(ctx,
AV_LOG_ERROR
,
"Requested planes not available.\n"
);
148
return
AVERROR
(EINVAL);
149
}
150
if
((ret =
av_image_fill_linesizes
(e->
linesize
, inlink->
format
, inlink->
w
)) < 0)
151
return
ret
;
152
153
e->
depth
= (desc->
comp
[0].
depth_minus1
+ 1) >> 3;
154
e->
step
=
av_get_padded_bits_per_pixel
(desc) >> 3;
155
e->
is_packed_rgb
= !(desc->
flags
&
AV_PIX_FMT_FLAG_PLANAR
);
156
if
(desc->
flags
&
AV_PIX_FMT_FLAG_RGB
) {
157
ff_fill_rgba_map
(rgba_map, inlink->
format
);
158
for
(i = 0; i < 4; i++)
159
e->
map
[i] = rgba_map[e->
map
[i]];
160
}
161
162
return
0;
163
}
164
165
static
int
config_output
(
AVFilterLink
*outlink)
166
{
167
AVFilterContext
*ctx = outlink->
src
;
168
AVFilterLink
*inlink = ctx->
inputs
[0];
169
ExtractPlanesContext
*e = ctx->
priv
;
170
const
AVPixFmtDescriptor
*desc =
av_pix_fmt_desc_get
(inlink->
format
);
171
const
int
output = outlink->
srcpad
- ctx->
output_pads
;
172
173
if
(e->
map
[output] == 1 || e->
map
[output] == 2) {
174
outlink->
h
=
FF_CEIL_RSHIFT
(inlink->
h
, desc->
log2_chroma_h
);
175
outlink->
w
=
FF_CEIL_RSHIFT
(inlink->
w
, desc->
log2_chroma_w
);
176
}
177
178
return
0;
179
}
180
181
static
void
extract_from_packed
(
uint8_t
*dst,
int
dst_linesize,
182
const
uint8_t
*
src
,
int
src_linesize,
183
int
width
,
int
height
,
184
int
depth
,
int
step,
int
comp
)
185
{
186
int
x,
y
;
187
188
for
(y = 0; y <
height
; y++) {
189
switch
(depth) {
190
case
1:
191
for
(x = 0; x <
width
; x++)
192
dst[x] = src[x * step + comp];
193
break
;
194
case
2:
195
for
(x = 0; x <
width
; x++) {
196
dst[x * 2 ] = src[x * step + comp * 2 ];
197
dst[x * 2 + 1] = src[x * step + comp * 2 + 1];
198
}
199
break
;
200
}
201
dst += dst_linesize;
202
src += src_linesize;
203
}
204
}
205
206
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*
frame
)
207
{
208
AVFilterContext
*ctx = inlink->
dst
;
209
ExtractPlanesContext
*e = ctx->
priv
;
210
int
i, eof = 0,
ret
= 0;
211
212
for
(i = 0; i < ctx->
nb_outputs
; i++) {
213
AVFilterLink
*outlink = ctx->
outputs
[i];
214
const
int
idx = e->
map
[i];
215
AVFrame
*
out
;
216
217
if
(outlink->
closed
)
218
continue
;
219
220
out =
ff_get_video_buffer
(outlink, outlink->
w
, outlink->
h
);
221
if
(!out) {
222
ret
=
AVERROR
(ENOMEM);
223
break
;
224
}
225
av_frame_copy_props
(out, frame);
226
227
if
(e->
is_packed_rgb
) {
228
extract_from_packed
(out->
data
[0], out->
linesize
[0],
229
frame->
data
[0], frame->
linesize
[0],
230
outlink->
w
, outlink->
h
,
231
e->
depth
,
232
e->
step
, idx);
233
}
else
{
234
av_image_copy_plane
(out->
data
[0], out->
linesize
[0],
235
frame->
data
[idx], frame->
linesize
[idx],
236
e->
linesize
[idx], outlink->
h
);
237
}
238
239
ret
=
ff_filter_frame
(outlink, out);
240
if
(
ret
==
AVERROR_EOF
)
241
eof++;
242
else
if
(
ret
< 0)
243
break
;
244
}
245
av_frame_free
(&frame);
246
247
if
(eof == ctx->
nb_outputs
)
248
ret
=
AVERROR_EOF
;
249
else
if
(
ret
==
AVERROR_EOF
)
250
ret
= 0;
251
return
ret
;
252
}
253
254
static
av_cold
int
init
(
AVFilterContext
*ctx)
255
{
256
ExtractPlanesContext
*e = ctx->
priv
;
257
int
planes = (e->
requested_planes
& 0xf) | (e->
requested_planes
>> 4);
258
int
i;
259
260
for
(i = 0; i < 4; i++) {
261
char
*
name
;
262
AVFilterPad
pad = { 0 };
263
264
if
(!(planes & (1 << i)))
265
continue
;
266
267
name =
av_asprintf
(
"out%d"
, ctx->
nb_outputs
);
268
if
(!name)
269
return
AVERROR
(ENOMEM);
270
e->
map
[ctx->
nb_outputs
] = i;
271
pad.
name
=
name
;
272
pad.
type
=
AVMEDIA_TYPE_VIDEO
;
273
pad.
config_props
=
config_output
;
274
275
ff_insert_outpad
(ctx, ctx->
nb_outputs
, &pad);
276
}
277
278
return
0;
279
}
280
281
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
282
{
283
int
i;
284
285
for
(i = 0; i < ctx->
nb_outputs
; i++)
286
av_freep
(&ctx->
output_pads
[i].
name
);
287
}
288
289
static
const
AVFilterPad
extractplanes_inputs
[] = {
290
{
291
.
name
=
"default"
,
292
.type =
AVMEDIA_TYPE_VIDEO
,
293
.filter_frame =
filter_frame
,
294
.config_props =
config_input
,
295
},
296
{ NULL }
297
};
298
299
AVFilter
ff_vf_extractplanes
= {
300
.
name
=
"extractplanes"
,
301
.description =
NULL_IF_CONFIG_SMALL
(
"Extract planes as grayscale frames."
),
302
.priv_size =
sizeof
(
ExtractPlanesContext
),
303
.priv_class = &extractplanes_class,
304
.
init
=
init
,
305
.
uninit
=
uninit
,
306
.
query_formats
=
query_formats
,
307
.
inputs
= extractplanes_inputs,
308
.
outputs
= NULL,
309
.
flags
=
AVFILTER_FLAG_DYNAMIC_OUTPUTS
,
310
};
311
312
#if CONFIG_ALPHAEXTRACT_FILTER
313
314
static
av_cold
int
init_alphaextract(
AVFilterContext
*ctx)
315
{
316
ExtractPlanesContext
*e = ctx->
priv
;
317
318
e->
requested_planes
=
PLANE_A
;
319
320
return
init
(ctx);
321
}
322
323
AVFilter
ff_vf_alphaextract = {
324
.
name
=
"alphaextract"
,
325
.description =
NULL_IF_CONFIG_SMALL
(
"Extract an alpha channel as a "
326
"grayscale image component."
),
327
.priv_size =
sizeof
(
ExtractPlanesContext
),
328
.
init
= init_alphaextract,
329
.
uninit
=
uninit
,
330
.
query_formats
=
query_formats
,
331
.
inputs
= extractplanes_inputs,
332
.
outputs
= NULL,
333
.
flags
=
AVFILTER_FLAG_DYNAMIC_OUTPUTS
,
334
};
335
#endif
/* CONFIG_ALPHAEXTRACT_FILTER */
Generated on Sun Mar 23 2014 23:50:09 for FFmpeg by
1.8.2