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