00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "avfilter.h"
00027 #include "libavutil/pixdesc.h"
00028
00029 typedef struct {
00030 int h;
00031 int vshift;
00032 uint32_t lcg_state;
00033 int use_random_h;
00034 } SliceContext;
00035
00036 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
00037 {
00038 SliceContext *slice = ctx->priv;
00039
00040 slice->h = 16;
00041 if (args) {
00042 if (!strcmp(args, "random")) {
00043 slice->use_random_h = 1;
00044 } else {
00045 sscanf(args, "%d", &slice->h);
00046 }
00047 }
00048 return 0;
00049 }
00050
00051 static int config_props(AVFilterLink *link)
00052 {
00053 SliceContext *slice = link->dst->priv;
00054
00055 slice->vshift = av_pix_fmt_descriptors[link->format].log2_chroma_h;
00056
00057 return 0;
00058 }
00059
00060 static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
00061 {
00062 SliceContext *slice = link->dst->priv;
00063
00064 if (slice->use_random_h) {
00065 slice->lcg_state = slice->lcg_state * 1664525 + 1013904223;
00066 slice->h = 8 + (uint64_t)slice->lcg_state * 25 / UINT32_MAX;
00067 }
00068
00069
00070
00071 slice->h = FFMAX(8, slice->h & (-1 << slice->vshift));
00072
00073 av_log(link->dst, AV_LOG_DEBUG, "h:%d\n", slice->h);
00074
00075 avfilter_start_frame(link->dst->outputs[0], picref);
00076 }
00077
00078 static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00079 {
00080 SliceContext *slice = link->dst->priv;
00081 int y2;
00082
00083 if (slice_dir == 1) {
00084 for (y2 = y; y2 + slice->h <= y + h; y2 += slice->h)
00085 avfilter_draw_slice(link->dst->outputs[0], y2, slice->h, slice_dir);
00086
00087 if (y2 < y + h)
00088 avfilter_draw_slice(link->dst->outputs[0], y2, y + h - y2, slice_dir);
00089 } else if (slice_dir == -1) {
00090 for (y2 = y + h; y2 - slice->h >= y; y2 -= slice->h)
00091 avfilter_draw_slice(link->dst->outputs[0], y2 - slice->h, slice->h, slice_dir);
00092
00093 if (y2 > y)
00094 avfilter_draw_slice(link->dst->outputs[0], y, y2 - y, slice_dir);
00095 }
00096 }
00097
00098 AVFilter avfilter_vf_slicify = {
00099 .name = "slicify",
00100 .description = NULL_IF_CONFIG_SMALL("Pass the images of input video on to next video filter as multiple slices."),
00101
00102 .init = init,
00103
00104 .priv_size = sizeof(SliceContext),
00105
00106 .inputs = (AVFilterPad[]) {{ .name = "default",
00107 .type = AVMEDIA_TYPE_VIDEO,
00108 .get_video_buffer = avfilter_null_get_video_buffer,
00109 .start_frame = start_frame,
00110 .draw_slice = draw_slice,
00111 .config_props = config_props,
00112 .end_frame = avfilter_null_end_frame, },
00113 { .name = NULL}},
00114 .outputs = (AVFilterPad[]) {{ .name = "default",
00115 .type = AVMEDIA_TYPE_VIDEO, },
00116 { .name = NULL}},
00117 };