~ubuntu-branches/ubuntu/raring/libav/raring-security

« back to all changes in this revision

Viewing changes to .pc/post-0.7.1/0039-vf_scale-don-t-leak-SWS-context.patch/libavfilter/vf_scale.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2011-10-01 00:22:07 UTC
  • mfrom: (1.3.8 sid)
  • Revision ID: package-import@ubuntu.com-20111001002207-tnxz39i0rwr5ufy9
Tags: 4:0.7.2-1ubuntu1
* Merge from debian, remaining changes:
  - don't build against libfaad, libdirac, librtmp and libopenjpeg,
    lame, xvid, x264  (all in universe)
  - not installing into multiarch directories
* This new upstream release has basically merged in all 70 patches that
  are present in 4:0.7.1-7ubuntu2, plus some additional, similarily
  focused ones.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2007 Bobby Bingham
3
 
 *
4
 
 * This file is part of Libav.
5
 
 *
6
 
 * Libav 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
 
 * Libav 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 Libav; 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
23
 
 * scale video filter
24
 
 */
25
 
 
26
 
#include "avfilter.h"
27
 
#include "libavutil/avstring.h"
28
 
#include "libavutil/eval.h"
29
 
#include "libavutil/pixdesc.h"
30
 
#include "libswscale/swscale.h"
31
 
 
32
 
static const char *var_names[] = {
33
 
    "PI",
34
 
    "PHI",
35
 
    "E",
36
 
    "in_w",   "iw",
37
 
    "in_h",   "ih",
38
 
    "out_w",  "ow",
39
 
    "out_h",  "oh",
40
 
    "a",
41
 
    "hsub",
42
 
    "vsub",
43
 
    NULL
44
 
};
45
 
 
46
 
enum var_name {
47
 
    VAR_PI,
48
 
    VAR_PHI,
49
 
    VAR_E,
50
 
    VAR_IN_W,   VAR_IW,
51
 
    VAR_IN_H,   VAR_IH,
52
 
    VAR_OUT_W,  VAR_OW,
53
 
    VAR_OUT_H,  VAR_OH,
54
 
    VAR_A,
55
 
    VAR_HSUB,
56
 
    VAR_VSUB,
57
 
    VARS_NB
58
 
};
59
 
 
60
 
typedef struct {
61
 
    struct SwsContext *sws;     ///< software scaler context
62
 
 
63
 
    /**
64
 
     * New dimensions. Special values are:
65
 
     *   0 = original width/height
66
 
     *  -1 = keep original aspect
67
 
     */
68
 
    int w, h;
69
 
    unsigned int flags;         ///sws flags
70
 
 
71
 
    int hsub, vsub;             ///< chroma subsampling
72
 
    int slice_y;                ///< top of current output slice
73
 
    int input_is_pal;           ///< set to 1 if the input format is paletted
74
 
 
75
 
    char w_expr[256];           ///< width  expression string
76
 
    char h_expr[256];           ///< height expression string
77
 
} ScaleContext;
78
 
 
79
 
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
80
 
{
81
 
    ScaleContext *scale = ctx->priv;
82
 
    const char *p;
83
 
 
84
 
    av_strlcpy(scale->w_expr, "iw", sizeof(scale->w_expr));
85
 
    av_strlcpy(scale->h_expr, "ih", sizeof(scale->h_expr));
86
 
 
87
 
    scale->flags = SWS_BILINEAR;
88
 
    if (args) {
89
 
        sscanf(args, "%255[^:]:%255[^:]", scale->w_expr, scale->h_expr);
90
 
        p = strstr(args,"flags=");
91
 
        if (p) scale->flags = strtoul(p+6, NULL, 0);
92
 
    }
93
 
 
94
 
    return 0;
95
 
}
96
 
 
97
 
static av_cold void uninit(AVFilterContext *ctx)
98
 
{
99
 
    ScaleContext *scale = ctx->priv;
100
 
    sws_freeContext(scale->sws);
101
 
    scale->sws = NULL;
102
 
}
103
 
 
104
 
static int query_formats(AVFilterContext *ctx)
105
 
