Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavfilter
vf_cropdetect.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2002 A'rpi
3
* This file is part of Libav.
4
*
5
* Libav is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
9
*
10
* Libav is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License along
16
* with Libav; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
*/
19
26
#include "
libavutil/imgutils.h
"
27
#include "
avfilter.h
"
28
29
typedef
struct
{
30
int
x1, y1, x2,
y2
;
31
int
limit
;
32
int
round
;
33
int
reset_count
;
34
int
frame_nb
;
35
int
max_pixsteps[4];
36
}
CropDetectContext
;
37
38
static
int
query_formats
(
AVFilterContext
*ctx)
39
{
40
static
const
enum
PixelFormat
pix_fmts[] = {
41
PIX_FMT_YUV420P
,
PIX_FMT_YUVJ420P
,
42
PIX_FMT_YUV422P
,
PIX_FMT_YUVJ422P
,
43
PIX_FMT_YUV444P
,
PIX_FMT_YUVJ444P
,
44
PIX_FMT_YUV411P
,
PIX_FMT_GRAY8
,
45
PIX_FMT_NV12
,
PIX_FMT_NV21
,
46
PIX_FMT_NONE
47
};
48
49
avfilter_set_common_formats
(ctx,
avfilter_make_format_list
(pix_fmts));
50
return
0;
51
}
52
53
static
int
checkline
(
void
*ctx,
const
unsigned
char
*src,
int
stride
,
int
len
,
int
bpp)
54
{
55
int
total = 0;
56
int
div =
len
;
57
58
switch
(bpp) {
59
case
1:
60
while
(--len >= 0) {
61
total += src[0];
62
src +=
stride
;
63
}
64
break
;
65
case
3:
66
case
4:
67
while
(--len >= 0) {
68
total += src[0] + src[1] + src[2];
69
src +=
stride
;
70
}
71
div *= 3;
72
break
;
73
}
74
total /= div;
75
76
av_log
(ctx,
AV_LOG_DEBUG
,
"total:%d\n"
, total);
77
return
total;
78
}
79
80
static
av_cold
int
init
(
AVFilterContext
*ctx,
const
char
*args,
void
*opaque)
81
{
82
CropDetectContext
*cd = ctx->
priv
;
83
84
cd->
limit
= 24;
85
cd->
round
= 0;
86
cd->
reset_count
= 0;
87
cd->
frame_nb
= -2;
88
89
if
(args)
90
sscanf(args,
"%d:%d:%d"
, &cd->
limit
, &cd->
round
, &cd->
reset_count
);
91
92
av_log
(ctx,
AV_LOG_INFO
,
"limit:%d round:%d reset_count:%d\n"
,
93
cd->
limit
, cd->
round
, cd->
reset_count
);
94
95
return
0;
96
}
97
98
static
int
config_input
(
AVFilterLink
*inlink)
99
{
100
AVFilterContext
*ctx = inlink->
dst
;
101
CropDetectContext
*cd = ctx->
priv
;
102
103
av_image_fill_max_pixsteps
(cd->
max_pixsteps
,
NULL
,
104
&
av_pix_fmt_descriptors
[inlink->
format
]);
105
106
cd->
x1
= inlink->
w
- 1;
107
cd->
y1
= inlink->
h
- 1;
108
cd->
x2
= 0;
109
cd->
y2
= 0;
110
111
return
0;
112
}
113
114
static
void
end_frame
(
AVFilterLink
*inlink)
115
{
116
AVFilterContext
*ctx = inlink->
dst
;
117
CropDetectContext
*cd = ctx->
priv
;
118
AVFilterBufferRef
*picref = inlink->
cur_buf
;
119
int
bpp = cd->
max_pixsteps
[0];
120
int
w, h, x, y, shrink_by;
121
122
// ignore first 2 frames - they may be empty
123
if
(++cd->
frame_nb
> 0) {
124
// Reset the crop area every reset_count frames, if reset_count is > 0
125
if
(cd->
reset_count
> 0 && cd->
frame_nb
> cd->
reset_count
) {
126
cd->
x1
= picref->
video
->
w
-1;
127
cd->
y1
= picref->
video
->
h
-1;
128
cd->
x2
= 0;
129
cd->
y2
= 0;
130
cd->
frame_nb
= 1;
131
}
132
133
for
(y = 0; y < cd->
y1
; y++) {
134
if
(
checkline
(ctx, picref->
data
[0] + picref->
linesize
[0] * y, bpp, picref->
video
->
w
, bpp) > cd->
limit
) {
135
cd->
y1
= y;
136
break
;
137
}
138
}
139
140
for
(y = picref->
video
->
h
-1; y > cd->
y2
; y--) {
141
if
(
checkline
(ctx, picref->
data
[0] + picref->
linesize
[0] * y, bpp, picref->
video
->
w
, bpp) > cd->
limit
) {
142
cd->
y2
= y;
143
break
;
144
}
145
}
146
147
for
(y = 0; y < cd->
x1
; y++) {
148
if
(
checkline
(ctx, picref->
data
[0] + bpp*y, picref->
linesize
[0], picref->
video
->
h
, bpp) > cd->
limit
) {
149
cd->
x1
= y;
150
break
;
151
}
152
}
153
154
for
(y = picref->
video
->
w
-1; y > cd->
x2
; y--) {
155
if
(
checkline
(ctx, picref->
data
[0] + bpp*y, picref->
linesize
[0], picref->
video
->
h
, bpp) > cd->
limit
) {
156
cd->
x2
= y;
157
break
;
158
}
159
}
160
161
// round x and y (up), important for yuv colorspaces
162
// make sure they stay rounded!
163
x = (cd->
x1
+1) & ~1;
164
y = (cd->
y1
+1) & ~1;
165
166
w = cd->
x2
- x + 1;
167
h = cd->
y2
- y + 1;
168
169
// w and h must be divisible by 2 as well because of yuv
170
// colorspace problems.
171
if
(cd->
round
<= 1)
172
cd->
round
= 16;
173
if
(cd->
round
% 2)
174
cd->
round
*= 2;
175
176
shrink_by = w % cd->
round
;
177
w -= shrink_by;
178
x += (shrink_by/2 + 1) & ~1;
179
180
shrink_by = h % cd->
round
;
181
h -= shrink_by;
182
y += (shrink_by/2 + 1) & ~1;
183
184
av_log
(ctx,
AV_LOG_INFO
,
185
"x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pos:%"
PRId64
" pts:%"
PRId64
" t:%f crop=%d:%d:%d:%d\n"
,
186
cd->
x1
, cd->
x2
, cd->
y1
, cd->
y2
, w, h, x, y, picref->
pos
, picref->
pts
,
187
picref->
pts
==
AV_NOPTS_VALUE
? -1 : picref->
pts
*
av_q2d
(inlink->
time_base
),
188
w, h, x, y);
189
}
190
191
avfilter_end_frame
(inlink->
dst
->
outputs
[0]);
192
}
193
194
AVFilter
avfilter_vf_cropdetect
= {
195
.
name
=
"cropdetect"
,
196
.description =
NULL_IF_CONFIG_SMALL
(
"Auto-detect crop size."
),
197
198
.priv_size =
sizeof
(
CropDetectContext
),
199
.
init
=
init
,
200
201
.
query_formats
=
query_formats
,
202
203
.inputs = (
AVFilterPad
[]) {{ .name =
"default"
,
204
.type =
AVMEDIA_TYPE_VIDEO
,
205
.config_props =
config_input
,
206
.get_video_buffer =
avfilter_null_get_video_buffer
,
207
.start_frame =
avfilter_null_start_frame
,
208
.end_frame =
end_frame
, },
209
{ .name =
NULL
}},
210
211
.outputs = (
AVFilterPad
[]) {{ .name =
"default"
,
212
.type =
AVMEDIA_TYPE_VIDEO
},
213
{ .name =
NULL
}},
214
};