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
27 #include "libavutil/pixdesc.h"
30 int x
; ///< x offset of the non-cropped area with respect to the input area
31 int y
; ///< y offset of the non-cropped area with respect to the input area
32 int w
; ///< width of the cropped area
33 int h
; ///< height of the cropped area
35 int bpp
; ///< bits per pixel
36 int hsub
, vsub
; ///< chroma subsampling
39 static int query_formats(AVFilterContext
*ctx
)
41 static const enum PixelFormat pix_fmts
[] = {
42 PIX_FMT_RGB48BE
, PIX_FMT_RGB48LE
,
43 PIX_FMT_ARGB
, PIX_FMT_RGBA
,
44 PIX_FMT_ABGR
, PIX_FMT_BGRA
,
45 PIX_FMT_RGB24
, PIX_FMT_BGR24
,
46 PIX_FMT_RGB565BE
, PIX_FMT_RGB565LE
,
47 PIX_FMT_RGB555BE
, PIX_FMT_RGB555LE
,
48 PIX_FMT_BGR565BE
, PIX_FMT_BGR565LE
,
49 PIX_FMT_BGR555BE
, PIX_FMT_BGR555LE
,
50 PIX_FMT_GRAY16BE
, PIX_FMT_GRAY16LE
,
51 PIX_FMT_YUV420P16LE
, PIX_FMT_YUV420P16BE
,
52 PIX_FMT_YUV422P16LE
, PIX_FMT_YUV422P16BE
,
53 PIX_FMT_YUV444P16LE
, PIX_FMT_YUV444P16BE
,
54 PIX_FMT_YUV444P
, PIX_FMT_YUV422P
,
55 PIX_FMT_YUV420P
, PIX_FMT_YUV411P
,
56 PIX_FMT_YUV410P
, PIX_FMT_YUV440P
,
57 PIX_FMT_YUVJ444P
, PIX_FMT_YUVJ422P
,
58 PIX_FMT_YUVJ420P
, PIX_FMT_YUVJ440P
,
60 PIX_FMT_RGB8
, PIX_FMT_BGR8
,
61 PIX_FMT_RGB4_BYTE
, PIX_FMT_BGR4_BYTE
,
62 PIX_FMT_PAL8
, PIX_FMT_GRAY8
,
66 avfilter_set_common_formats(ctx
, avfilter_make_format_list(pix_fmts
));
71 static av_cold
int init(AVFilterContext
*ctx
, const char *args
, void *opaque
)
73 CropContext
*crop
= ctx
->priv
;
76 sscanf(args
, "%d:%d:%d:%d", &crop
->x
, &crop
->y
, &crop
->w
, &crop
->h
);
81 static int config_input(AVFilterLink
*link
)
83 AVFilterContext
*ctx
= link
->dst
;
84 CropContext
*crop
= ctx
->priv
;
86 switch (link
->format
) {
101 case PIX_FMT_RGB565BE
:
102 case PIX_FMT_RGB565LE
:
103 case PIX_FMT_RGB555BE
:
104 case PIX_FMT_RGB555LE
:
105 case PIX_FMT_BGR565BE
:
106 case PIX_FMT_BGR565LE
:
107 case PIX_FMT_BGR555BE
:
108 case PIX_FMT_BGR555LE
:
109 case PIX_FMT_GRAY16BE
:
110 case PIX_FMT_GRAY16LE
:
111 case PIX_FMT_YUV420P16LE
:
112 case PIX_FMT_YUV420P16BE
:
113 case PIX_FMT_YUV422P16LE
:
114 case PIX_FMT_YUV422P16BE
:
115 case PIX_FMT_YUV444P16LE
:
116 case PIX_FMT_YUV444P16BE
:
123 avcodec_get_chroma_sub_sample(link
->format
, &crop
->hsub
, &crop
->vsub
);
126 crop
->w
= link
->w
- crop
->x
;
128 crop
->h
= link
->h
- crop
->y
;
130 crop
->x
&= ~((1 << crop
->hsub
) - 1);
131 crop
->y
&= ~((1 << crop
->vsub
) - 1);
133 av_log(link
->dst
, AV_LOG_INFO
, "x:%d y:%d w:%d h:%d\n",
134 crop
->x
, crop
->y
, crop
->w
, crop
->h
);
136 if (crop
->x
< 0 || crop
->y
< 0 ||
137 crop
->w
<= 0 || crop
->h
<= 0 ||
138 (unsigned)crop
->x
+ (unsigned)crop
->w
> link
->w
||
139 (unsigned)crop
->y
+ (unsigned)crop
->h
> link
->h
) {
140 av_log(ctx
, AV_LOG_ERROR
,
141 "Output area %d:%d:%d:%d not within the input area 0:0:%d:%d or zero-sized\n",
142 crop
->x
, crop
->y
, crop
->w
, crop
->h
, link
->w
, link
->h
);
149 static int config_output(AVFilterLink
*link
)
151 CropContext
*crop
= link
->src
->priv
;
159 static void start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
161 CropContext
*crop
= link
->dst
->priv
;
162 AVFilterPicRef
*ref2
= avfilter_ref_pic(picref
, ~0);
168 ref2
->data
[0] += crop
->y
* ref2
->linesize
[0];
169 ref2
->data
[0] += (crop
->x
* crop
->bpp
) >> 3;
171 if (!(av_pix_fmt_descriptors
[link
->format
].flags
& PIX_FMT_PAL
)) {
172 for (i
= 1; i
< 3; i
++) {
174 ref2
->data
[i
] += (crop
->y
>> crop
->vsub
) * ref2
->linesize
[i
];
175 ref2
->data
[i
] += ((crop
->x
* crop
->bpp
) >> 3) >> crop
->hsub
;
182 ref2
->data
[3] += crop
->y
* ref2
->linesize
[3];
183 ref2
->data
[3] += (crop
->x
* crop
->bpp
) >> 3;
186 avfilter_start_frame(link
->dst
->outputs
[0], ref2
);
189 static void draw_slice(AVFilterLink
*link
, int y
, int h
, int slice_dir
)
191 AVFilterContext
*ctx
= link
->dst
;
192 CropContext
*crop
= ctx
->priv
;
194 if (y
>= crop
->y
+ crop
->h
|| y
+ h
<= crop
->y
)
201 if (y
+ h
> crop
->y
+ crop
->h
)
202 h
= crop
->y
+ crop
->h
- y
;
204 avfilter_draw_slice(ctx
->outputs
[0], y
- crop
->y
, h
, slice_dir
);
207 AVFilter avfilter_vf_crop
= {
209 .description
= NULL_IF_CONFIG_SMALL("Crop the input video to x:y:width:height."),
211 .priv_size
= sizeof(CropContext
),
213 .query_formats
= query_formats
,
216 .inputs
= (AVFilterPad
[]) {{ .name
= "default",
217 .type
= AVMEDIA_TYPE_VIDEO
,
218 .start_frame
= start_frame
,
219 .draw_slice
= draw_slice
,
220 .get_video_buffer
= avfilter_null_get_video_buffer
,
221 .config_props
= config_input
, },
223 .outputs
= (AVFilterPad
[]) {{ .name
= "default",
224 .type
= AVMEDIA_TYPE_VIDEO
,
225 .config_props
= config_output
, },