diff --git a/libswscale/filters.c b/libswscale/filters.c index f9e0f3a1d0..e94b2ea5f6 100644 --- a/libswscale/filters.c +++ b/libswscale/filters.c @@ -192,7 +192,11 @@ int ff_sws_filter_generate(void *log, const SwsFilterParams *params, if (scaler == SWS_SCALE_AUTO) scaler = SWS_SCALE_BICUBIC; - const double ratio = (double) params->dst_size / params->src_size; + double virtual_size = params->virtual_size; + if (!virtual_size) + virtual_size = params->dst_size; + + const double ratio = virtual_size / params->src_size; double stretch = 1.0; if (ratio < 1.0 && scaler != SWS_SCALE_POINT) { /* Widen filter for downscaling (anti-aliasing) */ @@ -241,6 +245,7 @@ int ff_sws_filter_generate(void *log, const SwsFilterParams *params, memcpy(filter->name, fun.name, sizeof(filter->name)); filter->src_size = params->src_size; filter->dst_size = params->dst_size; + filter->virtual_size = virtual_size; filter->offset = params->offset; filter->filter_size = filter_size; if (filter->filter_size == 1) diff --git a/libswscale/filters.h b/libswscale/filters.h index 9cb467db24..830ee00200 100644 --- a/libswscale/filters.h +++ b/libswscale/filters.h @@ -73,6 +73,20 @@ typedef struct SwsFilterParams { int src_size; int dst_size; + /** + * The virtual output size. If zero, this is assumed to be the same as + * `dst_size`. Matters for e.g. chroma subsampling, where the the luma + * plane may be smaller than the dst_size. For example, a 99x99 input + * image has a chroma size of 50x50, which would be 100x100 after + * chroma upscaling; but is sampled only at 99x99 resolution. In this + * instance, dst_size is 99x99 and virtual_size is 100x100. + * + * The upscaling offset from this shift is implicit and does not need + * to be accounted for in `offset`. In other words, `offset` is taken + * relative to the virtual size, not the sampled size. + */ + double virtual_size; + /** * The sample offset, in units of input pixels. This is added onto all * sampled coordinates directly, i.e. a value of offset = 1.0 would shift @@ -111,6 +125,7 @@ typedef struct SwsFilterWeights { */ int src_size; int dst_size; + double virtual_size; double offset; /**