diff options
Diffstat (limited to 'src/i965_vpp_avs.c')
-rw-r--r-- | src/i965_vpp_avs.c | 271 |
1 files changed, 0 insertions, 271 deletions
diff --git a/src/i965_vpp_avs.c b/src/i965_vpp_avs.c deleted file mode 100644 index 58d0949..0000000 --- a/src/i965_vpp_avs.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * i965_vpp_avs.c - Adaptive Video Scaler (AVS) block - * - * Copyright (C) 2014 Intel Corporation - * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "sysdeps.h" -#include <math.h> -#include <va/va.h> -#include "i965_vpp_avs.h" - -typedef void (*AVSGenCoeffsFunc)(float *coeffs, int num_coeffs, int phase, - int num_phases, float f); - -/* Initializes all coefficients to zero */ -static void -avs_init_coeffs(float *coeffs, int num_coeffs) -{ -#if defined(__STDC_IEC_559__) && (__STDC_IEC_559__ > 0) - memset(coeffs, 0, num_coeffs * sizeof(*coeffs)); -#else - int i; - - for (i = 0; i < num_coeffs; i++) - coeffs[i] = 0.0f; -#endif -} - -/* Computes the sinc(x) function */ -static float -avs_sinc(float x) -{ - if (x == 0.0f) - return 1.0f; - return sin(x * M_PI) / (x * M_PI); -} - -/* Convolution kernel for linear interpolation */ -static float -avs_kernel_linear(float x) -{ - const float abs_x = fabsf(x); - - return abs_x < 1.0f ? 1 - abs_x : 0.0f; -} - -/* Convolution kernel for Lanczos-based interpolation */ -static float -avs_kernel_lanczos(float x, float a) -{ - const float abs_x = fabsf(x); - - return abs_x < a ? avs_sinc(x) * avs_sinc(x / a) : 0.0f; -} - -/* Truncates floating-point value towards an epsilon factor */ -static inline float -avs_trunc_coeff(float x, float epsilon) -{ - return rintf(x / epsilon) * epsilon; -} - -/* Normalize coefficients for one sample/direction */ -static void -avs_normalize_coeffs_1(float *coeffs, int num_coeffs, float epsilon) -{ - float s, sum = 0.0; - int i, c, r, r1; - - for (i = 0; i < num_coeffs; i++) - sum += coeffs[i]; - - if (sum < epsilon) - return; - - s = 0.0; - for (i = 0; i < num_coeffs; i++) - s += (coeffs[i] = avs_trunc_coeff(coeffs[i] / sum, epsilon)); - - /* Distribute the remaining bits, while allocating more to the center */ - c = num_coeffs/2; - c = c - (coeffs[c - 1] > coeffs[c]); - - r = (1.0f - s) / epsilon; - r1 = r / 4; - if (coeffs[c + 1] == 0.0f) - coeffs[c] += r * epsilon; - else { - coeffs[c] += (r - 2*r1) * epsilon; - coeffs[c - 1] += r1 * epsilon; - coeffs[c + 1] += r1 * epsilon; - } -} - -/* Normalize all coefficients so that their sum yields 1.0f */ -static void -avs_normalize_coeffs(AVSCoeffs *coeffs, const AVSConfig *config) -{ - avs_normalize_coeffs_1(coeffs->y_k_h, config->num_luma_coeffs, - config->coeff_epsilon); - avs_normalize_coeffs_1(coeffs->y_k_v, config->num_luma_coeffs, - config->coeff_epsilon); - avs_normalize_coeffs_1(coeffs->uv_k_h, config->num_chroma_coeffs, - config->coeff_epsilon); - avs_normalize_coeffs_1(coeffs->uv_k_v, config->num_chroma_coeffs, - config->coeff_epsilon); -} - -/* Validate coefficients for one sample/direction */ -static bool -avs_validate_coeffs_1(float *coeffs, int num_coeffs, const float *min_coeffs, - const float *max_coeffs) -{ - int i; - - for (i = 0; i < num_coeffs; i++) { - if (coeffs[i] < min_coeffs[i] || coeffs[i] > max_coeffs[i]) - return false; - } - return true; -} - -/* Validate coefficients wrt. the supplied range in config */ -static bool -avs_validate_coeffs(AVSCoeffs *coeffs, const AVSConfig *config) -{ - const AVSCoeffs * const min_coeffs = &config->coeff_range.lower_bound; - const AVSCoeffs * const max_coeffs = &config->coeff_range.upper_bound; - - return avs_validate_coeffs_1(coeffs->y_k_h, config->num_luma_coeffs, - min_coeffs->y_k_h, max_coeffs->y_k_h) && - avs_validate_coeffs_1(coeffs->y_k_v, config->num_luma_coeffs, - min_coeffs->y_k_v, max_coeffs->y_k_v) && - avs_validate_coeffs_1(coeffs->uv_k_h, config->num_chroma_coeffs, - min_coeffs->uv_k_h, max_coeffs->uv_k_h) && - avs_validate_coeffs_1(coeffs->uv_k_v, config->num_chroma_coeffs, - min_coeffs->uv_k_v, max_coeffs->uv_k_v); -} - -/* Generate coefficients for default quality (bilinear) */ -static void -avs_gen_coeffs_linear(float *coeffs, int num_coeffs, int phase, int num_phases, - float f) -{ - const int c = num_coeffs/2 - 1; - const float p = (float)phase / (num_phases*2); - - avs_init_coeffs(coeffs, num_coeffs); - coeffs[c] = avs_kernel_linear(p); - coeffs[c + 1] = avs_kernel_linear(p - 1); -} - -/* Generate coefficients for high quality (lanczos) */ -static void -avs_gen_coeffs_lanczos(float *coeffs, int num_coeffs, int phase, int num_phases, - float f) -{ - const int c = num_coeffs/2 - 1; - const int l = num_coeffs > 4 ? 3 : 2; - const float p = (float)phase / (num_phases*2); - int i; - - if (f > 1.0f) - f = 1.0f; - for (i = 0; i < num_coeffs; i++) - coeffs[i] = avs_kernel_lanczos((i - (c + p)) * f, l); -} - -/* Generate coefficients with the supplied scaler */ -static bool -avs_gen_coeffs(AVSState *avs, float sx, float sy, AVSGenCoeffsFunc gen_coeffs) -{ - const AVSConfig * const config = avs->config; - int i; - - for (i = 0; i <= config->num_phases; i++) { - AVSCoeffs * const coeffs = &avs->coeffs[i]; - - gen_coeffs(coeffs->y_k_h, config->num_luma_coeffs, - i, config->num_phases, sx); - gen_coeffs(coeffs->uv_k_h, config->num_chroma_coeffs, - i, config->num_phases, sx); - gen_coeffs(coeffs->y_k_v, config->num_luma_coeffs, - i, config->num_phases, sy); - gen_coeffs(coeffs->uv_k_v, config->num_chroma_coeffs, - i, config->num_phases, sy); - - avs_normalize_coeffs(coeffs, config); - if (!avs_validate_coeffs(coeffs, config)) - return false; - } - return true; -} - -/* Initializes AVS state with the supplied configuration */ -void -avs_init_state(AVSState *avs, const AVSConfig *config) -{ - avs->config = config; - avs->flags = 0; - avs->scale_x = 0.0f; - avs->scale_y = 0.0f; -} - -/* Checks whether the AVS scaling parameters changed */ -static inline bool -avs_params_changed(AVSState *avs, float sx, float sy, uint32_t flags) -{ - if (avs->flags != flags) - return true; - - if (flags >= VA_FILTER_SCALING_HQ) { - if (avs->scale_x != sx || avs->scale_y != sy) - return true; - } - else { - if (avs->scale_x == 0.0f || avs->scale_y == 0.0f) - return true; - } - return false; -} - -/* Updates AVS coefficients for the supplied factors and quality level */ -bool -avs_update_coefficients(AVSState *avs, float sx, float sy, uint32_t flags) -{ - AVSGenCoeffsFunc gen_coeffs; - - flags &= VA_FILTER_SCALING_MASK; - if (!avs_params_changed(avs, sx, sy, flags)) - return true; - - switch (flags) { - case VA_FILTER_SCALING_HQ: - gen_coeffs = avs_gen_coeffs_lanczos; - break; - default: - gen_coeffs = avs_gen_coeffs_linear; - break; - } - if (!avs_gen_coeffs(avs, sx, sy, gen_coeffs)) { - assert(0 && "invalid set of coefficients generated"); - return false; - } - - avs->flags = flags; - avs->scale_x = sx; - avs->scale_y = sy; - return true; -} |