153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org/* 253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * Copyright (c) 2013 The WebM project authors. All Rights Reserved. 353a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * 453a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * Use of this source code is governed by a BSD-style license 553a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * that can be found in the LICENSE file in the root of the source 653a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * tree. An additional intellectual property rights grant can be found 753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * in the file PATENTS. All contributing project authors may 853a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org * be found in the AUTHORS file in the root of the source tree. 953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org */ 1053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 1153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org#include "./vp9_rtcd.h" 1253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org#include "vp9/common/vp9_filter.h" 1353a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org#include "vp9/common/vp9_scale.h" 1453a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 150e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.orgstatic INLINE int scaled_x(int val, const struct scale_factors *sf) { 1693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org return (int)((int64_t)val * sf->x_scale_fp >> REF_SCALE_SHIFT); 1753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org} 1853a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 190e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.orgstatic INLINE int scaled_y(int val, const struct scale_factors *sf) { 2093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org return (int)((int64_t)val * sf->y_scale_fp >> REF_SCALE_SHIFT); 2153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org} 2253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 230e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.orgstatic int unscaled_value(int val, const struct scale_factors *sf) { 240e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org (void) sf; 2553a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org return val; 2653a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org} 2753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 2853a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.orgstatic int get_fixed_point_scale_factor(int other_size, int this_size) { 2953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // Calculate scaling factor once for each reference frame 3053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // and use fixed point scaling factors in decoding and encoding routines. 3153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // Hardware implementations can calculate scale factor in device driver 3253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // and use multiplication and shifting on hardware instead of division. 3353a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org return (other_size << REF_SCALE_SHIFT) / this_size; 3453a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org} 3553a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 3653a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.orgstatic int check_scale_factors(int other_w, int other_h, 3753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org int this_w, int this_h) { 3853a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org return 2 * this_w >= other_w && 3953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 2 * this_h >= other_h && 4053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org this_w <= 16 * other_w && 4153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org this_h <= 16 * other_h; 4253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org} 4353a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 440e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.orgMV32 vp9_scale_mv(const MV *mv, int x, int y, const struct scale_factors *sf) { 450e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org const int x_off_q4 = scaled_x(x << SUBPEL_BITS, sf) & SUBPEL_MASK; 460e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org const int y_off_q4 = scaled_y(y << SUBPEL_BITS, sf) & SUBPEL_MASK; 470e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org const MV32 res = { 480e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org scaled_y(mv->row, sf) + y_off_q4, 490e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org scaled_x(mv->col, sf) + x_off_q4 500e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org }; 510e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org return res; 520e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org} 530e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org 540e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.orgvoid vp9_setup_scale_factors_for_frame(struct scale_factors *sf, 5553a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org int other_w, int other_h, 5653a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org int this_w, int this_h) { 5753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org if (!check_scale_factors(other_w, other_h, this_w, this_h)) { 580e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->x_scale_fp = REF_INVALID_SCALE; 590e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->y_scale_fp = REF_INVALID_SCALE; 6053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org return; 6153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } 6253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 630e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w); 640e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h); 650e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->x_step_q4 = scaled_x(16, sf); 660e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->y_step_q4 = scaled_y(16, sf); 6753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 680e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org if (vp9_is_scaled(sf)) { 690e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->scale_value_x = scaled_x; 700e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->scale_value_y = scaled_y; 7153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } else { 720e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->scale_value_x = unscaled_value; 730e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->scale_value_y = unscaled_value; 7453a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } 7553a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org 7653a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // TODO(agrange): Investigate the best choice of functions to use here 7753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // for EIGHTTAP_SMOOTH. Since it is not interpolating, need to choose what 7853a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // to do at full-pel offsets. The current selection, where the filter is 7953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // applied in one direction only, and not at all for 0,0, seems to give the 8053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // best quality, but it may be worth trying an additional mode that does 8153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // do the filtering on full-pel. 820e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org if (sf->x_step_q4 == 16) { 830e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org if (sf->y_step_q4 == 16) { 8453a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // No scaling in either direction. 850e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][0] = vp9_convolve_copy; 860e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][1] = vp9_convolve_avg; 870e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][0] = vp9_convolve8_vert; 880e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][1] = vp9_convolve8_avg_vert; 890e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][0] = vp9_convolve8_horiz; 900e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][1] = vp9_convolve8_avg_horiz; 9153a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } else { 9253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // No scaling in x direction. Must always scale in the y direction. 930e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][0] = vp9_convolve8_vert; 940e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][1] = vp9_convolve8_avg_vert; 950e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][0] = vp9_convolve8_vert; 960e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][1] = vp9_convolve8_avg_vert; 970e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][0] = vp9_convolve8; 980e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][1] = vp9_convolve8_avg; 9953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } 10053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } else { 1010e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org if (sf->y_step_q4 == 16) { 10253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // No scaling in the y direction. Must always scale in the x direction. 1030e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][0] = vp9_convolve8_horiz; 1040e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][1] = vp9_convolve8_avg_horiz; 1050e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][0] = vp9_convolve8; 1060e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][1] = vp9_convolve8_avg; 1070e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][0] = vp9_convolve8_horiz; 1080e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][1] = vp9_convolve8_avg_horiz; 10953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } else { 11053a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // Must always scale in both directions. 1110e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][0] = vp9_convolve8; 1120e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][0][1] = vp9_convolve8_avg; 1130e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][0] = vp9_convolve8; 1140e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[0][1][1] = vp9_convolve8_avg; 1150e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][0] = vp9_convolve8; 1160e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][0][1] = vp9_convolve8_avg; 11753a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } 11853a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org } 11953a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org // 2D subpel motion always gets filtered in both directions 1200e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][1][0] = vp9_convolve8; 1210e29f91ae7876791fc422e9c7cea72b1866439a6johannkoenig@chromium.org sf->predict[1][1][1] = vp9_convolve8_avg; 12253a13f1fa964820f7a8f9d3932a6f3c0433f8bf5fgalligan@chromium.org} 123