History

Add scale filter.

Originally committed as revision 20519 to svn://svn.ffmpeg.org/ffmpeg/trunk

Stefano Sabatini committed 17 years ago

Commit c3eabb71 parent ba112575 files · +231 −1Browse files

Unified · Split

5 files
  1. doc/libavfilter.texi +25 −0
  2. libavfilter/Makefile +1 −0
  3. libavfilter/allfilters.c +1 −0
  4. libavfilter/avfilter.h +1 −1
  5. libavfilter/vf_scale.c +203 −0
doc/libavfilter.texi+25−0
@@ -164,6 +164,31 @@ not specified it will use the default value of 16. · 163 unmodified lines
164Adding this in the beginning of filter chains should make filtering164Adding this in the beginning of filter chains should make filtering
165faster due to better use of the memory cache.165faster due to better use of the memory cache.
166 166
167@section scale
168
169Scale the input video to width:height and/or convert the image format.
170
171For example the command:
172
173@example
174./ffmpeg -i in.avi -vfilters "scale=200:100" out.avi
175@end example
176
177will scale the input video to a size of 200x100.
178
179If the input image format is different from the format requested by
180the next filter, the scale filter will convert the input to the
181requested format.
182
183If the value for ``width'' or ``height'' is 0, the respective input
184size is used for the output.
185
186If the value for ``width'' or ``height'' is -1, the scale filter will
187use, for the respective output size, a value that maintains the aspect
188ratio of the input image.
189
190The default value of ``width'' and ``height'' is 0.
191
167@section vflip192@section vflip
168 193
169Flip the input video vertically.194Flip the input video vertically.
libavfilter/Makefile+1−0
@@ -16,6 +16,7 @@ OBJS-$(CONFIG_CROP_FILTER) += vf_crop.o · 15 unmodified lines
16OBJS-$(CONFIG_FORMAT_FILTER) += vf_format.o16OBJS-$(CONFIG_FORMAT_FILTER) += vf_format.o
17OBJS-$(CONFIG_NOFORMAT_FILTER) += vf_format.o17OBJS-$(CONFIG_NOFORMAT_FILTER) += vf_format.o
18OBJS-$(CONFIG_NULL_FILTER) += vf_null.o18OBJS-$(CONFIG_NULL_FILTER) += vf_null.o
19OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o
19OBJS-$(CONFIG_SLICIFY_FILTER) += vf_slicify.o20OBJS-$(CONFIG_SLICIFY_FILTER) += vf_slicify.o
20OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o21OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o
21 22
libavfilter/allfilters.c+1−0
@@ -38,6 +38,7 @@ void avfilter_register_all(void) · 37 unmodified lines
38 REGISTER_FILTER (FORMAT, format, vf);38 REGISTER_FILTER (FORMAT, format, vf);
39 REGISTER_FILTER (NOFORMAT, noformat, vf);39 REGISTER_FILTER (NOFORMAT, noformat, vf);
40 REGISTER_FILTER (NULL, null, vf);40 REGISTER_FILTER (NULL, null, vf);
41 REGISTER_FILTER (SCALE, scale, vf);
41 REGISTER_FILTER (SLICIFY, slicify, vf);42 REGISTER_FILTER (SLICIFY, slicify, vf);
42 REGISTER_FILTER (VFLIP, vflip, vf);43 REGISTER_FILTER (VFLIP, vflip, vf);
43}44}
libavfilter/avfilter.h+1−1
@@ -23,7 +23,7 @@ · 22 unmodified lines
23#define AVFILTER_AVFILTER_H23#define AVFILTER_AVFILTER_H
24 24
25#define LIBAVFILTER_VERSION_MAJOR 125#define LIBAVFILTER_VERSION_MAJOR 1
26#define LIBAVFILTER_VERSION_MINOR 726#define LIBAVFILTER_VERSION_MINOR 8
27#define LIBAVFILTER_VERSION_MICRO 027#define LIBAVFILTER_VERSION_MICRO 0
28 28
29#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \29#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
libavfilter/vf_scale.c+203−0
@@ -0,0 +1,203 @@
1/*
2 * copyright (c) 2007 Bobby Bingham
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file libavfilter/vf_scale.c
23 * scale video filter
24 */
25
26#include "avfilter.h"
27#include "libswscale/swscale.h"
28
29typedef struct {
30 struct SwsContext *sws; ///< software scaler context
31
32 /**
33 * New dimensions. Special values are:
34 * 0 = original width/height
35 * -1 = keep original aspect
36 */
37 int w, h;
38
39 int hsub, vsub; ///< chroma subsampling
40 int slice_y; ///< top of current output slice
41 int slice_dir; ///< detected slice direction order for the current frame
42 int input_is_pal; ///< set to 1 if the input format is paletted
43} ScaleContext;
44
45static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
46{
47 ScaleContext *scale = ctx->priv;
48
49 if (args)
50 sscanf(args, "%d:%d", &scale->w, &scale->h);
51
52 /* sanity check params */
53 if (scale->w < -1 || scale->h < -1) {
54 av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n");
55 return -1;
56 }
57 if (scale->w == -1 && scale->h == -1)
58 scale->w = scale->h = 0;
59
60 return 0;
61}
62
63static av_cold void uninit(AVFilterContext *ctx)
64{
65 ScaleContext *scale = ctx->priv;
66 sws_freeContext(scale->sws);
67 scale->sws = NULL;
68}
69
70static int query_formats(AVFilterContext *ctx)
71{
72 AVFilterFormats *formats;
73
74 if (ctx->inputs[0]) {
75 formats = avfilter_all_colorspaces();
76 avfilter_formats_ref(formats, &ctx->inputs[0]->out_formats);
77 }
78 if (ctx->outputs[0]) {
79 formats = avfilter_all_colorspaces();
80 avfilter_formats_ref(formats, &ctx->outputs[0]->in_formats);
81 }
82
83 return 0;
84}
85
86static int config_props(AVFilterLink *outlink)
87{
88 AVFilterContext *ctx = outlink->src;
89 AVFilterLink *inlink = outlink->src->inputs[0];
90 ScaleContext *scale = ctx->priv;
91 int64_t w, h;
92
93 if (!(w = scale->w))
94 w = inlink->w;
95 if (!(h = scale->h))
96 h = inlink->h;
97 if (w == -1)
98 w = av_rescale(h, inlink->w, inlink->h);
99 if (h == -1)
100 h = av_rescale(w, inlink->h, inlink->w);
101
102 if (w > INT_MAX || h > INT_MAX ||
103 (h * inlink->w) > INT_MAX ||
104 (w * inlink->h) > INT_MAX)
105 av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
106
107 outlink->w = w;
108 outlink->h = h;
109
110 /* TODO: make algorithm configurable */
111 scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format,
112 outlink->w, outlink->h, outlink->format,
113 SWS_BILINEAR, NULL, NULL, NULL);
114
115 av_log(ctx, AV_LOG_INFO, "w:%d h:%d fmt:%s\n",
116 outlink->w, outlink->h, avcodec_get_pix_fmt_name(outlink->format));
117
118 avcodec_get_chroma_sub_sample(outlink->format, &scale->hsub, &scale->vsub);
119
120 scale->input_is_pal = inlink->format == PIX_FMT_PAL8 ||
121 inlink->format == PIX_FMT_BGR4_BYTE ||
122 inlink->format == PIX_FMT_RGB4_BYTE ||
123 inlink->format == PIX_FMT_BGR8 ||
124 inlink->format == PIX_FMT_RGB8;
125
126 return !scale->sws;
127}
128
129static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
130{
131 ScaleContext *scale = link->dst->priv;
132 AVFilterLink *outlink = link->dst->outputs[0];
133 AVFilterPicRef *outpicref;
134
135 outpicref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
136 outpicref->pts = picref->pts;
137 outlink->outpic = outpicref;
138
139 av_reduce(&outpicref->pixel_aspect.num, &outpicref->pixel_aspect.den,
140 (int64_t)picref->pixel_aspect.num * outlink->h * link->w,
141 (int64_t)picref->pixel_aspect.den * outlink->w * link->h,
142 INT_MAX);
143
144 scale->slice_dir = 0;
145 avfilter_start_frame(outlink, avfilter_ref_pic(outpicref, ~0));
146}
147
148static void draw_slice(AVFilterLink *link, int y, int h)
149{
150 ScaleContext *scale = link->dst->priv;
151 int out_h;
152 AVFilterPicRef *cur_pic = link->cur_pic;
153 uint8_t *data[4];
154
155 if (!scale->slice_dir) {
156 if (y != 0 && y + h != link->h) {
157 av_log(scale, AV_LOG_ERROR, "Slices start in the middle!\n");
158 return;
159 }
160 scale->slice_dir = y ? -1 : 1;
161 scale->slice_y = y ? link->dst->outputs[0]->h : y;
162 }
163
164 data[0] = cur_pic->data[0] + y * cur_pic->linesize[0];
165 data[1] = scale->input_is_pal ?
166 cur_pic->data[1] :
167 cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1];
168 data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2];
169 data[3] = cur_pic->data[3] + y * cur_pic->linesize[3];
170
171 out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h,
172 link->dst->outputs[0]->outpic->data,
173 link->dst->outputs[0]->outpic->linesize);
174
175 if (scale->slice_dir == -1)
176 scale->slice_y -= out_h;
177 avfilter_draw_slice(link->dst->outputs[0], scale->slice_y, out_h);
178 if (scale->slice_dir == 1)
179 scale->slice_y += out_h;
180}
181
182AVFilter avfilter_vf_scale = {
183 .name = "scale",
184 .description = "Scale the input video to width:height size and/or convert the image format.",
185
186 .init = init,
187 .uninit = uninit,
188
189 .query_formats = query_formats,
190
191 .priv_size = sizeof(ScaleContext),
192
193 .inputs = (AVFilterPad[]) {{ .name = "default",
194 .type = CODEC_TYPE_VIDEO,
195 .start_frame = start_frame,
196 .draw_slice = draw_slice,
197 .min_perms = AV_PERM_READ, },
198 { .name = NULL}},
199 .outputs = (AVFilterPad[]) {{ .name = "default",
200 .type = CODEC_TYPE_VIDEO,
201 .config_props = config_props, },
202 { .name = NULL}},
203};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t