Most logic from this filter has been co-opted into swscale itself, allowing the resulting filter to be substantially simpler as it no longer has to worry about context initialization, interlacing, etc.
Unified · Split
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #include "filters.h" | 31 | #include "filters.h" |
| 32 | #include "formats.h" | 32 | #include "formats.h" |
| 33 | #include "framesync.h" | 33 | #include "framesync.h" |
| 34 | #include "libavutil/pixfmt.h" | ||
| 34 | #include "scale_eval.h" | 35 | #include "scale_eval.h" |
| 35 | #include "video.h" | 36 | #include "video.h" |
| 36 | #include "libavutil/eval.h" | 37 | #include "libavutil/eval.h" |
| @@ -131,10 +132,7 @@ enum EvalMode { · 94 unmodified lines | |||
| 131 | 132 | ||
| 132 | typedef struct ScaleContext { | 133 | typedef struct ScaleContext { |
| 133 | const AVClass *class; | 134 | const AVClass *class; |
| 134 | struct SwsContext *sws; ///< software scaler context | 135 | SwsContext *sws; |
| 135 | struct SwsContext *isws[2]; ///< software scaler context for interlaced material | ||
| 136 | // context used for forwarding options to sws | ||
| 137 | struct SwsContext *sws_opts; | ||
| 138 | FFFrameSync fs; | 136 | FFFrameSync fs; |
| 139 | 137 | ||
| 140 | /** | 138 | /** |
| @@ -149,8 +147,6 @@ typedef struct ScaleContext { · 8 unmodified lines | |||
| 149 | 147 | ||
| 150 | int hsub, vsub; ///< chroma subsampling | 148 | int hsub, vsub; ///< chroma subsampling |
| 151 | int slice_y; ///< top of current output slice | 149 | int slice_y; ///< top of current output slice |
| 152 | int input_is_pal; ///< set to 1 if the input format is paletted | ||
| 153 | int output_is_pal; ///< set to 1 if the output format is paletted | ||
| 154 | int interlaced; | 150 | int interlaced; |
| 155 | int uses_ref; | 151 | int uses_ref; |
| 156 | 152 | ||
| @@ -334,40 +330,24 @@ revert: · 177 unmodified lines | |||
| 334 | static av_cold int preinit(AVFilterContext *ctx) | 330 | static av_cold int preinit(AVFilterContext *ctx) |
| 335 | { | 331 | { |
| 336 | ScaleContext *scale = ctx->priv; | 332 | ScaleContext *scale = ctx->priv; |
| 337 | int ret; | ||
| 338 | 333 | ||
| 339 | scale->sws_opts = sws_alloc_context(); | 334 | scale->sws = sws_alloc_context(); |
| 340 | if (!scale->sws_opts) | 335 | if (!scale->sws) |
| 341 | return AVERROR(ENOMEM); | 336 | return AVERROR(ENOMEM); |
| 342 | 337 | ||
| 343 | // set threads=0, so we can later check whether the user modified it | 338 | // set threads=0, so we can later check whether the user modified it |
| 344 | ret = av_opt_set_int(scale->sws_opts, "threads", 0, 0); | 339 | scale->sws->threads = 0; |
| 345 | if (ret < 0) | ||
| 346 | return ret; | ||
| 347 | 340 | ||
| 348 | ff_framesync_preinit(&scale->fs); | 341 | ff_framesync_preinit(&scale->fs); |
| 349 | 342 | ||
| 350 | return 0; | 343 | return 0; |
| 351 | } | 344 | } |
| 352 | 345 | ||
| 353 | static const int sws_colorspaces[] = { | ||
| 354 | AVCOL_SPC_UNSPECIFIED, | ||
| 355 | AVCOL_SPC_RGB, | ||
| 356 | AVCOL_SPC_BT709, | ||
| 357 | AVCOL_SPC_BT470BG, | ||
| 358 | AVCOL_SPC_SMPTE170M, | ||
| 359 | AVCOL_SPC_FCC, | ||
| 360 | AVCOL_SPC_SMPTE240M, | ||
| 361 | AVCOL_SPC_BT2020_NCL, | ||
| 362 | -1 | ||
| 363 | }; | ||
| 364 | |||
| 365 | static int do_scale(FFFrameSync *fs); | 346 | static int do_scale(FFFrameSync *fs); |
| 366 | 347 | ||
| 367 | static av_cold int init(AVFilterContext *ctx) | 348 | static av_cold int init(AVFilterContext *ctx) |
| 368 | { | 349 | { |
| 369 | ScaleContext *scale = ctx->priv; | 350 | ScaleContext *scale = ctx->priv; |
| 370 | int64_t threads; | ||
| 371 | int ret; | 351 | int ret; |
| 372 | 352 | ||
| 373 | if (ctx->filter == &ff_vf_scale2ref) | 353 | if (ctx->filter == &ff_vf_scale2ref) |
| @@ -407,14 +387,13 @@ static av_cold int init(AVFilterContext *ctx) · 33 unmodified lines | |||
| 407 | if (ret < 0) | 387 | if (ret < 0) |
| 408 | return ret; | 388 | return ret; |
| 409 | 389 | ||
| 410 | if (scale->in_color_matrix != -1 && | 390 | if (scale->in_color_matrix != -1 && !sws_test_colorspace(scale->in_color_matrix, 0)) { |
| 411 | !ff_fmt_is_in(scale->in_color_matrix, sws_colorspaces)) { | ||
| 412 | av_log(ctx, AV_LOG_ERROR, "Unsupported input color matrix '%s'\n", | 391 | av_log(ctx, AV_LOG_ERROR, "Unsupported input color matrix '%s'\n", |
| 413 | av_color_space_name(scale->in_color_matrix)); | 392 | av_color_space_name(scale->in_color_matrix)); |
| 414 | return AVERROR(EINVAL); | 393 | return AVERROR(EINVAL); |
| 415 | } | 394 | } |
| 416 | 395 | ||
| 417 | if (!ff_fmt_is_in(scale->out_color_matrix, sws_colorspaces)) { | 396 | if (scale->out_color_matrix != -1 && !sws_test_colorspace(scale->out_color_matrix, 1)) { |
| 418 | av_log(ctx, AV_LOG_ERROR, "Unsupported output color matrix '%s'\n", | 397 | av_log(ctx, AV_LOG_ERROR, "Unsupported output color matrix '%s'\n", |
| 419 | av_color_space_name(scale->out_color_matrix)); | 398 | av_color_space_name(scale->out_color_matrix)); |
| 420 | return AVERROR(EINVAL); | 399 | return AVERROR(EINVAL); |
| @@ -424,25 +403,23 @@ static av_cold int init(AVFilterContext *ctx) · 3 unmodified lines | |||
| 424 | scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); | 403 | scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); |
| 425 | 404 | ||
| 426 | if (scale->flags_str && *scale->flags_str) { | 405 | if (scale->flags_str && *scale->flags_str) { |
| 427 | ret = av_opt_set(scale->sws_opts, "sws_flags", scale->flags_str, 0); | 406 | ret = av_opt_set(scale->sws, "sws_flags", scale->flags_str, 0); |
| 428 | if (ret < 0) | 407 | if (ret < 0) |
| 429 | return ret; | 408 | return ret; |
| 430 | } | 409 | } |
| 431 | 410 | ||
| 432 | for (int i = 0; i < FF_ARRAY_ELEMS(scale->param); i++) | 411 | for (int i = 0; i < FF_ARRAY_ELEMS(scale->param); i++) |
| 433 | if (scale->param[i] != DBL_MAX) { | 412 | if (scale->param[i] != DBL_MAX) |
| 434 | ret = av_opt_set_double(scale->sws_opts, i ? "param1" : "param0", | 413 | scale->sws->scaler_params[i] = scale->param[i]; |
| 435 | scale->param[i], 0); | 414 | |
| 436 | if (ret < 0) | 415 | scale->sws->src_h_chr_pos = scale->in_h_chr_pos; |
| 437 | return ret; | 416 | scale->sws->src_v_chr_pos = scale->in_v_chr_pos; |
| 438 | } | 417 | scale->sws->dst_h_chr_pos = scale->out_h_chr_pos; |
| 418 | scale->sws->dst_v_chr_pos = scale->out_v_chr_pos; | ||
| 439 | 419 | ||
| 440 | // use generic thread-count if the user did not set it explicitly | 420 | // use generic thread-count if the user did not set it explicitly |
| 441 | ret = av_opt_get_int(scale->sws_opts, "threads", 0, &threads); | 421 | if (!scale->sws->threads) |
| 442 | if (ret < 0) | 422 | scale->sws->threads = ff_filter_get_nb_threads(ctx); |
| 443 | return ret; | ||
| 444 | if (!threads) | ||
| 445 | av_opt_set_int(scale->sws_opts, "threads", ff_filter_get_nb_threads(ctx), 0); | ||
| 446 | 423 | ||
| 447 | if (ctx->filter != &ff_vf_scale2ref && scale->uses_ref) { | 424 | if (ctx->filter != &ff_vf_scale2ref && scale->uses_ref) { |
| 448 | AVFilterPad pad = { | 425 | AVFilterPad pad = { |
| @@ -464,11 +441,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 15 unmodified lines | |||
| 464 | av_expr_free(scale->h_pexpr); | 441 | av_expr_free(scale->h_pexpr); |
| 465 | scale->w_pexpr = scale->h_pexpr = NULL; | 442 | scale->w_pexpr = scale->h_pexpr = NULL; |
| 466 | ff_framesync_uninit(&scale->fs); | 443 | ff_framesync_uninit(&scale->fs); |
| 467 | sws_freeContext(scale->sws_opts); | 444 | sws_free_context(&scale->sws); |
| 468 | sws_freeContext(scale->sws); | ||
| 469 | sws_freeContext(scale->isws[0]); | ||
| 470 | sws_freeContext(scale->isws[1]); | ||
| 471 | scale->sws = NULL; | ||
| 472 | } | 445 | } |
| 473 | 446 | ||
| 474 | static int query_formats(const AVFilterContext *ctx, | 447 | static int query_formats(const AVFilterContext *ctx, |
| @@ -485,10 +458,9 @@ static int query_formats(const AVFilterContext *ctx, · 10 unmodified lines | |||
| 485 | formats = NULL; | 458 | formats = NULL; |
| 486 | while ((desc = av_pix_fmt_desc_next(desc))) { | 459 | while ((desc = av_pix_fmt_desc_next(desc))) { |
| 487 | pix_fmt = av_pix_fmt_desc_get_id(desc); | 460 | pix_fmt = av_pix_fmt_desc_get_id(desc); |
| 488 | if ((sws_isSupportedInput(pix_fmt) || | 461 | if (sws_test_format(pix_fmt, 0)) { |
| 489 | sws_isSupportedEndiannessConversion(pix_fmt)) | 462 | if ((ret = ff_add_format(&formats, pix_fmt)) < 0) |
| 490 | && (ret = ff_add_format(&formats, pix_fmt)) < 0) { | 463 | return ret; |
| 491 | return ret; | ||
| 492 | } | 464 | } |
| 493 | } | 465 | } |
| 494 | if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0) | 466 | if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0) |
| @@ -498,18 +470,24 @@ static int query_formats(const AVFilterContext *ctx, · 3 unmodified lines | |||
| 498 | formats = NULL; | 470 | formats = NULL; |
| 499 | while ((desc = av_pix_fmt_desc_next(desc))) { | 471 | while ((desc = av_pix_fmt_desc_next(desc))) { |
| 500 | pix_fmt = av_pix_fmt_desc_get_id(desc); | 472 | pix_fmt = av_pix_fmt_desc_get_id(desc); |
| 501 | if ((sws_isSupportedOutput(pix_fmt) || pix_fmt == AV_PIX_FMT_PAL8 || | 473 | if (sws_test_format(pix_fmt, 1) || pix_fmt == AV_PIX_FMT_PAL8) { |
| 502 | sws_isSupportedEndiannessConversion(pix_fmt)) | 474 | if ((ret = ff_add_format(&formats, pix_fmt)) < 0) |
| 503 | && (ret = ff_add_format(&formats, pix_fmt)) < 0) { | 475 | return ret; |
| 504 | return ret; | ||
| 505 | } | 476 | } |
| 506 | } | 477 | } |
| 507 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->formats)) < 0) | 478 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->formats)) < 0) |
| 508 | return ret; | 479 | return ret; |
| 509 | 480 | ||
| 510 | /* accept all supported inputs, even if user overrides their properties */ | 481 | /* accept all supported inputs, even if user overrides their properties */ |
| 511 | if ((ret = ff_formats_ref(ff_make_format_list(sws_colorspaces), | 482 | formats = ff_all_color_spaces(); |
| 512 | &cfg_in[0]->color_spaces)) < 0) | 483 | for (int i = 0; i < formats->nb_formats; i++) { |
| 484 | if (!sws_test_colorspace(formats->formats[i], 0)) { | ||
| 485 | for (int j = i--; j < formats->nb_formats; j++) | ||
| 486 | formats->formats[j] = formats->formats[j + 1]; | ||
| 487 | formats->nb_formats--; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | if ((ret = ff_formats_ref(formats, &cfg_in[0]->color_spaces)) < 0) | ||
| 513 | return ret; | 491 | return ret; |
| 514 | 492 | ||
| 515 | if ((ret = ff_formats_ref(ff_all_color_ranges(), | 493 | if ((ret = ff_formats_ref(ff_all_color_ranges(), |
| @@ -517,9 +495,18 @@ static int query_formats(const AVFilterContext *ctx, · 1 unmodified line | |||
| 517 | return ret; | 495 | return ret; |
| 518 | 496 | ||
| 519 | /* propagate output properties if overridden */ | 497 | /* propagate output properties if overridden */ |
| 520 | formats = scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED | 498 | if (scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED) { |
| 521 | ? ff_make_formats_list_singleton(scale->out_color_matrix) | 499 | formats = ff_make_formats_list_singleton(scale->out_color_matrix); |
| 522 | : ff_make_format_list(sws_colorspaces); | 500 | } else { |
| 501 | formats = ff_all_color_spaces(); | ||
| 502 | for (int i = 0; i < formats->nb_formats; i++) { | ||
| 503 | if (!sws_test_colorspace(formats->formats[i], 1)) { | ||
| 504 | for (int j = i--; j < formats->nb_formats; j++) | ||
| 505 | formats->formats[j] = formats->formats[j + 1]; | ||
| 506 | formats->nb_formats--; | ||
| 507 | } | ||
| 508 | } | ||
| 509 | } | ||
| 523 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_spaces)) < 0) | 510 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_spaces)) < 0) |
| 524 | return ret; | 511 | return ret; |
| 525 | 512 | ||
| @@ -621,50 +608,6 @@ fail: · 95 unmodified lines | |||
| 621 | return ret; | 608 | return ret; |
| 622 | } | 609 | } |
| 623 | 610 | ||
| 624 | static void calc_chroma_pos(int *h_pos_out, int *v_pos_out, int chroma_loc, | ||
| 625 | int h_pos_override, int v_pos_override, | ||
| 626 | int h_sub, int v_sub, int index) | ||
| 627 | { | ||
| 628 | int h_pos, v_pos; | ||
| 629 | |||
| 630 | /* Explicitly default to center siting for compatibility with swscale */ | ||
| 631 | if (chroma_loc == AVCHROMA_LOC_UNSPECIFIED) | ||
| 632 | chroma_loc = AVCHROMA_LOC_CENTER; | ||
| 633 | |||
| 634 | /* av_chroma_location_enum_to_pos() always gives us values in the range from | ||
| 635 | * 0 to 256, but we need to adjust this to the true value range of the | ||
| 636 | * subsampling grid, which may be larger for h/v_sub > 1 */ | ||
| 637 | av_chroma_location_enum_to_pos(&h_pos, &v_pos, chroma_loc); | ||
| 638 | h_pos *= (1 << h_sub) - 1; | ||
| 639 | v_pos *= (1 << v_sub) - 1; | ||
| 640 | |||
| 641 | if (h_pos_override != -513) | ||
| 642 | h_pos = h_pos_override; | ||
| 643 | if (v_pos_override != -513) | ||
| 644 | v_pos = v_pos_override; | ||
| 645 | |||
| 646 | /* Fix vertical chroma position for interlaced frames */ | ||
| 647 | if (v_sub && index > 0) { | ||
| 648 | /* When vertically subsampling, chroma samples are effectively only | ||
| 649 | * placed next to even rows. To access them from the odd field, we need | ||
| 650 | * to account for this shift by offsetting the distance of one luma row. | ||
| 651 | * | ||
| 652 | * For 4x vertical subsampling (v_sub == 2), they are only placed | ||
| 653 | * next to every *other* even row, so we need to shift by three luma | ||
| 654 | * rows to get to the chroma sample. */ | ||
| 655 | if (index == 2) | ||
| 656 | v_pos += (256 << v_sub) - 256; | ||
| 657 | |||
| 658 | /* Luma row distance is doubled for fields, so halve offsets */ | ||
| 659 | v_pos >>= 1; | ||
| 660 | } | ||
| 661 | |||
| 662 | /* Explicitly strip chroma offsets when not subsampling, because it | ||
| 663 | * interferes with the operation of flags like SWS_FULL_CHR_H_INP */ | ||
| 664 | *h_pos_out = h_sub ? h_pos : -513; | ||
| 665 | *v_pos_out = v_sub ? v_pos : -513; | ||
| 666 | } | ||
| 667 | |||
| 668 | static int config_props(AVFilterLink *outlink) | 611 | static int config_props(AVFilterLink *outlink) |
| 669 | { | 612 | { |
| 670 | AVFilterContext *ctx = outlink->src; | 613 | AVFilterContext *ctx = outlink->src; |
| @@ -672,12 +615,8 @@ static int config_props(AVFilterLink *outlink) · 1 unmodified line | |||
| 672 | AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref ? | 615 | AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref ? |
| 673 | outlink->src->inputs[1] : | 616 | outlink->src->inputs[1] : |
| 674 | outlink->src->inputs[0]; | 617 | outlink->src->inputs[0]; |
| 675 | enum AVPixelFormat outfmt = outlink->format; | ||
| 676 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | ||
| 677 | const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outfmt); | ||
| 678 | ScaleContext *scale = ctx->priv; | 618 | ScaleContext *scale = ctx->priv; |
| 679 | uint8_t *flags_val = NULL; | 619 | uint8_t *flags_val = NULL; |
| 680 | int in_range, in_colorspace; | ||
| 681 | int ret; | 620 | int ret; |
| 682 | 621 | ||
| 683 | if ((ret = scale_eval_dimensions(ctx)) < 0) | 622 | if ((ret = scale_eval_dimensions(ctx)) < 0) |
| @@ -701,107 +640,12 @@ static int config_props(AVFilterLink *outlink) · 17 unmodified lines | |||
| 701 | 640 | ||
| 702 | /* TODO: make algorithm configurable */ | 641 | /* TODO: make algorithm configurable */ |
| 703 | 642 | ||
| 704 | scale->input_is_pal = desc->flags & AV_PIX_FMT_FLAG_PAL; | ||
| 705 | if (outfmt == AV_PIX_FMT_PAL8) outfmt = AV_PIX_FMT_BGR8; | ||
| 706 | scale->output_is_pal = av_pix_fmt_desc_get(outfmt)->flags & AV_PIX_FMT_FLAG_PAL; | ||
| 707 | |||
| 708 | in_range = scale->in_range; | ||
| 709 | if (in_range == AVCOL_RANGE_UNSPECIFIED) | ||
| 710 | in_range = inlink0->color_range; | ||
| 711 | |||
| 712 | in_colorspace = scale->in_color_matrix; | ||
| 713 | if (in_colorspace == -1 /* auto */) | ||
| 714 | in_colorspace = inlink0->colorspace; | ||
| 715 | |||
| 716 | if (scale->sws) | ||
| 717 | sws_freeContext(scale->sws); | ||
| 718 | if (scale->isws[0]) | ||
| 719 | sws_freeContext(scale->isws[0]); | ||
| 720 | if (scale->isws[1]) | ||
| 721 | sws_freeContext(scale->isws[1]); | ||
| 722 | scale->isws[0] = scale->isws[1] = scale->sws = NULL; | ||
| 723 | if (inlink0->w == outlink->w && | ||
| 724 | inlink0->h == outlink->h && | ||
| 725 | in_range == outlink->color_range && | ||
| 726 | in_colorspace == outlink->colorspace && | ||
| 727 | inlink0->format == outlink->format && | ||
| 728 | scale->in_chroma_loc == scale->out_chroma_loc) | ||
| 729 | ; | ||
| 730 | else { | ||
| 731 | struct SwsContext **swscs[3] = {&scale->sws, &scale->isws[0], &scale->isws[1]}; | ||
| 732 | int i; | ||
| 733 | |||
| 734 | for (i = 0; i < 3; i++) { | ||
| 735 | int in_full, out_full, brightness, contrast, saturation; | ||
| 736 | int h_chr_pos, v_chr_pos; | ||
| 737 | const int *inv_table, *table; | ||
| 738 | struct SwsContext *const s = sws_alloc_context(); | ||
| 739 | if (!s) | ||
| 740 | return AVERROR(ENOMEM); | ||
| 741 | *swscs[i] = s; | ||
| 742 | |||
| 743 | ret = av_opt_copy(s, scale->sws_opts); | ||
| 744 | if (ret < 0) | ||
| 745 | return ret; | ||
| 746 | |||
| 747 | av_opt_set_int(s, "srcw", inlink0 ->w, 0); | ||
| 748 | av_opt_set_int(s, "srch", inlink0 ->h >> !!i, 0); | ||
| 749 | av_opt_set_int(s, "src_format", inlink0->format, 0); | ||
| 750 | av_opt_set_int(s, "dstw", outlink->w, 0); | ||
| 751 | av_opt_set_int(s, "dsth", outlink->h >> !!i, 0); | ||
| 752 | av_opt_set_int(s, "dst_format", outfmt, 0); | ||
| 753 | if (in_range != AVCOL_RANGE_UNSPECIFIED) | ||
| 754 | av_opt_set_int(s, "src_range", | ||
| 755 | in_range == AVCOL_RANGE_JPEG, 0); | ||
| 756 | if (outlink->color_range != AVCOL_RANGE_UNSPECIFIED) | ||
| 757 | av_opt_set_int(s, "dst_range", | ||
| 758 | outlink->color_range == AVCOL_RANGE_JPEG, 0); | ||
| 759 | |||
| 760 | calc_chroma_pos(&h_chr_pos, &v_chr_pos, scale->in_chroma_loc, | ||
| 761 | scale->in_h_chr_pos, scale->in_v_chr_pos, | ||
| 762 | desc->log2_chroma_w, desc->log2_chroma_h, i); | ||
| 763 | av_opt_set_int(s, "src_h_chr_pos", h_chr_pos, 0); | ||
| 764 | av_opt_set_int(s, "src_v_chr_pos", v_chr_pos, 0); | ||
| 765 | |||
| 766 | calc_chroma_pos(&h_chr_pos, &v_chr_pos, scale->out_chroma_loc, | ||
| 767 | scale->out_h_chr_pos, scale->out_v_chr_pos, | ||
| 768 | outdesc->log2_chroma_w, outdesc->log2_chroma_h, i); | ||
| 769 | av_opt_set_int(s, "dst_h_chr_pos", h_chr_pos, 0); | ||
| 770 | av_opt_set_int(s, "dst_v_chr_pos", v_chr_pos, 0); | ||
| 771 | |||
| 772 | if ((ret = sws_init_context(s, NULL, NULL)) < 0) | ||
| 773 | return ret; | ||
| 774 | |||
| 775 | sws_getColorspaceDetails(s, (int **)&inv_table, &in_full, | ||
| 776 | (int **)&table, &out_full, | ||
| 777 | &brightness, &contrast, &saturation); | ||
| 778 | |||
| 779 | if (scale->in_color_matrix == -1 /* auto */) | ||
| 780 | inv_table = sws_getCoefficients(inlink0->colorspace); | ||
| 781 | else if (scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED) | ||
| 782 | inv_table = sws_getCoefficients(scale->in_color_matrix); | ||
| 783 | if (outlink->colorspace != AVCOL_SPC_UNSPECIFIED) | ||
| 784 | table = sws_getCoefficients(outlink->colorspace); | ||
| 785 | else if (scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED) | ||
| 786 | table = inv_table; | ||
| 787 | |||
| 788 | sws_setColorspaceDetails(s, inv_table, in_full, | ||
| 789 | table, out_full, | ||
| 790 | brightness, contrast, saturation); | ||
| 791 | |||
| 792 | if (!scale->interlaced) | ||
| 793 | break; | ||
| 794 | } | ||
| 795 | } | ||
| 796 | |||
| 797 | if (inlink0->sample_aspect_ratio.num){ | 643 | if (inlink0->sample_aspect_ratio.num){ |
| 798 | outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink0->w, outlink->w * inlink0->h}, inlink0->sample_aspect_ratio); | 644 | outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink0->w, outlink->w * inlink0->h}, inlink0->sample_aspect_ratio); |
| 799 | } else | 645 | } else |
| 800 | outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; | 646 | outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; |
| 801 | 647 | ||
| 802 | if (scale->sws) | 648 | av_opt_get(scale->sws, "sws_flags", 0, &flags_val); |
| 803 | av_opt_get(scale->sws, "sws_flags", 0, &flags_val); | ||
| 804 | |||
| 805 | av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d -> w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d flags:%s\n", | 649 | av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d -> w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d flags:%s\n", |
| 806 | inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), | 650 | inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), |
| 807 | av_color_space_name(inlink->colorspace), av_color_range_name(inlink->color_range), | 651 | av_color_space_name(inlink->colorspace), av_color_range_name(inlink->color_range), |
| @@ -868,56 +712,6 @@ static int request_frame_ref(AVFilterLink *outlink) · 60 unmodified lines | |||
| 868 | return ff_request_frame(outlink->src->inputs[1]); | 712 | return ff_request_frame(outlink->src->inputs[1]); |
| 869 | } | 713 | } |
| 870 | 714 | ||
| 871 | static void frame_offset(AVFrame *frame, int dir, int is_pal) | ||
| 872 | { | ||
| 873 | for (int i = 0; i < 4 && frame->data[i]; i++) { | ||
| 874 | if (i == 1 && is_pal) | ||
| 875 | break; | ||
| 876 | frame->data[i] += frame->linesize[i] * dir; | ||
| 877 | } | ||
| 878 | } | ||
| 879 | |||
| 880 | static int scale_field(ScaleContext *scale, AVFrame *dst, AVFrame *src, | ||
| 881 | int field) | ||
| 882 | { | ||
| 883 | int orig_h_src = src->height; | ||
| 884 | int orig_h_dst = dst->height; | ||
| 885 | int ret; | ||
| 886 | |||
| 887 | // offset the data pointers for the bottom field | ||
| 888 | if (field) { | ||
| 889 | frame_offset(src, 1, scale->input_is_pal); | ||
| 890 | frame_offset(dst, 1, scale->output_is_pal); | ||
| 891 | } | ||
| 892 | |||
| 893 | // take every second line | ||
| 894 | for (int i = 0; i < 4; i++) { | ||
| 895 | src->linesize[i] *= 2; | ||
| 896 | dst->linesize[i] *= 2; | ||
| 897 | } | ||
| 898 | src->height /= 2; | ||
| 899 | dst->height /= 2; | ||
| 900 | |||
| 901 | ret = sws_scale_frame(scale->isws[field], dst, src); | ||
| 902 | if (ret < 0) | ||
| 903 | return ret; | ||
| 904 | |||
| 905 | // undo the changes we made above | ||
| 906 | for (int i = 0; i < 4; i++) { | ||
| 907 | src->linesize[i] /= 2; | ||
| 908 | dst->linesize[i] /= 2; | ||
| 909 | } | ||
| 910 | src->height = orig_h_src; | ||
| 911 | dst->height = orig_h_dst; | ||
| 912 | |||
| 913 | if (field) { | ||
| 914 | frame_offset(src, -1, scale->input_is_pal); | ||
| 915 | frame_offset(dst, -1, scale->output_is_pal); | ||
| 916 | } | ||
| 917 | |||
| 918 | return 0; | ||
| 919 | } | ||
| 920 | |||
| 921 | /* Takes over ownership of *frame_in, passes ownership of *frame_out to caller */ | 715 | /* Takes over ownership of *frame_in, passes ownership of *frame_out to caller */ |
| 922 | static int scale_frame(AVFilterLink *link, AVFrame **frame_in, | 716 | static int scale_frame(AVFilterLink *link, AVFrame **frame_in, |
| 923 | AVFrame **frame_out) | 717 | AVFrame **frame_out) |
| @@ -929,12 +723,9 @@ static int scale_frame(AVFilterLink *link, AVFrame **frame_in, · 5 unmodified lines | |||
| 929 | AVFrame *out, *in = *frame_in; | 723 | AVFrame *out, *in = *frame_in; |
| 930 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); | 724 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); |
| 931 | char buf[32]; | 725 | char buf[32]; |
| 932 | int ret; | 726 | int ret, flags_orig, frame_changed; |
| 933 | int frame_changed; | ||
| 934 | 727 | ||
| 935 | *frame_in = NULL; | 728 | *frame_in = NULL; |
| 936 | if (in->colorspace == AVCOL_SPC_YCGCO) | ||
| 937 | av_log(link->dst, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); | ||
| 938 | 729 | ||
| 939 | frame_changed = in->width != link->w || | 730 | frame_changed = in->width != link->w || |
| 940 | in->height != link->h || | 731 | in->height != link->h || |
| @@ -1013,11 +804,6 @@ FF_ENABLE_DEPRECATION_WARNINGS · 72 unmodified lines | |||
| 1013 | } | 804 | } |
| 1014 | 805 | ||
| 1015 | scale: | 806 | scale: |
| 1016 | if (!scale->sws) { | ||
| 1017 | *frame_out = in; | ||
| 1018 | return 0; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | scale->hsub = desc->log2_chroma_w; | 807 | scale->hsub = desc->log2_chroma_w; |
| 1022 | scale->vsub = desc->log2_chroma_h; | 808 | scale->vsub = desc->log2_chroma_h; |
| 1023 | 809 | ||
| @@ -1027,6 +813,18 @@ scale: · 3 unmodified lines | |||
| 1027 | goto err; | 813 | goto err; |
| 1028 | } | 814 | } |
| 1029 | 815 | ||
| 816 | if (scale->in_color_matrix != -1) | ||
| 817 | in->colorspace = scale->in_color_matrix; | ||
| 818 | if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) | ||
| 819 | in->color_range = scale->in_range; | ||
| 820 | in->chroma_location = scale->in_chroma_loc; | ||
| 821 | |||
| 822 | flags_orig = in->flags; | ||
| 823 | if (scale->interlaced > 0) | ||
| 824 | in->flags |= AV_FRAME_FLAG_INTERLACED; | ||
| 825 | else if (!scale->interlaced) | ||
| 826 | in->flags &= ~AV_FRAME_FLAG_INTERLACED; | ||
| 827 | |||
| 1030 | av_frame_copy_props(out, in); | 828 | av_frame_copy_props(out, in); |
| 1031 | out->width = outlink->w; | 829 | out->width = outlink->w; |
| 1032 | out->height = outlink->h; | 830 | out->height = outlink->h; |
| @@ -1035,26 +833,31 @@ scale: · 2 unmodified lines | |||
| 1035 | if (scale->out_chroma_loc != AVCHROMA_LOC_UNSPECIFIED) | 833 | if (scale->out_chroma_loc != AVCHROMA_LOC_UNSPECIFIED) |
| 1036 | out->chroma_location = scale->out_chroma_loc; | 834 | out->chroma_location = scale->out_chroma_loc; |
| 1037 | 835 | ||
| 1038 | if (scale->output_is_pal) | ||
| 1039 | avpriv_set_systematic_pal2((uint32_t*)out->data[1], outlink->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : outlink->format); | ||
| 1040 | |||
| 1041 | av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, | 836 | av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, |
| 1042 | (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, | 837 | (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, |
| 1043 | (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, | 838 | (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, |
| 1044 | INT_MAX); | 839 | INT_MAX); |
| 1045 | 840 | ||
| 1046 | if (scale->interlaced>0 || (scale->interlaced<0 && | 841 | if (sws_is_noop(out, in)) { |
| 1047 | (in->flags & AV_FRAME_FLAG_INTERLACED))) { | 842 | av_frame_free(&out); |
| 1048 | ret = scale_field(scale, out, in, 0); | 843 | in->flags = flags_orig; |
| 1049 | if (ret >= 0) | 844 | *frame_out = in; |
| 1050 | ret = scale_field(scale, out, in, 1); | 845 | return 0; |
| 1051 | } else { | ||
| 1052 | ret = sws_scale_frame(scale->sws, out, in); | ||
| 1053 | } | 846 | } |
| 1054 | 847 | ||
| 848 | if (out->format == AV_PIX_FMT_PAL8) { | ||
| 849 | out->format = AV_PIX_FMT_BGR8; | ||
| 850 | avpriv_set_systematic_pal2((uint32_t*) out->data[1], out->format); | ||
| 851 | } | ||
| 852 | |||
| 853 | ret = sws_scale_frame(scale->sws, out, in); | ||
| 854 | av_frame_free(&in); | ||
| 855 | out->flags = flags_orig; | ||
| 856 | out->format = outlink->format; /* undo PAL8 handling */ | ||
| 1055 | if (ret < 0) | 857 | if (ret < 0) |
| 1056 | av_frame_free(&out); | 858 | av_frame_free(&out); |
| 1057 | *frame_out = out; | 859 | *frame_out = out; |
| 860 | return ret; | ||
| 1058 | 861 | ||
| 1059 | err: | 862 | err: |
| 1060 | av_frame_free(&in); | 863 | av_frame_free(&in); |
| @@ -1232,8 +1035,8 @@ static void *child_next(void *obj, void *prev) · 171 unmodified lines | |||
| 1232 | { | 1035 | { |
| 1233 | ScaleContext *s = obj; | 1036 | ScaleContext *s = obj; |
| 1234 | if (!prev) | 1037 | if (!prev) |
| 1235 | return s->sws_opts; | 1038 | return s->sws; |
| 1236 | if (prev == s->sws_opts) | 1039 | if (prev == s->sws) |
| 1237 | return &s->fs; | 1040 | return &s->fs; |
| 1238 | return NULL; | 1041 | return NULL; |
| 1239 | } | 1042 | } |
| @@ -1350,7 +1153,7 @@ static void *scale2ref_child_next(void *obj, void *prev) · 110 unmodified lines | |||
| 1350 | { | 1153 | { |
| 1351 | ScaleContext *s = obj; | 1154 | ScaleContext *s = obj; |
| 1352 | if (!prev) | 1155 | if (!prev) |
| 1353 | return s->sws_opts; | 1156 | return s->sws; |
| 1354 | return NULL; | 1157 | return NULL; |
| 1355 | } | 1158 | } |
| 1356 | 1159 | ||