Revision 57e2ded4 libavfilter/vf_scale.c

View differences:

libavfilter/vf_scale.c
25 25

  
26 26
#include "avfilter.h"
27 27
#include "libavutil/pixdesc.h"
28
#include "libavutil/avassert.h"
28 29
#include "libswscale/swscale.h"
29 30

  
30 31
typedef struct {
31 32
    struct SwsContext *sws;     ///< software scaler context
33
    struct SwsContext *isws[2]; ///< software scaler context for interlaced material
32 34

  
33 35
    /**
34 36
     * New dimensions. Special values are:
......
41 43
    int hsub, vsub;             ///< chroma subsampling
42 44
    int slice_y;                ///< top of current output slice
43 45
    int input_is_pal;           ///< set to 1 if the input format is paletted
46
    int interlaced;
44 47
} ScaleContext;
45 48

  
46 49
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
......
53 56
        sscanf(args, "%d:%d", &scale->w, &scale->h);
54 57
        p = strstr(args,"flags=");
55 58
        if (p) scale->flags = strtoul(p+6, NULL, 0);
59
        if(strstr(args,"interl=1")){
60
            scale->interlaced=1;
61
        }else if(strstr(args,"interl=-1"))
62
            scale->interlaced=-1;
56 63
    }
57 64

  
58 65
    /* sanity check params */
......
70 77
{
71 78
    ScaleContext *scale = ctx->priv;
72 79
    sws_freeContext(scale->sws);
80
    sws_freeContext(scale->isws[0]);
81
    sws_freeContext(scale->isws[1]);
73 82
    scale->sws = NULL;
74 83
}
75 84

  
......
138 147
    scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format,
139 148
                                outlink->w, outlink->h, outlink->format,
140 149
                                scale->flags, NULL, NULL, NULL);
150
    scale->isws[0] = sws_getContext(inlink ->w, inlink ->h/2, inlink ->format,
151
                                    outlink->w, outlink->h/2, outlink->format,
152
                                    scale->flags, NULL, NULL, NULL);
153
    scale->isws[1] = sws_getContext(inlink ->w, inlink ->h/2, inlink ->format,
154
                                    outlink->w, outlink->h/2, outlink->format,
155
                                    scale->flags, NULL, NULL, NULL);
141 156
    if (!scale->sws)
142 157
        return AVERROR(EINVAL);
143 158

  
......
169 184
    avfilter_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
170 185
}
171 186

  
187
static int scale_slice(AVFilterLink *link, struct SwsContext *sws, int y, int h, int mul, int field)
188
{
189
    ScaleContext *scale = link->dst->priv;
190
    AVFilterBufferRef *cur_pic = link->cur_buf;
191
    AVFilterBufferRef *out_buf = link->dst->outputs[0]->out_buf;
192
    const uint8_t *in[4], *out[4];
193
    int in_stride[4],out_stride[4];
194
    int i;
195

  
196
    for(i=0; i<4; i++){
197
        int vsub= ((i+1)&2) ? scale->vsub : 0;
198
         in_stride[i] = cur_pic->linesize[i] * mul;
199
        out_stride[i] = out_buf->linesize[i] * mul;
200
         in[i] = cur_pic->data[i] + ((y>>vsub)+field) * cur_pic->linesize[i];
201
        out[i] = out_buf->data[i] +            field  * out_buf->linesize[i];
202
    }
203
    if(scale->input_is_pal){
204
         in[1] = cur_pic->data[1];
205
        out[1] = out_buf->data[1];
206
    }
207

  
208
    return sws_scale(sws, in, in_stride, y/mul, h,
209
                         out,out_stride);
210
}
211

  
172 212
static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
173 213
{
174 214
    ScaleContext *scale = link->dst->priv;
175 215
    int out_h;
176
    AVFilterBufferRef *cur_pic = link->cur_buf;
177
    const uint8_t *data[4];
178 216

  
179 217
    if (scale->slice_y == 0 && slice_dir == -1)
180 218
        scale->slice_y = link->dst->outputs[0]->h;
181 219

  
182
    data[0] = cur_pic->data[0] +  y               * cur_pic->linesize[0];
183
    data[1] = scale->input_is_pal ?
184
              cur_pic->data[1] :
185
              cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1];
186
    data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2];
187
    data[3] = cur_pic->data[3] +  y               * cur_pic->linesize[3];
188

  
189
    out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h,
190
                      link->dst->outputs[0]->out_buf->data,
191
                      link->dst->outputs[0]->out_buf->linesize);
220
    if(scale->interlaced>0 || (scale->interlaced<0 && link->cur_buf->video->interlaced)){
221
        av_assert0(y%4 == 0);
222
        out_h = scale_slice(link, scale->isws[0], y, (h+1)/2, 2, 0);
223
        out_h+= scale_slice(link, scale->isws[1], y,  h   /2, 2, 1);
224
    }else{
225
        out_h = scale_slice(link, scale->sws, y, h, 1, 0);
226
    }
192 227

  
193 228
    if (slice_dir == -1)
194 229
        scale->slice_y -= out_h;

Also available in: Unified diff