{
106
 
    AVFilterFormats *formats;
107
 
    enum PixelFormat pix_fmt;
108
 
    int ret;
109
 
 
110
 
    if (ctx->inputs[0]) {
111
 
        formats = NULL;
112
 
        for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++)
113
 
            if (   sws_isSupportedInput(pix_fmt)
114
 
                && (ret = avfilter_add_format(&formats, pix_fmt)) < 0) {
115
 
                avfilter_formats_unref(&formats);
116
 
                return ret;
117
 
            }
118
 
        avfilter_formats_ref(formats, &ctx->inputs[0]->out_formats);
119
 
    }
120
 
    if (ctx->outputs[0]) {
121
 
        formats = NULL;
122
 
        for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++)
123
 
            if (    sws_isSupportedOutput(pix_fmt)
124
 
                && (ret = avfilter_add_format(&formats, pix_fmt)) < 0) {
125
 
                avfilter_formats_unref(&formats);
126
 
                return ret;
127
 
            }
128
 
        avfilter_formats_ref(formats, &ctx->outputs[0]->in_formats);
129
 
    }
130
 
 
131
 
    return 0;
132
 
}
133
 
 
134
 
static int config_props(AVFilterLink *outlink)
135
 
{
136
 
    AVFilterContext *ctx = outlink->src;
137
 
    AVFilterLink *inlink = outlink->src->inputs[0];
138
 
    ScaleContext *scale = ctx->priv;
139
 
    int64_t w, h;
140
 
    double var_values[VARS_NB], res;
141
 
    char *expr;
142
 
    int ret;
143
 
 
144
 
    var_values[VAR_PI]    = M_PI;
145
 
    var_values[VAR_PHI]   = M_PHI;
146
 
    var_values[VAR_E]     = M_E;
147
 
    var_values[VAR_IN_W]  = var_values[VAR_IW] = inlink->w;
148
 
    var_values[VAR_IN_H]  = var_values[VAR_IH] = inlink->h;
149
 
    var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
150
 
    var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
151
 
    var_values[VAR_A]     = (float) inlink->w / inlink->h;
152
 
    var_values[VAR_HSUB]  = 1<<av_pix_fmt_descriptors[inlink->format].log2_chroma_w;
153
 
    var_values[VAR_VSUB]  = 1<<av_pix_fmt_descriptors[inlink->format].log2_chroma_h;
154
 
 
155
 
    /* evaluate width and height */
156
 
    av_expr_parse_and_eval(&res, (expr = scale->w_expr),
157
 
                           var_names, var_values,
158
 
                           NULL, NULL, NULL, NULL, NULL, 0, ctx);
159
 
    scale->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
160
 
    if ((ret = av_expr_parse_and_eval(&res, (expr = scale->h_expr),
161
 
                                      var_names, var_values,
162
 
                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
163
 
        goto fail;
164
 
    scale->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res;
165
 
    /* evaluate again the width, as it may depend on the output height */
166
 
    if ((ret = av_expr_parse_and_eval(&res, (expr = scale->w_expr),
167
 
                                      var_names, var_values,
168
 
                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
169
 
        goto fail;
170
 
    scale->w = res;
171
 
 
172
 
    w = scale->w;
173
 
    h = scale->h;
174
 
 
175
 
    /* sanity check params */
176
 
    if (w <  -1 || h <  -1) {
177
 
        av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n");
178
 
        return AVERROR(EINVAL);
179
 
    }
180
 
    if (w == -1 && h == -1)
181
 
        scale->w = scale->h = 0;
182
 
 
183
 
    if (!(w = scale->w))
184
 
        w = inlink->w;
185
 
    if (!(h = scale->h))
186
 
        h = inlink->h;
187
 
    if (w == -1)
188
 
        w = av_rescale(h, inlink->w, inlink->h);
189
 
    if (h == -1)
190
 
        h = av_rescale(w, inlink->h, inlink->w);
191
 
 
192
 
    if (w > INT_MAX || h > INT_MAX ||
193
 
        (h * inlink->w) > INT_MAX  ||
194
 
        (w * inlink->h) > INT_MAX)
195
 
        av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
196
 
 
197
 
    outlink->w = w;
198
 
    outlink->h = h;
199
 
 
200
 
    /* TODO: make algorithm configurable */
201
 
    av_log(ctx, AV_LOG_INFO, "w:%d h:%d fmt:%s -> w:%d h:%d fmt:%s flags:0x%0x\n",
202
 
           inlink ->w, inlink ->h, av_pix_fmt_descriptors[ inlink->format].name,
203
 
           outlink->w, outlink->h, av_pix_fmt_descriptors[outlink->format].name,
204
 
           scale->flags);
205
 
 
206
 
    scale->input_is_pal = av_pix_fmt_descriptors[inlink->format].flags & PIX_FMT_PAL;
207
 
 
208
 
    scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format,
209
 
                                outlink->w, outlink->h, outlink->format,
210
 
                                scale->flags, NULL, NULL, NULL);
211
 
    if (!scale->sws)
212
 
        return AVERROR(EINVAL);
213
 
 
214
 
    return 0;
215
 
 
216
 
fail:
217
 
    av_log(NULL, AV_LOG_ERROR,
218
 
           "Error when evaluating the expression '%s'\n", expr);
219
 
    return ret;
220
 
}
221
 
 
222
 
static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
223
 
{
224
 
    ScaleContext *scale = link->dst->priv;
225
 
    AVFilterLink *outlink = link->dst->outputs[0];
226
 
    AVFilterBufferRef *outpicref;
227
 
 
228
 
    scale->hsub = av_pix_fmt_descriptors[link->format].log2_chroma_w;
229
 
    scale->vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
230
 
 
231
 
    outpicref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
232
 
    avfilter_copy_buffer_ref_props(outpicref, picref);
233
 
    outpicref->video->w = outlink->w;
234
 
    outpicref->video->h = outlink->h;
235
 
 
236
 
    outlink->out_buf = outpicref;
237
 
 
238
 
    av_reduce(&outpicref->video->pixel_aspect.num, &outpicref->video->pixel_aspect.den,
239
 
              (int64_t)picref->video->pixel_aspect.num * outlink->h * link->w,
240
 
              (int64_t)picref->video->pixel_aspect.den * outlink->w * link->h,
241
 
              INT_MAX);
242
 
 
243
 
    scale->slice_y = 0;
244
 
    avfilter_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
245
 
}
246
 
 
247
 
static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
248
 
{
249
 
    ScaleContext *scale = link->dst->priv;
250
 
    int out_h;
251
 
    AVFilterBufferRef *cur_pic = link->cur_buf;
252
 
    const uint8_t *data[4];
253
 
 
254
 
    if (scale->slice_y == 0 && slice_dir == -1)
255
 
        scale->slice_y = link->dst->outputs[0]->h;
256
 
 
257
 
    data[0] = cur_pic->data[0] +  y               * cur_pic->linesize[0];
258
 
    data[1] = scale->input_is_pal ?
259
 
              cur_pic->data[1] :
260
 
              cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1];
261
 
    data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2];
262
 
    data[3] = cur_pic->data[3] +  y               * cur_pic->linesize[3];
263
 
 
264
 
    out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h,
265
 
                      link->dst->outputs[0]->out_buf->data,
266
 
                      link->dst->outputs[0]->out_buf->linesize);
267
 
 
268
 
    if (slice_dir == -1)
269
 
        scale->slice_y -= out_h;
270
 
    avfilter_draw_slice(link->dst->outputs[0], scale->slice_y, out_h, slice_dir);
271
 
    if (slice_dir == 1)
272
 
        scale->slice_y += out_h;
273
 
}
274
 
 
275
 
AVFilter avfilter_vf_scale = {
276
 
    .name      = "scale",
277
 
    .description = NULL_IF_CONFIG_SMALL("Scale the input video to width:height size and/or convert the image format."),
278
 
 
279
 
    .init      = init,
280
 
    .uninit    = uninit,
281
 
 
282
 
    .query_formats = query_formats,
283
 
 
284
 
    .priv_size = sizeof(ScaleContext),
285
 
 
286
 
    .inputs    = (AVFilterPad[]) {{ .name             = "default",
287
 
                                    .type             = AVMEDIA_TYPE_VIDEO,
288
 
                                    .start_frame      = start_frame,
289
 
                                    .draw_slice       = draw_slice,
290
 
                                    .min_perms        = AV_PERM_READ, },
291
 
                                  { .name = NULL}},
292
 
    .outputs   = (AVFilterPad[]) {{ .name             = "default",
293
 
                                    .type             = AVMEDIA_TYPE_VIDEO,
294
 
                                    .config_props     = config_props, },
295
 
                                  { .name = NULL}},
296
 
};