This aligns the behavior of vf_libplacebo with other filters in the vf_scale family, that forward any change in the SAR as a result of changing the output resolution to the output frame / link, and updates the ff_scale_adjust_dimensions() call to continue working as intended. The new behavior reflects the documentation of vf_libplacebo, which described this behavior despite that not being the way the filter worked up to this point. As an aside, also fixes a bug where the AVFrame SAR was inconsistent with the AVFilterLink SAR when the s->nb_inputs > 1 condition was met.
Unified · Split
| @@ -186,6 +186,7 @@ typedef struct LibplaceboContext { · 185 unmodified lines | ||
| 186 | 186 | float corner_rounding; |
| 187 | 187 | int force_original_aspect_ratio; |
| 188 | 188 | int force_divisible_by; |
| 189 | + int reset_sar; | |
| 189 | 190 | int normalize_sar; |
| 190 | 191 | int apply_filmgrain; |
| 191 | 192 | int apply_dovi; |
| @@ -929,6 +930,15 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 737 unmodified lines | ||
| 929 | 930 | if (s->apply_filmgrain) |
| 930 | 931 | av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); |
| 931 | 932 | |
| 933 | + if (s->reset_sar) { | |
| 934 | + out->sample_aspect_ratio = ref->sample_aspect_ratio; | |
| 935 | + } else { | |
| 936 | + const AVRational ar_ref = { ref->width, ref->height }; | |
| 937 | + const AVRational ar_out = { out->width, out->height }; | |
| 938 | + const AVRational stretch = av_div_q(ar_ref, ar_out); | |
| 939 | + out->sample_aspect_ratio = av_mul_q(ref->sample_aspect_ratio, stretch); | |
| 940 | + } | |
| 941 | + | |
| 932 | 942 | /* Map, render and unmap output frame */ |
| 933 | 943 | if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { |
| 934 | 944 | ok = pl_map_avframe_ex(s->gpu, &target, pl_avframe_params( |
| @@ -1288,19 +1298,28 @@ static int libplacebo_config_output(AVFilterLink *outlink) · 353 unmodified lines | ||
| 1288 | 1298 | RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, |
| 1289 | 1299 | &outlink->w, &outlink->h)); |
| 1290 | 1300 | |
| 1301 | + s->reset_sar = s->normalize_sar || s->nb_inputs > 1; | |
| 1302 | + double sar_in = inlink->sample_aspect_ratio.num ? | |
| 1303 | + av_q2d(inlink->sample_aspect_ratio) : 1.0; | |
| 1304 | + | |
| 1291 | 1305 | ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h, |
| 1292 | 1306 | s->force_original_aspect_ratio, |
| 1293 | − s->force_divisible_by, 1.f); | |
| 1307 | + s->force_divisible_by, | |
| 1308 | + s->reset_sar ? sar_in : 1.0); | |
| 1294 | 1309 | |
| 1295 | − if (s->normalize_sar || s->nb_inputs > 1) { | |
| 1310 | + if (s->reset_sar) { | |
| 1296 | 1311 | /* SAR is normalized, or we have multiple inputs, set out to 1:1 */ |
| 1297 | 1312 | outlink->sample_aspect_ratio = (AVRational){ 1, 1 }; |
| 1298 | − } else { | |
| 1313 | + } else if (inlink->sample_aspect_ratio.num) { | |
| 1299 | 1314 | /* This is consistent with other scale_* filters, which only |
| 1300 | 1315 | * set the outlink SAR to be equal to the scale SAR iff the input SAR |
| 1301 | 1316 | * was set to something nonzero */ |
| 1302 | − if (inlink->sample_aspect_ratio.num) | |
| 1303 | − outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | |
| 1317 | + const AVRational ar_in = { inlink->w, inlink->h }; | |
| 1318 | + const AVRational ar_out = { outlink->w, outlink->h }; | |
| 1319 | + const AVRational stretch = av_div_q(ar_in, ar_out); | |
| 1320 | + outlink->sample_aspect_ratio = av_mul_q(inlink->sample_aspect_ratio, stretch); | |
| 1321 | + } else { | |
| 1322 | + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | |
| 1304 | 1323 | } |
| 1305 | 1324 | |
| 1306 | 1325 | /* Frame rate */ |