Libav 0.7.1
|
00001 /* 00002 * Copyright (c) 2007 Bobby Bingham 00003 * 00004 * This file is part of Libav. 00005 * 00006 * Libav is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * Libav is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with Libav; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 /* ensure that slices play nice with chroma subsampling, and enforce 00070 * a reasonable minimum size for the slices */ 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 };