Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
| ... | ... |
@@ -25,10 +25,12 @@ |
| 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,6 +43,7 @@ typedef struct {
|
| 41 | 41 |
int hsub, vsub; ///< chroma subsampling |
| 42 | 42 |
int slice_y; ///< top of current output slice |
| 43 | 43 |
int input_is_pal; ///< set to 1 if the input format is paletted |
| 44 |
+ int interlaced; |
|
| 44 | 45 |
} ScaleContext; |
| 45 | 46 |
|
| 46 | 47 |
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
| ... | ... |
@@ -53,6 +56,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
| 53 | 53 |
sscanf(args, "%d:%d", &scale->w, &scale->h); |
| 54 | 54 |
p = strstr(args,"flags="); |
| 55 | 55 |
if (p) scale->flags = strtoul(p+6, NULL, 0); |
| 56 |
+ if(strstr(args,"interl=1")){
|
|
| 57 |
+ scale->interlaced=1; |
|
| 58 |
+ }else if(strstr(args,"interl=-1")) |
|
| 59 |
+ scale->interlaced=-1; |
|
| 56 | 60 |
} |
| 57 | 61 |
|
| 58 | 62 |
/* sanity check params */ |
| ... | ... |
@@ -70,6 +77,8 @@ static av_cold void uninit(AVFilterContext *ctx) |
| 70 | 70 |
{
|
| 71 | 71 |
ScaleContext *scale = ctx->priv; |
| 72 | 72 |
sws_freeContext(scale->sws); |
| 73 |
+ sws_freeContext(scale->isws[0]); |
|
| 74 |
+ sws_freeContext(scale->isws[1]); |
|
| 73 | 75 |
scale->sws = NULL; |
| 74 | 76 |
} |
| 75 | 77 |
|
| ... | ... |
@@ -138,6 +147,12 @@ static int config_props(AVFilterLink *outlink) |
| 138 | 138 |
scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format, |
| 139 | 139 |
outlink->w, outlink->h, outlink->format, |
| 140 | 140 |
scale->flags, NULL, NULL, NULL); |
| 141 |
+ scale->isws[0] = sws_getContext(inlink ->w, inlink ->h/2, inlink ->format, |
|
| 142 |
+ outlink->w, outlink->h/2, outlink->format, |
|
| 143 |
+ scale->flags, NULL, NULL, NULL); |
|
| 144 |
+ scale->isws[1] = sws_getContext(inlink ->w, inlink ->h/2, inlink ->format, |
|
| 145 |
+ outlink->w, outlink->h/2, outlink->format, |
|
| 146 |
+ scale->flags, NULL, NULL, NULL); |
|
| 141 | 147 |
if (!scale->sws) |
| 142 | 148 |
return AVERROR(EINVAL); |
| 143 | 149 |
|
| ... | ... |
@@ -169,26 +184,46 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) |
| 169 | 169 |
avfilter_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0)); |
| 170 | 170 |
} |
| 171 | 171 |
|
| 172 |
+static int scale_slice(AVFilterLink *link, struct SwsContext *sws, int y, int h, int mul, int field) |
|
| 173 |
+{
|
|
| 174 |
+ ScaleContext *scale = link->dst->priv; |
|
| 175 |
+ AVFilterBufferRef *cur_pic = link->cur_buf; |
|
| 176 |
+ AVFilterBufferRef *out_buf = link->dst->outputs[0]->out_buf; |
|
| 177 |
+ const uint8_t *in[4], *out[4]; |
|
| 178 |
+ int in_stride[4],out_stride[4]; |
|
| 179 |
+ int i; |
|
| 180 |
+ |
|
| 181 |
+ for(i=0; i<4; i++){
|
|
| 182 |
+ int vsub= ((i+1)&2) ? scale->vsub : 0; |
|
| 183 |
+ in_stride[i] = cur_pic->linesize[i] * mul; |
|
| 184 |
+ out_stride[i] = out_buf->linesize[i] * mul; |
|
| 185 |
+ in[i] = cur_pic->data[i] + ((y>>vsub)+field) * cur_pic->linesize[i]; |
|
| 186 |
+ out[i] = out_buf->data[i] + field * out_buf->linesize[i]; |
|
| 187 |
+ } |
|
| 188 |
+ if(scale->input_is_pal){
|
|
| 189 |
+ in[1] = cur_pic->data[1]; |
|
| 190 |
+ out[1] = out_buf->data[1]; |
|
| 191 |
+ } |
|
| 192 |
+ |
|
| 193 |
+ return sws_scale(sws, in, in_stride, y/mul, h, |
|
| 194 |
+ out,out_stride); |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 172 | 197 |
static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir) |
| 173 | 198 |
{
|
| 174 | 199 |
ScaleContext *scale = link->dst->priv; |
| 175 | 200 |
int out_h; |
| 176 |
- AVFilterBufferRef *cur_pic = link->cur_buf; |
|
| 177 |
- const uint8_t *data[4]; |
|
| 178 | 201 |
|
| 179 | 202 |
if (scale->slice_y == 0 && slice_dir == -1) |
| 180 | 203 |
scale->slice_y = link->dst->outputs[0]->h; |
| 181 | 204 |
|
| 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); |
|
| 205 |
+ if(scale->interlaced>0 || (scale->interlaced<0 && link->cur_buf->video->interlaced)){
|
|
| 206 |
+ av_assert0(y%4 == 0); |
|
| 207 |
+ out_h = scale_slice(link, scale->isws[0], y, (h+1)/2, 2, 0); |
|
| 208 |
+ out_h+= scale_slice(link, scale->isws[1], y, h /2, 2, 1); |
|
| 209 |
+ }else{
|
|
| 210 |
+ out_h = scale_slice(link, scale->sws, y, h, 1, 0); |
|
| 211 |
+ } |
|
| 192 | 212 |
|
| 193 | 213 |
if (slice_dir == -1) |
| 194 | 214 |
scale->slice_y -= out_h; |