2 * copyright (c) 2007 Bobby Bingham
4 * This file is part of FFmpeg.
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.
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.
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
22 * @file libavfilter/vf_crop.c
29 int x
; ///< x offset of the non-cropped area with respect to the input area
30 int y
; ///< y offset of the non-cropped area with respect to the input area
31 int w
; ///< width of the cropped area
32 int h
; ///< height of the cropped area
34 int bpp
; ///< bits per pixel
35 int hsub
, vsub
; ///< chroma subsampling
38 static int query_formats(AVFilterContext
*ctx
)
40 static const enum PixelFormat pix_fmts
[] = {
41 PIX_FMT_RGB48BE
, PIX_FMT_RGB48LE
,
42 PIX_FMT_ARGB
, PIX_FMT_RGBA
,
43 PIX_FMT_ABGR
, PIX_FMT_BGRA
,
44 PIX_FMT_RGB24
, PIX_FMT_BGR24
,
45 PIX_FMT_RGB565BE
, PIX_FMT_RGB565LE
,
46 PIX_FMT_RGB555BE
, PIX_FMT_RGB555LE
,
47 PIX_FMT_BGR565BE
, PIX_FMT_BGR565LE
,
48 PIX_FMT_BGR555BE
, PIX_FMT_BGR555LE
,
49 PIX_FMT_GRAY16BE
, PIX_FMT_GRAY16LE
,
50 PIX_FMT_YUV420P16LE
, PIX_FMT_YUV420P16BE
,
51 PIX_FMT_YUV422P16LE
, PIX_FMT_YUV422P16BE
,
52 PIX_FMT_YUV444P16LE
, PIX_FMT_YUV444P16BE
,
53 PIX_FMT_YUV444P
, PIX_FMT_YUV422P
,
54 PIX_FMT_YUV420P
, PIX_FMT_YUV411P
,
55 PIX_FMT_YUV410P
, PIX_FMT_YUV440P
,
56 PIX_FMT_YUVJ444P
, PIX_FMT_YUVJ422P
,
57 PIX_FMT_YUVJ420P
, PIX_FMT_YUVJ440P
,
59 PIX_FMT_RGB8
, PIX_FMT_BGR8
,
60 PIX_FMT_RGB4_BYTE
, PIX_FMT_BGR4_BYTE
,
61 PIX_FMT_PAL8
, PIX_FMT_GRAY8
,
65 avfilter_set_common_formats(ctx
, avfilter_make_format_list(pix_fmts
));
70 static av_cold
int init(AVFilterContext
*ctx
, const char *args
, void *opaque
)
72 CropContext
*crop
= ctx
->priv
;
75 sscanf(args
, "%d:%d:%d:%d", &crop
->x
, &crop
->y
, &crop
->w
, &crop
->h
);
80 static int config_input(AVFilterLink
*link
)
82 AVFilterContext
*ctx
= link
->dst
;
83 CropContext
*crop
= ctx
->priv
;
85 switch (link
->format
) {
100 case PIX_FMT_RGB565BE
:
101 case PIX_FMT_RGB565LE
:
102 case PIX_FMT_RGB555BE
:
103 case PIX_FMT_RGB555LE
:
104 case PIX_FMT_BGR565BE
:
105 case PIX_FMT_BGR565LE
:
106 case PIX_FMT_BGR555BE
:
107 case PIX_FMT_BGR555LE
:
108 case PIX_FMT_GRAY16BE
:
109 case PIX_FMT_GRAY16LE
:
110 case PIX_FMT_YUV420P16LE
:
111 case PIX_FMT_YUV420P16BE
:
112 case PIX_FMT_YUV422P16LE
:
113 case PIX_FMT_YUV422P16BE
:
114 case PIX_FMT_YUV444P16LE
:
115 case PIX_FMT_YUV444P16BE
:
122 avcodec_get_chroma_sub_sample(link
->format
, &crop
->hsub
, &crop
->vsub
);
125 crop
->w
= link
->w
- crop
->x
;
127 crop
->h
= link
->h
- crop
->y
;
129 crop
->x
&= ~((1 << crop
->hsub
) - 1);
130 crop
->y
&= ~((1 << crop
->vsub
) - 1);
132 av_log(link
->dst
, AV_LOG_INFO
, "x:%d y:%d w:%d h:%d\n",
133 crop
->x
, crop
->y
, crop
->w
, crop
->h
);
135 if (crop
->x
< 0 || crop
->y
< 0 ||
136 crop
->w
<= 0 || crop
->h
<= 0 ||
137 (unsigned)crop
->x
+ (unsigned)crop
->w
> link
->w
||
138 (unsigned)crop
->y
+ (unsigned)crop
->h
> link
->h
) {
139 av_log(ctx
, AV_LOG_ERROR
,
140 "Output area %d:%d:%d:%d not within the input area 0:0:%d:%d or zero-sized\n",
141 crop
->x
, crop
->y
, crop
->w
, crop
->h
, link
->w
, link
->h
);
148 static int config_output(AVFilterLink
*link
)
150 CropContext
*crop
= link
->src
->priv
;
158 static AVFilterPicRef
*get_video_buffer(AVFilterLink
*link
, int perms
,
161 return avfilter_get_video_buffer(link
->dst
->outputs
[0], perms
, w
, h
);
164 static void start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
166 CropContext
*crop
= link
->dst
->priv
;
167 AVFilterPicRef
*ref2
= avfilter_ref_pic(picref
, ~0);
173 ref2
->data
[0] += crop
->y
* ref2
->linesize
[0];
174 ref2
->data
[0] += (crop
->x
* crop
->bpp
) >> 3;
176 if (link
->format
!= PIX_FMT_PAL8
&&
177 link
->format
!= PIX_FMT_BGR4_BYTE
&&
178 link
->format
!= PIX_FMT_RGB4_BYTE
&&
179 link
->format
!= PIX_FMT_BGR8
&&
180 link
->format
!= PIX_FMT_RGB8
) {
181 for (i
= 1; i
< 3; i
++) {
183 ref2
->data
[i
] += (crop
->y
>> crop
->vsub
) * ref2
->linesize
[i
];
184 ref2
->data
[i
] += ((crop
->x
* crop
->bpp
) >> 3) >> crop
->hsub
;
191 ref2
->data
[3] += crop
->y
* ref2
->linesize
[3];
192 ref2
->data
[3] += (crop
->x
* crop
->bpp
) >> 3;
195 avfilter_start_frame(link
->dst
->outputs
[0], ref2
);
198 static void draw_slice(AVFilterLink
*link
, int y
, int h
)
200 AVFilterContext
*ctx
= link
->dst
;
201 CropContext
*crop
= ctx
->priv
;
203 if (y
>= crop
->y
+ crop
->h
|| y
+ h
<= crop
->y
)
210 if (y
+ h
> crop
->y
+ crop
->h
)
211 h
= crop
->y
+ crop
->h
- y
;
213 avfilter_draw_slice(ctx
->outputs
[0], y
- crop
->y
, h
);
216 AVFilter avfilter_vf_crop
= {
218 .description
= NULL_IF_CONFIG_SMALL("Crop the input video to x:y:width:height."),
220 .priv_size
= sizeof(CropContext
),
222 .query_formats
= query_formats
,
225 .inputs
= (AVFilterPad
[]) {{ .name
= "default",
226 .type
= CODEC_TYPE_VIDEO
,
227 .start_frame
= start_frame
,
228 .draw_slice
= draw_slice
,
229 .get_video_buffer
= get_video_buffer
,
230 .config_props
= config_input
, },
232 .outputs
= (AVFilterPad
[]) {{ .name
= "default",
233 .type
= CODEC_TYPE_VIDEO
,
234 .config_props
= config_output
, },