190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/* 2f71323e297a928af368937089d3ed71239786f86Andreas Huber * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber * 4f71323e297a928af368937089d3ed71239786f86Andreas Huber * Use of this source code is governed by a BSD-style license 5f71323e297a928af368937089d3ed71239786f86Andreas Huber * that can be found in the LICENSE file in the root of the source 6f71323e297a928af368937089d3ed71239786f86Andreas Huber * tree. An additional intellectual property rights grant can be found 7f71323e297a928af368937089d3ed71239786f86Andreas Huber * in the file PATENTS. All contributing project authors may 8f71323e297a928af368937089d3ed71239786f86Andreas Huber * be found in the AUTHORS file in the root of the source tree. 990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber */ 1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 1190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 1290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <float.h> 1390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <math.h> 1490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdio.h> 1590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "vpx_mem/vpx_mem.h" 1690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "vpxscale_arbitrary.h" 1790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 1890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define FIXED_POINT 1990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 2090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define MAX_IN_WIDTH 800 2190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define MAX_IN_HEIGHT 600 2290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define MAX_OUT_WIDTH 800 2390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define MAX_OUT_HEIGHT 600 2490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define MAX_OUT_DIMENSION ((MAX_OUT_WIDTH > MAX_OUT_HEIGHT) ? \ 2590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber MAX_OUT_WIDTH : MAX_OUT_HEIGHT) 2690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 2790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberBICUBIC_SCALER_STRUCT g_b_scaler; 2890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic int g_first_time = 1; 2990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#pragma DATA_SECTION(g_hbuf, "VP6_HEAP") 3190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#pragma DATA_ALIGN (g_hbuf, 32); 3290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberunsigned char g_hbuf[MAX_OUT_DIMENSION]; 3390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#pragma DATA_SECTION(g_hbuf_uv, "VP6_HEAP") 3590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#pragma DATA_ALIGN (g_hbuf_uv, 32); 3690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberunsigned char g_hbuf_uv[MAX_OUT_DIMENSION]; 3790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef FIXED_POINT 4090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic int a_i = 0.6 * 65536; 4190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else 4290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic float a = -0.6; 4390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 4490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 4590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef FIXED_POINT 4690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 3 2 4790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C0 = a*t - a*t 4890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 49f71323e297a928af368937089d3ed71239786f86Andreas Huberstatic short c0_fixed(unsigned int t) 5090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 5190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // put t in Q16 notation 5290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned short v1, v2; 5390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q16 5590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v1 = (a_i * t) >> 16; 5690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v1 = (v1 * t) >> 16; 5790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q16 5990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (a_i * t) >> 16; 6090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 6190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 6290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 6390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q12 6490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return -((v1 - v2) >> 4); 6590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 6690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 6790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 2 3 6890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C1 = a*t + (3-2*a)*t - (2-a)*t 6990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 70f71323e297a928af368937089d3ed71239786f86Andreas Huberstatic short c1_fixed(unsigned int t) 7190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 7290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned short v1, v2, v3; 7390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned short two, three; 7490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 7590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q16 7690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v1 = (a_i * t) >> 16; 7790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 7890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q13 7990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber two = 2 << 13; 8090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = two - (a_i >> 3); 8190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 8290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 8390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 8490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 8590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q13 8690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber three = 3 << 13; 8790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = three - (2 * (a_i >> 3)); 8890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 8990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 9090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q12 9290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return (((v1 >> 3) - v2 + v3) >> 1); 9390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 9590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 2 3 9790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C2 = 1 - (3-a)*t + (2-a)*t 9890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 99f71323e297a928af368937089d3ed71239786f86Andreas Huberstatic short c2_fixed(unsigned int t) 10090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 10190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned short v1, v2, v3; 10290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned short two, three; 10390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 10490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q13 10590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v1 = 1 << 13; 10690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 10790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q13 10890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber three = 3 << 13; 10990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = three - (a_i >> 3); 11090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 11190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 11290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 11390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q13 11490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber two = 2 << 13; 11590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = two - (a_i >> 3); 11690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 11790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 11890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 11990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 12090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q12 12190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return (v1 - v2 + v3) >> 1; 12290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 12390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 12490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 2 3 12590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C3 = a*t - 2*a*t + a*t 12690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 127f71323e297a928af368937089d3ed71239786f86Andreas Huberstatic short c3_fixed(unsigned int t) 12890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 12990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int v1, v2, v3; 13090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 13190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q16 13290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v1 = (a_i * t) >> 16; 13390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 13490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q15 13590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = 2 * (a_i >> 1); 13690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 13790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v2 = (v2 * t) >> 16; 13890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 13990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q16 14090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (a_i * t) >> 16; 14190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 14290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber v3 = (v3 * t) >> 16; 14390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 14490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Q12 14590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return ((v2 - (v1 >> 1) - (v3 >> 1)) >> 3); 14690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 14790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else 14890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 3 2 14990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C0 = -a*t + a*t 15090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 15190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfloat C0(float t) 15290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 15390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return -a * t * t * t + a * t * t; 15490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 15590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 15690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 2 3 15790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C1 = -a*t + (2*a+3)*t - (a+2)*t 15890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 15990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfloat C1(float t) 16090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 16190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return -(a + 2.0f) * t * t * t + (2.0f * a + 3.0f) * t * t - a * t; 16290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 16390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 16490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 2 3 16590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C2 = 1 - (a+3)*t + (a+2)*t 16690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 16790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfloat C2(float t) 16890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 16990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return (a + 2.0f) * t * t * t - (a + 3.0f) * t * t + 1.0f; 17090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 17190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 17290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 2 3 17390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// C3 = a*t - 2*a*t + a*t 17490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 17590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfloat C3(float t) 17690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 17790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return a * t * t * t - 2.0f * a * t * t + a * t; 17890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 17990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 18090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 18190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if 0 18290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint compare_real_fixed() 18390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 18490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int i, errors = 0; 18590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber float mult = 1.0 / 10000.0; 18690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned int fixed_mult = mult * 4294967296;//65536; 18790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned int phase_offset_int; 18890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber float phase_offset_real; 18990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 19090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < 10000; i++) 19190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 19290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int fixed0, fixed1, fixed2, fixed3, fixed_total; 19390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int real0, real1, real2, real3, real_total; 19490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 19590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_real = (float)i * mult; 19690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_int = (fixed_mult * i) >> 16; 19790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// phase_offset_int = phase_offset_real * 65536; 19890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 19990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed0 = c0_fixed(phase_offset_int); 20090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber real0 = C0(phase_offset_real) * 4096.0; 20190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 20290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((abs(fixed0) > (abs(real0) + 1)) || (abs(fixed0) < (abs(real0) - 1))) 20390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber errors++; 20490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 20590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed1 = c1_fixed(phase_offset_int); 20690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber real1 = C1(phase_offset_real) * 4096.0; 20790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 20890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((abs(fixed1) > (abs(real1) + 1)) || (abs(fixed1) < (abs(real1) - 1))) 20990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber errors++; 21090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 21190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed2 = c2_fixed(phase_offset_int); 21290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber real2 = C2(phase_offset_real) * 4096.0; 21390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 21490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((abs(fixed2) > (abs(real2) + 1)) || (abs(fixed2) < (abs(real2) - 1))) 21590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber errors++; 21690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 21790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed3 = c3_fixed(phase_offset_int); 21890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber real3 = C3(phase_offset_real) * 4096.0; 21990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 22090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((abs(fixed3) > (abs(real3) + 1)) || (abs(fixed3) < (abs(real3) - 1))) 22190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber errors++; 22290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 22390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed_total = fixed0 + fixed1 + fixed2 + fixed3; 22490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber real_total = real0 + real1 + real2 + real3; 22590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 22690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((fixed_total > 4097) || (fixed_total < 4094)) 22790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber errors ++; 22890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 22990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((real_total > 4097) || (real_total < 4095)) 23090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber errors ++; 23190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 23290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 23390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return errors; 23490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 23590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 23690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 23790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// Find greatest common denominator between two integers. Method used here is 23890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// slow compared to Euclid's algorithm, but does not require any division. 23990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint gcd(int a, int b) 24090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 24190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Problem with this algorithm is that if a or b = 0 this function 24290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // will never exit. Don't want to return 0 because any computation 24390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // that was based on a common denoninator and tried to reduce by 24490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // dividing by 0 would fail. Best solution that could be thought of 24590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // would to be fail by returing a 1; 24690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (a <= 0 || b <= 0) 24790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return 1; 24890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 24990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber while (a != b) 25090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 25190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (b > a) 25290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber b = b - a; 25390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber else 25490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 25590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int tmp = a;//swap large and 25690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber a = b; //small 25790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber b = tmp; 25890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 25990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 26090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 26190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return b; 26290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 26390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 26490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervoid bicubic_coefficient_init() 26590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 26690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_memset(&g_b_scaler, 0, sizeof(BICUBIC_SCALER_STRUCT)); 26790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_first_time = 0; 26890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 26990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 27090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervoid bicubic_coefficient_destroy() 27190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 27290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (!g_first_time) 27390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 27479f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.l_w); 27590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 27679f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.l_h); 27790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 27879f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.l_h_uv); 27990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 28079f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.c_w); 28190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 28279f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.c_h); 28390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 28479f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.c_h_uv); 28590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 28690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber vpx_memset(&g_b_scaler, 0, sizeof(BICUBIC_SCALER_STRUCT)); 28790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 28890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 28990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 29090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// Create the coeffients that will be used for the cubic interpolation. 29190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// Because scaling does not have to be equal in the vertical and horizontal 29290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// regimes the phase offsets will be different. There are 4 coefficents 29390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// for each point, two on each side. The layout is that there are the 29490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// 4 coefficents for each phase in the array and then the next phase. 29590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint bicubic_coefficient_setup(int in_width, int in_height, int out_width, int out_height) 29690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 29790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int i; 29890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef FIXED_POINT 29990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int phase_offset_int; 30090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned int fixed_mult; 30190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int product_val = 0; 30290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else 30390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber float phase_offset; 30490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 30590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int gcd_w, gcd_h, gcd_h_uv, d_w, d_h, d_h_uv; 30690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 30790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (g_first_time) 30890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber bicubic_coefficient_init(); 30990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 31090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 31190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // check to see if the coefficents have already been set up correctly 31290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((in_width == g_b_scaler.in_width) && (in_height == g_b_scaler.in_height) 31390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber && (out_width == g_b_scaler.out_width) && (out_height == g_b_scaler.out_height)) 31490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return 0; 31590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 31690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.in_width = in_width; 31790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.in_height = in_height; 31890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.out_width = out_width; 31990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.out_height = out_height; 32090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 32190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Don't want to allow crazy scaling, just try and prevent a catastrophic 32290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // failure here. Want to fail after setting the member functions so if 32390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // if the scaler is called the member functions will not scale. 32490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (out_width <= 0 || out_height <= 0) 32590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return -1; 32690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 32790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // reduce in/out width and height ratios using the gcd 32890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber gcd_w = gcd(out_width, in_width); 32990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber gcd_h = gcd(out_height, in_height); 33090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber gcd_h_uv = gcd(out_height, in_height / 2); 33190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 33290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // the numerator width and height are to be saved in 33390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // globals so they can be used during the scaling process 33490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // without having to be recalculated. 33590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.nw = out_width / gcd_w; 33690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber d_w = in_width / gcd_w; 33790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 33890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.nh = out_height / gcd_h; 33990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber d_h = in_height / gcd_h; 34090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 34190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.nh_uv = out_height / gcd_h_uv; 34290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber d_h_uv = (in_height / 2) / gcd_h_uv; 34390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 34490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // allocate memory for the coefficents 34579f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.l_w); 34690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 34779f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.l_h); 34890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 34979f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.l_h_uv); 35090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 35190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.l_w = (short *)vpx_memalign(32, out_width * 2); 35290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.l_h = (short *)vpx_memalign(32, out_height * 2); 35390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.l_h_uv = (short *)vpx_memalign(32, out_height * 2); 35490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 35579f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.c_w); 35690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 35779f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.c_h); 35890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 35979f15823c34ae1e423108295e416213200bb280fAndreas Huber vpx_free(g_b_scaler.c_h_uv); 36090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 36190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_w = (short *)vpx_memalign(32, g_b_scaler.nw * 4 * 2); 36290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h = (short *)vpx_memalign(32, g_b_scaler.nh * 4 * 2); 36390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h_uv = (short *)vpx_memalign(32, g_b_scaler.nh_uv * 4 * 2); 36490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 36590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.hbuf = g_hbuf; 36690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.hbuf_uv = g_hbuf_uv; 36790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 36890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Set up polyphase filter taps. This needs to be done before 36990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // the scaling because of the floating point math required. The 37090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // coefficients are multiplied by 2^12 so that fixed point math 37190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // can be used in the main scaling loop. 37290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef FIXED_POINT 37390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed_mult = (1.0 / (float)g_b_scaler.nw) * 4294967296; 37490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 37590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val = 0; 37690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 37790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < g_b_scaler.nw; i++) 37890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 37990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (product_val > g_b_scaler.nw) 38090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val -= g_b_scaler.nw; 38190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 38290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_int = (fixed_mult * product_val) >> 16; 38390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 38490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_w[i*4] = c3_fixed(phase_offset_int); 38590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_w[i*4+1] = c2_fixed(phase_offset_int); 38690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_w[i*4+2] = c1_fixed(phase_offset_int); 38790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_w[i*4+3] = c0_fixed(phase_offset_int); 38890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 38990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val += d_w; 39090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 39190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 39290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 39390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed_mult = (1.0 / (float)g_b_scaler.nh) * 4294967296; 39490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 39590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val = 0; 39690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 39790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < g_b_scaler.nh; i++) 39890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 39990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (product_val > g_b_scaler.nh) 40090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val -= g_b_scaler.nh; 40190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 40290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_int = (fixed_mult * product_val) >> 16; 40390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 40490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h[i*4] = c0_fixed(phase_offset_int); 40590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h[i*4+1] = c1_fixed(phase_offset_int); 40690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h[i*4+2] = c2_fixed(phase_offset_int); 40790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h[i*4+3] = c3_fixed(phase_offset_int); 40890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 40990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val += d_h; 41090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 41190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 41290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fixed_mult = (1.0 / (float)g_b_scaler.nh_uv) * 4294967296; 41390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 41490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val = 0; 41590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 41690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < g_b_scaler.nh_uv; i++) 41790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 41890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (product_val > g_b_scaler.nh_uv) 41990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val -= g_b_scaler.nh_uv; 42090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 42190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_int = (fixed_mult * product_val) >> 16; 42290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 42390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h_uv[i*4] = c0_fixed(phase_offset_int); 42490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h_uv[i*4+1] = c1_fixed(phase_offset_int); 42590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h_uv[i*4+2] = c2_fixed(phase_offset_int); 42690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.c_h_uv[i*4+3] = c3_fixed(phase_offset_int); 42790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 42890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber product_val += d_h_uv; 42990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 43090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 43190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else 43290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 43390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < g_nw; i++) 43490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 43590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset = (float)((i * d_w) % g_nw) / (float)g_nw; 43690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_w[i*4] = (C3(phase_offset) * 4096.0); 43790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_w[i*4+1] = (C2(phase_offset) * 4096.0); 43890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_w[i*4+2] = (C1(phase_offset) * 4096.0); 43990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_w[i*4+3] = (C0(phase_offset) * 4096.0); 44090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 44190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 44290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < g_nh; i++) 44390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 44490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset = (float)((i * d_h) % g_nh) / (float)g_nh; 44590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h[i*4] = (C0(phase_offset) * 4096.0); 44690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h[i*4+1] = (C1(phase_offset) * 4096.0); 44790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h[i*4+2] = (C2(phase_offset) * 4096.0); 44890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h[i*4+3] = (C3(phase_offset) * 4096.0); 44990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 45090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 45190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < g_nh_uv; i++) 45290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 45390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset = (float)((i * d_h_uv) % g_nh_uv) / (float)g_nh_uv; 45490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h_uv[i*4] = (C0(phase_offset) * 4096.0); 45590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h_uv[i*4+1] = (C1(phase_offset) * 4096.0); 45690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h_uv[i*4+2] = (C2(phase_offset) * 4096.0); 45790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_c_h_uv[i*4+3] = (C3(phase_offset) * 4096.0); 45890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 45990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 46090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 46190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 46290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Create an array that corresponds input lines to output lines. 46390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // This doesn't require floating point math, but it does require 46490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // a division and because hardware division is not present that 46590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // is a call. 46690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < out_width; i++) 46790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 46890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.l_w[i] = (i * d_w) / g_b_scaler.nw; 46990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 47090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((g_b_scaler.l_w[i] + 2) <= in_width) 47190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.max_usable_out_width = i; 47290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 47390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 47490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 47590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (i = 0; i < out_height + 1; i++) 47690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 47790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.l_h[i] = (i * d_h) / g_b_scaler.nh; 47890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.l_h_uv[i] = (i * d_h_uv) / g_b_scaler.nh_uv; 47990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 48090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 48190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return 0; 48290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 48390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 48490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint bicubic_scale(int in_width, int in_height, int in_stride, 48590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int out_width, int out_height, int out_stride, 48690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned char *input_image, unsigned char *output_image) 48790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 48890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber short *RESTRICT l_w, * RESTRICT l_h; 48990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber short *RESTRICT c_w, * RESTRICT c_h; 49090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned char *RESTRICT ip, * RESTRICT op; 49190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber unsigned char *RESTRICT hbuf; 49290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int h, w, lw, lh; 49390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int temp_sum; 49490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int phase_offset_w, phase_offset_h; 49590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 49690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber c_w = g_b_scaler.c_w; 49790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber c_h = g_b_scaler.c_h; 49890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 49990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber op = output_image; 50090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 50190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber l_w = g_b_scaler.l_w; 50290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber l_h = g_b_scaler.l_h; 50390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 50490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_h = 0; 50590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 50690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (h = 0; h < out_height; h++) 50790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 50890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // select the row to work on 50990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber lh = l_h[h]; 51090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ip = input_image + (in_stride * lh); 51190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 51290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // vp8_filter the row vertically into an temporary buffer. 51390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // If the phase offset == 0 then all the multiplication 51490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // is going to result in the output equalling the input. 51590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // So instead point the temporary buffer to the input. 51690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // Also handle the boundry condition of not being able to 51790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // filter that last lines. 51890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (phase_offset_h && (lh < in_height - 2)) 51990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 52090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber hbuf = g_b_scaler.hbuf; 52190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 52290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (w = 0; w < in_width; w++) 52390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 52490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum = c_h[phase_offset_h*4+3] * ip[w - in_stride]; 52590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum += c_h[phase_offset_h*4+2] * ip[w]; 52690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum += c_h[phase_offset_h*4+1] * ip[w + in_stride]; 52790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum += c_h[phase_offset_h*4] * ip[w + 2*in_stride]; 52890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 52990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber hbuf[w] = temp_sum >> 12; 53090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 53190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 53290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber else 53390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber hbuf = ip; 53490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 53590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // increase the phase offset for the next time around. 53690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (++phase_offset_h >= g_b_scaler.nh) 53790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_h = 0; 53890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 53990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // now filter and expand it horizontally into the final 54090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // output buffer 54190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_w = 0; 54290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 54390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber for (w = 0; w < out_width; w++) 54490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber { 54590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // get the index to use to expand the image 54690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber lw = l_w[w]; 54790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 54890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum = c_w[phase_offset_w*4] * hbuf[lw - 1]; 54990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum += c_w[phase_offset_w*4+1] * hbuf[lw]; 55090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum += c_w[phase_offset_w*4+2] * hbuf[lw + 1]; 55190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum += c_w[phase_offset_w*4+3] * hbuf[lw + 2]; 55290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum = temp_sum >> 12; 55390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 55490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (++phase_offset_w >= g_b_scaler.nw) 55590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber phase_offset_w = 0; 55690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 55790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber // boundry conditions 55890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if ((lw + 2) >= in_width) 55990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum = hbuf[lw]; 56090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 56190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (lw == 0) 56290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber temp_sum = hbuf[0]; 56390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 56490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber op[w] = temp_sum; 56590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 56690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 56790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber op += out_stride; 56890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 56990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 57090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return 0; 57190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 57290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 57390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervoid bicubic_scale_frame_reset() 57490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 57590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.out_width = 0; 57690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber g_b_scaler.out_height = 0; 57790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 57890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 57990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervoid bicubic_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, 58090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int new_width, int new_height) 58190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 58290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 58390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dst->y_width = new_width; 58490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dst->y_height = new_height; 58590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dst->uv_width = new_width / 2; 58690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dst->uv_height = new_height / 2; 58790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 58890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dst->y_stride = dst->y_width; 58990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dst->uv_stride = dst->uv_width; 59090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 59190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber bicubic_scale(src->y_width, src->y_height, src->y_stride, 59290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber new_width, new_height, dst->y_stride, 59390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber src->y_buffer, dst->y_buffer); 59490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 59590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber bicubic_scale(src->uv_width, src->uv_height, src->uv_stride, 59690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber new_width / 2, new_height / 2, dst->uv_stride, 59790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber src->u_buffer, dst->u_buffer); 59890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 59990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber bicubic_scale(src->uv_width, src->uv_height, src->uv_stride, 60090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber new_width / 2, new_height / 2, dst->uv_stride, 60190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber src->v_buffer, dst->v_buffer); 60290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 603