boxblur.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
  3. * Copyright (c) 2011 Stefano Sabatini
  4. * Copyright (c) 2018 Danil Iashchenko
  5. *
  6. * This file is part of FFmpeg.
  7. *
  8. * FFmpeg is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * FFmpeg is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with FFmpeg; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include "boxblur.h"
  23. static const char *const var_names[] = {
  24. "w",
  25. "h",
  26. "cw",
  27. "ch",
  28. "hsub",
  29. "vsub",
  30. NULL
  31. };
  32. enum var_name {
  33. VAR_W,
  34. VAR_H,
  35. VAR_CW,
  36. VAR_CH,
  37. VAR_HSUB,
  38. VAR_VSUB,
  39. VARS_NB
  40. };
  41. int ff_boxblur_eval_filter_params(AVFilterLink *inlink,
  42. FilterParam *luma_param,
  43. FilterParam *chroma_param,
  44. FilterParam *alpha_param)
  45. {
  46. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  47. AVFilterContext *ctx = inlink->dst;
  48. int w = inlink->w, h = inlink->h;
  49. int cw, ch;
  50. double var_values[VARS_NB], res;
  51. char *expr;
  52. int ret;
  53. if (!luma_param->radius_expr) {
  54. av_log(ctx, AV_LOG_ERROR, "Luma radius expression is not set.\n");
  55. return AVERROR(EINVAL);
  56. }
  57. /* fill missing params */
  58. if (!chroma_param->radius_expr) {
  59. chroma_param->radius_expr = av_strdup(luma_param->radius_expr);
  60. if (!chroma_param->radius_expr)
  61. return AVERROR(ENOMEM);
  62. }
  63. if (chroma_param->power < 0)
  64. chroma_param->power = luma_param->power;
  65. if (!alpha_param->radius_expr) {
  66. alpha_param->radius_expr = av_strdup(luma_param->radius_expr);
  67. if (!alpha_param->radius_expr)
  68. return AVERROR(ENOMEM);
  69. }
  70. if (alpha_param->power < 0)
  71. alpha_param->power = luma_param->power;
  72. var_values[VAR_W] = inlink->w;
  73. var_values[VAR_H] = inlink->h;
  74. var_values[VAR_CW] = cw = w>>(desc->log2_chroma_w);
  75. var_values[VAR_CH] = ch = h>>(desc->log2_chroma_h);
  76. var_values[VAR_HSUB] = 1<<(desc->log2_chroma_w);
  77. var_values[VAR_VSUB] = 1<<(desc->log2_chroma_h);
  78. #define EVAL_RADIUS_EXPR(comp) \
  79. expr = comp->radius_expr; \
  80. ret = av_expr_parse_and_eval(&res, expr, var_names, var_values, \
  81. NULL, NULL, NULL, NULL, NULL, 0, ctx); \
  82. comp->radius = res; \
  83. if (ret < 0) { \
  84. av_log(NULL, AV_LOG_ERROR, \
  85. "Error when evaluating " #comp " radius expression '%s'\n", expr); \
  86. return ret; \
  87. }
  88. EVAL_RADIUS_EXPR(luma_param);
  89. EVAL_RADIUS_EXPR(chroma_param);
  90. EVAL_RADIUS_EXPR(alpha_param);
  91. av_log(ctx, AV_LOG_VERBOSE,
  92. "luma_radius:%d luma_power:%d "
  93. "chroma_radius:%d chroma_power:%d "
  94. "alpha_radius:%d alpha_power:%d "
  95. "w:%d chroma_w:%d h:%d chroma_h:%d\n",
  96. luma_param ->radius, luma_param ->power,
  97. chroma_param->radius, chroma_param->power,
  98. alpha_param ->radius, alpha_param ->power,
  99. w, cw, h, ch);
  100. #define CHECK_RADIUS_VAL(w_, h_, comp) \
  101. if (comp->radius < 0 || \
  102. 2*comp->radius > FFMIN(w_, h_)) { \
  103. av_log(ctx, AV_LOG_ERROR, \
  104. "Invalid " #comp " radius value %d, must be >= 0 and <= %d\n", \
  105. comp->radius, FFMIN(w_, h_)/2); \
  106. return AVERROR(EINVAL); \
  107. }
  108. CHECK_RADIUS_VAL(w, h, luma_param);
  109. CHECK_RADIUS_VAL(cw, ch, chroma_param);
  110. CHECK_RADIUS_VAL(w, h, alpha_param);
  111. return 0;
  112. }