media/libvpx/vp9/common/vp9_scale.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
     3  *
     4  *  Use of this source code is governed by a BSD-style license
     5  *  that can be found in the LICENSE file in the root of the source
     6  *  tree. An additional intellectual property rights grant can be found
     7  *  in the file PATENTS.  All contributing project authors may
     8  *  be found in the AUTHORS file in the root of the source tree.
     9  */
    11 #include "./vp9_rtcd.h"
    12 #include "vp9/common/vp9_filter.h"
    13 #include "vp9/common/vp9_scale.h"
    15 static INLINE int scaled_x(int val, const struct scale_factors_common *sfc) {
    16   return val * sfc->x_scale_fp >> REF_SCALE_SHIFT;
    17 }
    19 static INLINE int scaled_y(int val, const struct scale_factors_common *sfc) {
    20   return val * sfc->y_scale_fp >> REF_SCALE_SHIFT;
    21 }
    23 static int unscaled_value(int val, const struct scale_factors_common *sfc) {
    24   (void) sfc;
    25   return val;
    26 }
    28 static MV32 scaled_mv(const MV *mv, const struct scale_factors *scale) {
    29   const MV32 res = {
    30     scaled_y(mv->row, scale->sfc) + scale->y_offset_q4,
    31     scaled_x(mv->col, scale->sfc) + scale->x_offset_q4
    32   };
    33   return res;
    34 }
    36 static MV32 unscaled_mv(const MV *mv, const struct scale_factors *scale) {
    37   const MV32 res = {
    38     mv->row,
    39     mv->col
    40   };
    41   return res;
    42 }
    44 static void set_offsets_with_scaling(struct scale_factors *scale,
    45                                      int row, int col) {
    46   scale->x_offset_q4 = scaled_x(col << SUBPEL_BITS, scale->sfc) & SUBPEL_MASK;
    47   scale->y_offset_q4 = scaled_y(row << SUBPEL_BITS, scale->sfc) & SUBPEL_MASK;
    48 }
    50 static void set_offsets_without_scaling(struct scale_factors *scale,
    51                                         int row, int col) {
    52   scale->x_offset_q4 = 0;
    53   scale->y_offset_q4 = 0;
    54 }
    56 static int get_fixed_point_scale_factor(int other_size, int this_size) {
    57   // Calculate scaling factor once for each reference frame
    58   // and use fixed point scaling factors in decoding and encoding routines.
    59   // Hardware implementations can calculate scale factor in device driver
    60   // and use multiplication and shifting on hardware instead of division.
    61   return (other_size << REF_SCALE_SHIFT) / this_size;
    62 }
    64 static int check_scale_factors(int other_w, int other_h,
    65                                int this_w, int this_h) {
    66   return 2 * this_w >= other_w &&
    67          2 * this_h >= other_h &&
    68          this_w <= 16 * other_w &&
    69          this_h <= 16 * other_h;
    70 }
    72 void vp9_setup_scale_factors_for_frame(struct scale_factors *scale,
    73                                        struct scale_factors_common *scale_comm,
    74                                        int other_w, int other_h,
    75                                        int this_w, int this_h) {
    76   if (!check_scale_factors(other_w, other_h, this_w, this_h)) {
    77     scale_comm->x_scale_fp = REF_INVALID_SCALE;
    78     scale_comm->y_scale_fp = REF_INVALID_SCALE;
    79     return;
    80   }
    82   scale_comm->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
    83   scale_comm->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);
    84   scale_comm->x_step_q4 = scaled_x(16, scale_comm);
    85   scale_comm->y_step_q4 = scaled_y(16, scale_comm);
    87   if (vp9_is_scaled(scale_comm)) {
    88     scale_comm->scale_value_x = scaled_x;
    89     scale_comm->scale_value_y = scaled_y;
    90     scale_comm->set_scaled_offsets = set_offsets_with_scaling;
    91     scale_comm->scale_mv = scaled_mv;
    92   } else {
    93     scale_comm->scale_value_x = unscaled_value;
    94     scale_comm->scale_value_y = unscaled_value;
    95     scale_comm->set_scaled_offsets = set_offsets_without_scaling;
    96     scale_comm->scale_mv = unscaled_mv;
    97   }
    99   // TODO(agrange): Investigate the best choice of functions to use here
   100   // for EIGHTTAP_SMOOTH. Since it is not interpolating, need to choose what
   101   // to do at full-pel offsets. The current selection, where the filter is
   102   // applied in one direction only, and not at all for 0,0, seems to give the
   103   // best quality, but it may be worth trying an additional mode that does
   104   // do the filtering on full-pel.
   105   if (scale_comm->x_step_q4 == 16) {
   106     if (scale_comm->y_step_q4 == 16) {
   107       // No scaling in either direction.
   108       scale_comm->predict[0][0][0] = vp9_convolve_copy;
   109       scale_comm->predict[0][0][1] = vp9_convolve_avg;
   110       scale_comm->predict[0][1][0] = vp9_convolve8_vert;
   111       scale_comm->predict[0][1][1] = vp9_convolve8_avg_vert;
   112       scale_comm->predict[1][0][0] = vp9_convolve8_horiz;
   113       scale_comm->predict[1][0][1] = vp9_convolve8_avg_horiz;
   114     } else {
   115       // No scaling in x direction. Must always scale in the y direction.
   116       scale_comm->predict[0][0][0] = vp9_convolve8_vert;
   117       scale_comm->predict[0][0][1] = vp9_convolve8_avg_vert;
   118       scale_comm->predict[0][1][0] = vp9_convolve8_vert;
   119       scale_comm->predict[0][1][1] = vp9_convolve8_avg_vert;
   120       scale_comm->predict[1][0][0] = vp9_convolve8;
   121       scale_comm->predict[1][0][1] = vp9_convolve8_avg;
   122     }
   123   } else {
   124     if (scale_comm->y_step_q4 == 16) {
   125       // No scaling in the y direction. Must always scale in the x direction.
   126       scale_comm->predict[0][0][0] = vp9_convolve8_horiz;
   127       scale_comm->predict[0][0][1] = vp9_convolve8_avg_horiz;
   128       scale_comm->predict[0][1][0] = vp9_convolve8;
   129       scale_comm->predict[0][1][1] = vp9_convolve8_avg;
   130       scale_comm->predict[1][0][0] = vp9_convolve8_horiz;
   131       scale_comm->predict[1][0][1] = vp9_convolve8_avg_horiz;
   132     } else {
   133       // Must always scale in both directions.
   134       scale_comm->predict[0][0][0] = vp9_convolve8;
   135       scale_comm->predict[0][0][1] = vp9_convolve8_avg;
   136       scale_comm->predict[0][1][0] = vp9_convolve8;
   137       scale_comm->predict[0][1][1] = vp9_convolve8_avg;
   138       scale_comm->predict[1][0][0] = vp9_convolve8;
   139       scale_comm->predict[1][0][1] = vp9_convolve8_avg;
   140     }
   141   }
   142   // 2D subpel motion always gets filtered in both directions
   143   scale_comm->predict[1][1][0] = vp9_convolve8;
   144   scale_comm->predict[1][1][1] = vp9_convolve8_avg;
   146   scale->sfc = scale_comm;
   147   scale->x_offset_q4 = 0;  // calculated per block
   148   scale->y_offset_q4 = 0;  // calculated per block
   149 }

mercurial