| @@ -59,6 +59,17 @@ static const char *const var_names[] = { · 58 unmodified lines |
| 59 | #if FF_API_FRAME_PKT | 59 | #if FF_API_FRAME_PKT |
| 60 | "pos", | 60 | "pos", |
| 61 | #endif | 61 | #endif |
| | 62 | "ref_w", "rw", |
| | 63 | "ref_h", "rh", |
| | 64 | "ref_a", |
| | 65 | "ref_sar", |
| | 66 | "ref_dar", "rdar", |
| | 67 | "ref_hsub", |
| | 68 | "ref_vsub", |
| | 69 | "ref_n", |
| | 70 | "ref_t", |
| | 71 | "ref_pos", |
| | 72 | /* Legacy variables for scale2ref */ |
| 62 | "main_w", | 73 | "main_w", |
| 63 | "main_h", | 74 | "main_h", |
| 64 | "main_a", | 75 | "main_a", |
| @@ -89,6 +100,16 @@ enum var_name { · 24 unmodified lines |
| 89 | #if FF_API_FRAME_PKT | 100 | #if FF_API_FRAME_PKT |
| 90 | VAR_POS, | 101 | VAR_POS, |
| 91 | #endif | 102 | #endif |
| | 103 | VAR_REF_W, VAR_RW, |
| | 104 | VAR_REF_H, VAR_RH, |
| | 105 | VAR_REF_A, |
| | 106 | VAR_REF_SAR, |
| | 107 | VAR_REF_DAR, VAR_RDAR, |
| | 108 | VAR_REF_HSUB, |
| | 109 | VAR_REF_VSUB, |
| | 110 | VAR_REF_N, |
| | 111 | VAR_REF_T, |
| | 112 | VAR_REF_POS, |
| 92 | VAR_S2R_MAIN_W, | 113 | VAR_S2R_MAIN_W, |
| 93 | VAR_S2R_MAIN_H, | 114 | VAR_S2R_MAIN_H, |
| 94 | VAR_S2R_MAIN_A, | 115 | VAR_S2R_MAIN_A, |
| @@ -131,6 +152,7 @@ typedef struct ScaleContext { · 36 unmodified lines |
| 131 | int input_is_pal; ///< set to 1 if the input format is paletted | 152 | int input_is_pal; ///< set to 1 if the input format is paletted |
| 132 | int output_is_pal; ///< set to 1 if the output format is paletted | 153 | int output_is_pal; ///< set to 1 if the output format is paletted |
| 133 | int interlaced; | 154 | int interlaced; |
| | 155 | int uses_ref; |
| 134 | | 156 | |
| 135 | char *w_expr; ///< width expression string | 157 | char *w_expr; ///< width expression string |
| 136 | char *h_expr; ///< height expression string | 158 | char *h_expr; ///< height expression string |
| @@ -190,6 +212,38 @@ static int check_exprs(AVFilterContext *ctx) · 53 unmodified lines |
| 190 | av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr); | 212 | av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr); |
| 191 | } | 213 | } |
| 192 | | 214 | |
| | 215 | if (vars_w[VAR_REF_W] || vars_h[VAR_REF_W] || |
| | 216 | vars_w[VAR_RW] || vars_h[VAR_RW] || |
| | 217 | vars_w[VAR_REF_H] || vars_h[VAR_REF_H] || |
| | 218 | vars_w[VAR_RH] || vars_h[VAR_RH] || |
| | 219 | vars_w[VAR_REF_A] || vars_h[VAR_REF_A] || |
| | 220 | vars_w[VAR_REF_SAR] || vars_h[VAR_REF_SAR] || |
| | 221 | vars_w[VAR_REF_DAR] || vars_h[VAR_REF_DAR] || |
| | 222 | vars_w[VAR_RDAR] || vars_h[VAR_RDAR] || |
| | 223 | vars_w[VAR_REF_HSUB] || vars_h[VAR_REF_HSUB] || |
| | 224 | vars_w[VAR_REF_VSUB] || vars_h[VAR_REF_VSUB] || |
| | 225 | vars_w[VAR_REF_N] || vars_h[VAR_REF_N] || |
| | 226 | vars_w[VAR_REF_T] || vars_h[VAR_REF_T] || |
| | 227 | vars_w[VAR_REF_POS] || vars_h[VAR_REF_POS]) { |
| | 228 | scale->uses_ref = 1; |
| | 229 | } |
| | 230 | |
| | 231 | if (ctx->filter != &ff_vf_scale2ref && |
| | 232 | (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || |
| | 233 | vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || |
| | 234 | vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] || |
| | 235 | vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] || |
| | 236 | vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] || |
| | 237 | vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] || |
| | 238 | vars_w[VAR_S2R_MAIN_HSUB] || vars_h[VAR_S2R_MAIN_HSUB] || |
| | 239 | vars_w[VAR_S2R_MAIN_VSUB] || vars_h[VAR_S2R_MAIN_VSUB] || |
| | 240 | vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || |
| | 241 | vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || |
| | 242 | vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { |
| | 243 | av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref variables are not valid in scale filter.\n"); |
| | 244 | return AVERROR(EINVAL); |
| | 245 | } |
| | 246 | |
| 193 | if (ctx->filter != &ff_vf_scale2ref && | 247 | if (ctx->filter != &ff_vf_scale2ref && |
| 194 | (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || | 248 | (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || |
| 195 | vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || | 249 | vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || |
| @@ -385,6 +439,9 @@ static av_cold int init(AVFilterContext *ctx) · 189 unmodified lines |
| 385 | if (!threads) | 439 | if (!threads) |
| 386 | av_opt_set_int(scale->sws_opts, "threads", ff_filter_get_nb_threads(ctx), 0); | 440 | av_opt_set_int(scale->sws_opts, "threads", ff_filter_get_nb_threads(ctx), 0); |
| 387 | | 441 | |
| | 442 | if (ctx->filter != &ff_vf_scale2ref) |
| | 443 | ctx->nb_inputs = scale->uses_ref ? 2 : 1; |
| | 444 | |
| 388 | return 0; | 445 | return 0; |
| 389 | } | 446 | } |
| 390 | | 447 | |
| @@ -506,6 +563,20 @@ static int scale_eval_dimensions(AVFilterContext *ctx) · 115 unmodified lines |
| 506 | scale->var_values[VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; | 563 | scale->var_values[VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; |
| 507 | } | 564 | } |
| 508 | | 565 | |
| | 566 | if (scale->uses_ref) { |
| | 567 | const AVFilterLink *reflink = ctx->inputs[1]; |
| | 568 | const AVPixFmtDescriptor *ref_desc = av_pix_fmt_desc_get(reflink->format); |
| | 569 | scale->var_values[VAR_REF_W] = scale->var_values[VAR_RW] = reflink->w; |
| | 570 | scale->var_values[VAR_REF_H] = scale->var_values[VAR_RH] = reflink->h; |
| | 571 | scale->var_values[VAR_REF_A] = (double) reflink->w / reflink->h; |
| | 572 | scale->var_values[VAR_REF_SAR] = reflink->sample_aspect_ratio.num ? |
| | 573 | (double) reflink->sample_aspect_ratio.num / reflink->sample_aspect_ratio.den : 1; |
| | 574 | scale->var_values[VAR_REF_DAR] = scale->var_values[VAR_RDAR] = |
| | 575 | scale->var_values[VAR_REF_A] * scale->var_values[VAR_REF_SAR]; |
| | 576 | scale->var_values[VAR_REF_HSUB] = 1 << ref_desc->log2_chroma_w; |
| | 577 | scale->var_values[VAR_REF_VSUB] = 1 << ref_desc->log2_chroma_h; |
| | 578 | } |
| | 579 | |
| 509 | res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); | 580 | res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); |
| 510 | eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; | 581 | eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; |
| 511 | | 582 | |
| @@ -693,6 +764,13 @@ static int config_props(AVFilterLink *outlink) · 181 unmodified lines |
| 693 | scale->fs.in[0].sync = 1; | 764 | scale->fs.in[0].sync = 1; |
| 694 | scale->fs.in[0].before = EXT_STOP; | 765 | scale->fs.in[0].before = EXT_STOP; |
| 695 | scale->fs.in[0].after = EXT_STOP; | 766 | scale->fs.in[0].after = EXT_STOP; |
| | 767 | if (scale->uses_ref) { |
| | 768 | av_assert0(ctx->nb_inputs == 2); |
| | 769 | scale->fs.in[1].time_base = ctx->inputs[1]->time_base; |
| | 770 | scale->fs.in[1].sync = 0; |
| | 771 | scale->fs.in[1].before = EXT_NULL; |
| | 772 | scale->fs.in[1].after = EXT_INFINITY; |
| | 773 | } |
| 696 | | 774 | |
| 697 | ret = ff_framesync_configure(&scale->fs); | 775 | ret = ff_framesync_configure(&scale->fs); |
| 698 | if (ret < 0) | 776 | if (ret < 0) |
| @@ -919,13 +997,55 @@ scale: · 220 unmodified lines |
| 919 | static int do_scale(FFFrameSync *fs) | 997 | static int do_scale(FFFrameSync *fs) |
| 920 | { | 998 | { |
| 921 | AVFilterContext *ctx = fs->parent; | 999 | AVFilterContext *ctx = fs->parent; |
| | 1000 | ScaleContext *scale = ctx->priv; |
| 922 | AVFilterLink *outlink = ctx->outputs[0]; | 1001 | AVFilterLink *outlink = ctx->outputs[0]; |
| 923 | AVFrame *in, *out; | 1002 | AVFrame *out, *in = NULL, *ref = NULL; |
| 924 | int ret; | 1003 | int ret = 0, frame_changed; |
| 925 | | 1004 | |
| 926 | ret = ff_framesync_get_frame(fs, 0, &in, 1); | 1005 | ret = ff_framesync_get_frame(fs, 0, &in, 1); |
| 927 | if (ret < 0) | 1006 | if (ret < 0) |
| 928 | return ret; | 1007 | goto err; |
| | 1008 | |
| | 1009 | if (scale->uses_ref) { |
| | 1010 | ret = ff_framesync_get_frame(fs, 1, &ref, 0); |
| | 1011 | if (ret < 0) |
| | 1012 | goto err; |
| | 1013 | } |
| | 1014 | |
| | 1015 | if (ref) { |
| | 1016 | AVFilterLink *reflink = ctx->inputs[1]; |
| | 1017 | frame_changed = ref->width != reflink->w || |
| | 1018 | ref->height != reflink->h || |
| | 1019 | ref->format != reflink->format || |
| | 1020 | ref->sample_aspect_ratio.den != reflink->sample_aspect_ratio.den || |
| | 1021 | ref->sample_aspect_ratio.num != reflink->sample_aspect_ratio.num || |
| | 1022 | ref->colorspace != reflink->colorspace || |
| | 1023 | ref->color_range != reflink->color_range; |
| | 1024 | |
| | 1025 | if (frame_changed) { |
| | 1026 | reflink->format = ref->format; |
| | 1027 | reflink->w = ref->width; |
| | 1028 | reflink->h = ref->height; |
| | 1029 | reflink->sample_aspect_ratio.num = ref->sample_aspect_ratio.num; |
| | 1030 | reflink->sample_aspect_ratio.den = ref->sample_aspect_ratio.den; |
| | 1031 | reflink->colorspace = ref->colorspace; |
| | 1032 | reflink->color_range = ref->color_range; |
| | 1033 | |
| | 1034 | ret = config_props(outlink); |
| | 1035 | if (ret < 0) |
| | 1036 | goto err; |
| | 1037 | } |
| | 1038 | |
| | 1039 | if (scale->eval_mode == EVAL_MODE_FRAME) { |
| | 1040 | scale->var_values[VAR_REF_N] = reflink->frame_count_out; |
| | 1041 | scale->var_values[VAR_REF_T] = TS2T(ref->pts, reflink->time_base); |
| | 1042 | #if FF_API_FRAME_PKT |
| | 1043 | FF_DISABLE_DEPRECATION_WARNINGS |
| | 1044 | scale->var_values[VAR_REF_POS] = ref->pkt_pos == -1 ? NAN : ref->pkt_pos; |
| | 1045 | FF_ENABLE_DEPRECATION_WARNINGS |
| | 1046 | #endif |
| | 1047 | } |
| | 1048 | } |
| 929 | | 1049 | |
| 930 | ret = scale_frame(ctx->inputs[0], in, &out); | 1050 | ret = scale_frame(ctx->inputs[0], in, &out); |
| 931 | if (out) { | 1051 | if (out) { |
| @@ -933,6 +1053,9 @@ static int do_scale(FFFrameSync *fs) · 1 unmodified line |
| 933 | return ff_filter_frame(outlink, out); | 1053 | return ff_filter_frame(outlink, out); |
| 934 | } | 1054 | } |
| 935 | | 1055 | |
| | 1056 | err: |
| | 1057 | if (ret < 0) |
| | 1058 | av_frame_free(&in); |
| 936 | return ret; | 1059 | return ret; |
| 937 | } | 1060 | } |
| 938 | | 1061 | |
| @@ -1108,6 +1231,9 @@ static const AVFilterPad avfilter_vf_scale_inputs[] = { · 169 unmodified lines |
| 1108 | { | 1231 | { |
| 1109 | .name = "default", | 1232 | .name = "default", |
| 1110 | .type = AVMEDIA_TYPE_VIDEO, | 1233 | .type = AVMEDIA_TYPE_VIDEO, |
| | 1234 | }, { |
| | 1235 | .name = "ref", |
| | 1236 | .type = AVMEDIA_TYPE_VIDEO, |
| 1111 | }, | 1237 | }, |
| 1112 | }; | 1238 | }; |
| 1113 | | 1239 | |