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
23 * video slicing filter
27 #include "libavutil/pixdesc.h"
30 int h
; ///< output slice height
31 int vshift
; ///< vertical chroma subsampling shift
32 uint32_t lcg_state
; ///< LCG state used to compute random slice height
33 int use_random_h
; ///< enable the use of random slice height values
36 static av_cold
int init(AVFilterContext
*ctx
, const char *args
, void *opaque
)
38 SliceContext
*slice
= ctx
->priv
;
42 if (!strcmp(args
, "random")) {
43 slice
->use_random_h
= 1;
45 sscanf(args
, "%d", &slice
->h
);
51 static int config_props(AVFilterLink
*link
)
53 SliceContext
*slice
= link
->dst
->priv
;
55 slice
->vshift
= av_pix_fmt_descriptors
[link
->format
].log2_chroma_h
;
60 static void start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
62 SliceContext
*slice
= link
->dst
->priv
;
64 if (slice
->use_random_h
) {
65 slice
->lcg_state
= slice
->lcg_state
* 1664525 + 1013904223;
66 slice
->h
= 8 + (uint64_t)slice
->lcg_state
* 25 / UINT32_MAX
;
69 /* ensure that slices play nice with chroma subsampling, and enforce
70 * a reasonable minimum size for the slices */
71 slice
->h
= FFMAX(8, slice
->h
& (-1 << slice
->vshift
));
73 av_log(link
->dst
, AV_LOG_DEBUG
, "h:%d\n", slice
->h
);
75 avfilter_start_frame(link
->dst
->outputs
[0], picref
);
78 static void draw_slice(AVFilterLink
*link
, int y
, int h
, int slice_dir
)
80 SliceContext
*slice
= link
->dst
->priv
;
84 for (y2
= y
; y2
+ slice
->h
<= y
+ h
; y2
+= slice
->h
)
85 avfilter_draw_slice(link
->dst
->outputs
[0], y2
, slice
->h
, slice_dir
);
88 avfilter_draw_slice(link
->dst
->outputs
[0], y2
, y
+ h
- y2
, slice_dir
);
89 } else if (slice_dir
== -1) {
90 for (y2
= y
+ h
; y2
- slice
->h
>= y
; y2
-= slice
->h
)
91 avfilter_draw_slice(link
->dst
->outputs
[0], y2
- slice
->h
, slice
->h
, slice_dir
);
94 avfilter_draw_slice(link
->dst
->outputs
[0], y
, y2
- y
, slice_dir
);
98 AVFilter avfilter_vf_slicify
= {
100 .description
= "Pass the images of input video on to next video filter as multiple slices.",
104 .priv_size
= sizeof(SliceContext
),
106 .inputs
= (AVFilterPad
[]) {{ .name
= "default",
107 .type
= AVMEDIA_TYPE_VIDEO
,
108 .get_video_buffer
= avfilter_null_get_video_buffer
,
109 .start_frame
= start_frame
,
110 .draw_slice
= draw_slice
,
111 .config_props
= config_props
,
112 .end_frame
= avfilter_null_end_frame
, },
114 .outputs
= (AVFilterPad
[]) {{ .name
= "default",
115 .type
= AVMEDIA_TYPE_VIDEO
, },