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