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 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
00058
00059 slice->vshift = desc->log2_chroma_h;
00060
00061 return 0;
00062 }
00063
00064 static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
00065 {
00066 SliceContext *slice = link->dst->priv;
00067
00068 if (slice->use_random_h) {
00069 slice->lcg_state = slice->lcg_state * 1664525 + 1013904223;
00070 slice->h = 8 + (uint64_t)slice->lcg_state * 25 / UINT32_MAX;
00071 }
00072
00073
00074
00075 slice->h = FFMAX(8, slice->h & (-1 << slice->vshift));
00076
00077 av_log(link->dst, AV_LOG_DEBUG, "h:%d\n", slice->h);
00078 link->cur_buf = NULL;
00079
00080 return ff_start_frame(link->dst->outputs[0], picref);
00081 }
00082
00083 static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00084 {
00085 SliceContext *slice = link->dst->priv;
00086 int y2, ret = 0;
00087
00088 if (slice_dir == 1) {
00089 for (y2 = y; y2 + slice->h <= y + h; y2 += slice->h) {
00090 ret = ff_draw_slice(link->dst->outputs[0], y2, slice->h, slice_dir);
00091 if (ret < 0)
00092 return ret;
00093 }
00094
00095 if (y2 < y + h)
00096 return ff_draw_slice(link->dst->outputs[0], y2, y + h - y2, slice_dir);
00097 } else if (slice_dir == -1) {
00098 for (y2 = y + h; y2 - slice->h >= y; y2 -= slice->h) {
00099 ret = ff_draw_slice(link->dst->outputs[0], y2 - slice->h, slice->h, slice_dir);
00100 if (ret < 0)
00101 return ret;
00102 }
00103
00104 if (y2 > y)
00105 return ff_draw_slice(link->dst->outputs[0], y, y2 - y, slice_dir);
00106 }
00107 return 0;
00108 }
00109
00110 static const AVFilterPad avfilter_vf_slicify_inputs[] = {
00111 {
00112 .name = "default",
00113 .type = AVMEDIA_TYPE_VIDEO,
00114 .get_video_buffer = ff_null_get_video_buffer,
00115 .start_frame = start_frame,
00116 .draw_slice = draw_slice,
00117 .config_props = config_props,
00118 .end_frame = ff_null_end_frame,
00119 },
00120 { NULL }
00121 };
00122
00123 static const AVFilterPad avfilter_vf_slicify_outputs[] = {
00124 {
00125 .name = "default",
00126 .type = AVMEDIA_TYPE_VIDEO,
00127 },
00128 { NULL }
00129 };
00130
00131 AVFilter avfilter_vf_slicify = {
00132 .name = "slicify",
00133 .description = NULL_IF_CONFIG_SMALL("Pass the images of input video on to next video filter as multiple slices."),
00134
00135 .init = init,
00136
00137 .priv_size = sizeof(SliceContext),
00138
00139 .inputs = avfilter_vf_slicify_inputs,
00140 .outputs = avfilter_vf_slicify_outputs,
00141 };