tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

disflow.c (32548B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 // Dense Inverse Search flow algorithm
     13 // Paper: https://arxiv.org/abs/1603.03590
     14 
     15 #include <assert.h>
     16 #include <math.h>
     17 
     18 #include "aom_dsp/aom_dsp_common.h"
     19 #include "aom_dsp/flow_estimation/corner_detect.h"
     20 #include "aom_dsp/flow_estimation/disflow.h"
     21 #include "aom_dsp/flow_estimation/ransac.h"
     22 #include "aom_dsp/pyramid.h"
     23 #include "aom_mem/aom_mem.h"
     24 
     25 #include "config/aom_dsp_rtcd.h"
     26 
     27 // Amount to downsample the flow field by.
     28 // e.g., DOWNSAMPLE_SHIFT = 2 (DOWNSAMPLE_FACTOR == 4) means we calculate
     29 // one flow point for each 4x4 pixel region of the frame
     30 // Must be a power of 2
     31 #define DOWNSAMPLE_SHIFT 3
     32 #define DOWNSAMPLE_FACTOR (1 << DOWNSAMPLE_SHIFT)
     33 
     34 // Filters used when upscaling the flow field from one pyramid level
     35 // to another. See upscale_flow_component for details on kernel selection
     36 #define FLOW_UPSCALE_TAPS 4
     37 
     38 // Number of outermost flow field entries (on each edge) which can't be
     39 // computed, because the patch they correspond to extends outside of the
     40 // frame
     41 // The border is (DISFLOW_PATCH_SIZE >> 1) pixels, which is
     42 // (DISFLOW_PATCH_SIZE >> 1) >> DOWNSAMPLE_SHIFT many flow field entries
     43 #define FLOW_BORDER_INNER ((DISFLOW_PATCH_SIZE >> 1) >> DOWNSAMPLE_SHIFT)
     44 
     45 // Number of extra padding entries on each side of the flow field.
     46 // These samples are added so that we do not need to apply clamping when
     47 // interpolating or upsampling the flow field
     48 #define FLOW_BORDER_OUTER (FLOW_UPSCALE_TAPS / 2)
     49 
     50 // When downsampling the flow field, each flow field entry covers a square
     51 // region of pixels in the image pyramid. This value is equal to the position
     52 // of the center of that region, as an offset from the top/left edge.
     53 //
     54 // Note: Using ((DOWNSAMPLE_FACTOR - 1) / 2) is equivalent to the more
     55 // natural expression ((DOWNSAMPLE_FACTOR / 2) - 1),
     56 // unless DOWNSAMPLE_FACTOR == 1 (ie, no downsampling), in which case
     57 // this gives the correct offset of 0 instead of -1.
     58 #define UPSAMPLE_CENTER_OFFSET ((DOWNSAMPLE_FACTOR - 1) / 2)
     59 
     60 static double flow_upscale_filter[2][FLOW_UPSCALE_TAPS] = {
     61  // Cubic interpolation kernels for phase=0.75 and phase=0.25, respectively
     62  { -3 / 128., 29 / 128., 111 / 128., -9 / 128. },
     63  { -9 / 128., 111 / 128., 29 / 128., -3 / 128. }
     64 };
     65 
     66 static inline void get_cubic_kernel_dbl(double x, double kernel[4]) {
     67  // Check that the fractional position is in range.
     68  //
     69  // Note: x is calculated from, e.g., `u_frac = u - floor(u)`.
     70  // Mathematically, this implies that 0 <= x < 1. However, in practice it is
     71  // possible to have x == 1 due to floating point rounding. This is fine,
     72  // and we still interpolate correctly if we allow x = 1.
     73  assert(0 <= x && x <= 1);
     74 
     75  double x2 = x * x;
     76  double x3 = x2 * x;
     77  kernel[0] = -0.5 * x + x2 - 0.5 * x3;
     78  kernel[1] = 1.0 - 2.5 * x2 + 1.5 * x3;
     79  kernel[2] = 0.5 * x + 2.0 * x2 - 1.5 * x3;
     80  kernel[3] = -0.5 * x2 + 0.5 * x3;
     81 }
     82 
     83 static inline void get_cubic_kernel_int(double x, int kernel[4]) {
     84  double kernel_dbl[4];
     85  get_cubic_kernel_dbl(x, kernel_dbl);
     86 
     87  kernel[0] = (int)rint(kernel_dbl[0] * (1 << DISFLOW_INTERP_BITS));
     88  kernel[1] = (int)rint(kernel_dbl[1] * (1 << DISFLOW_INTERP_BITS));
     89  kernel[2] = (int)rint(kernel_dbl[2] * (1 << DISFLOW_INTERP_BITS));
     90  kernel[3] = (int)rint(kernel_dbl[3] * (1 << DISFLOW_INTERP_BITS));
     91 }
     92 
     93 static inline double get_cubic_value_dbl(const double *p,
     94                                         const double kernel[4]) {
     95  return kernel[0] * p[0] + kernel[1] * p[1] + kernel[2] * p[2] +
     96         kernel[3] * p[3];
     97 }
     98 
     99 static inline int get_cubic_value_int(const int *p, const int kernel[4]) {
    100  return kernel[0] * p[0] + kernel[1] * p[1] + kernel[2] * p[2] +
    101         kernel[3] * p[3];
    102 }
    103 
    104 static inline double bicubic_interp_one(const double *arr, int stride,
    105                                        const double h_kernel[4],
    106                                        const double v_kernel[4]) {
    107  double tmp[1 * 4];
    108 
    109  // Horizontal convolution
    110  for (int i = -1; i < 3; ++i) {
    111    tmp[i + 1] = get_cubic_value_dbl(&arr[i * stride - 1], h_kernel);
    112  }
    113 
    114  // Vertical convolution
    115  return get_cubic_value_dbl(tmp, v_kernel);
    116 }
    117 
    118 static int determine_disflow_correspondence(const ImagePyramid *src_pyr,
    119                                            const ImagePyramid *ref_pyr,
    120                                            CornerList *corners,
    121                                            const FlowField *flow,
    122                                            Correspondence *correspondences) {
    123  const int width = flow->width;
    124  const int height = flow->height;
    125  const int stride = flow->stride;
    126 
    127  int num_correspondences = 0;
    128  for (int i = 0; i < corners->num_corners; ++i) {
    129    const int x0 = corners->corners[2 * i];
    130    const int y0 = corners->corners[2 * i + 1];
    131 
    132    // Offset points, to compensate for the fact that (say) a flow field entry
    133    // at horizontal index i, is nominally associated with the pixel at
    134    // horizontal coordinate (i << DOWNSAMPLE_FACTOR) + UPSAMPLE_CENTER_OFFSET
    135    // This offset must be applied before we split the coordinate into integer
    136    // and fractional parts, in order for the interpolation to be correct.
    137    const int x = x0 - UPSAMPLE_CENTER_OFFSET;
    138    const int y = y0 - UPSAMPLE_CENTER_OFFSET;
    139 
    140    // Split the pixel coordinates into integer flow field coordinates and
    141    // an offset for interpolation
    142    const int flow_x = x >> DOWNSAMPLE_SHIFT;
    143    const double flow_sub_x =
    144        (x & (DOWNSAMPLE_FACTOR - 1)) / (double)DOWNSAMPLE_FACTOR;
    145    const int flow_y = y >> DOWNSAMPLE_SHIFT;
    146    const double flow_sub_y =
    147        (y & (DOWNSAMPLE_FACTOR - 1)) / (double)DOWNSAMPLE_FACTOR;
    148 
    149    // Exclude points which would sample from the outer border of the flow
    150    // field, as this would give lower-quality results.
    151    //
    152    // Note: As we never read from the border region at pyramid level 0, we
    153    // can skip filling it in. If the conditions here are removed, or any
    154    // other logic is added which reads from this border region, then
    155    // compute_flow_field() will need to be modified to call
    156    // fill_flow_field_borders() at pyramid level 0 to set up the correct
    157    // border data.
    158    if (flow_x < 1 || (flow_x + 2) >= width) continue;
    159    if (flow_y < 1 || (flow_y + 2) >= height) continue;
    160 
    161    double h_kernel[4];
    162    double v_kernel[4];
    163    get_cubic_kernel_dbl(flow_sub_x, h_kernel);
    164    get_cubic_kernel_dbl(flow_sub_y, v_kernel);
    165 
    166    double flow_u = bicubic_interp_one(&flow->u[flow_y * stride + flow_x],
    167                                       stride, h_kernel, v_kernel);
    168    double flow_v = bicubic_interp_one(&flow->v[flow_y * stride + flow_x],
    169                                       stride, h_kernel, v_kernel);
    170 
    171    // Refine the interpolated flow vector one last time
    172    const int patch_tl_x = x0 - DISFLOW_PATCH_CENTER;
    173    const int patch_tl_y = y0 - DISFLOW_PATCH_CENTER;
    174    aom_compute_flow_at_point(
    175        src_pyr->layers[0].buffer, ref_pyr->layers[0].buffer, patch_tl_x,
    176        patch_tl_y, src_pyr->layers[0].width, src_pyr->layers[0].height,
    177        src_pyr->layers[0].stride, &flow_u, &flow_v);
    178 
    179    // Use original points (without offsets) when filling in correspondence
    180    // array
    181    correspondences[num_correspondences].x = x0;
    182    correspondences[num_correspondences].y = y0;
    183    correspondences[num_correspondences].rx = x0 + flow_u;
    184    correspondences[num_correspondences].ry = y0 + flow_v;
    185    num_correspondences++;
    186  }
    187  return num_correspondences;
    188 }
    189 
    190 // Compare two regions of width x height pixels, one rooted at position
    191 // (x, y) in src and the other at (x + u, y + v) in ref.
    192 // This function returns the sum of squared pixel differences between
    193 // the two regions.
    194 static inline void compute_flow_vector(const uint8_t *src, const uint8_t *ref,
    195                                       int width, int height, int stride, int x,
    196                                       int y, double u, double v,
    197                                       const int16_t *dx, const int16_t *dy,
    198                                       int *b) {
    199  memset(b, 0, 2 * sizeof(*b));
    200 
    201  // Split offset into integer and fractional parts, and compute cubic
    202  // interpolation kernels
    203  const int u_int = (int)floor(u);
    204  const int v_int = (int)floor(v);
    205  const double u_frac = u - floor(u);
    206  const double v_frac = v - floor(v);
    207 
    208  int h_kernel[4];
    209  int v_kernel[4];
    210  get_cubic_kernel_int(u_frac, h_kernel);
    211  get_cubic_kernel_int(v_frac, v_kernel);
    212 
    213  // Storage for intermediate values between the two convolution directions
    214  int tmp_[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 3)];
    215  int *tmp = tmp_ + DISFLOW_PATCH_SIZE;  // Offset by one row
    216 
    217  // Clamp coordinates so that all pixels we fetch will remain within the
    218  // allocated border region, but allow them to go far enough out that
    219  // the border pixels' values do not change.
    220  // Since we are calculating an 8x8 block, the bottom-right pixel
    221  // in the block has coordinates (x0 + 7, y0 + 7). Then, the cubic
    222  // interpolation has 4 taps, meaning that the output of pixel
    223  // (x_w, y_w) depends on the pixels in the range
    224  // ([x_w - 1, x_w + 2], [y_w - 1, y_w + 2]).
    225  //
    226  // Thus the most extreme coordinates which will be fetched are
    227  // (x0 - 1, y0 - 1) and (x0 + 9, y0 + 9).
    228  const int x0 = clamp(x + u_int, -9, width);
    229  const int y0 = clamp(y + v_int, -9, height);
    230 
    231  // Horizontal convolution
    232  for (int i = -1; i < DISFLOW_PATCH_SIZE + 2; ++i) {
    233    const int y_w = y0 + i;
    234    for (int j = 0; j < DISFLOW_PATCH_SIZE; ++j) {
    235      const int x_w = x0 + j;
    236      int arr[4];
    237 
    238      arr[0] = (int)ref[y_w * stride + (x_w - 1)];
    239      arr[1] = (int)ref[y_w * stride + (x_w + 0)];
    240      arr[2] = (int)ref[y_w * stride + (x_w + 1)];
    241      arr[3] = (int)ref[y_w * stride + (x_w + 2)];
    242 
    243      // Apply kernel and round, keeping 6 extra bits of precision.
    244      //
    245      // 6 is the maximum allowable number of extra bits which will avoid
    246      // the intermediate values overflowing an int16_t. The most extreme
    247      // intermediate value occurs when:
    248      // * The input pixels are [0, 255, 255, 0]
    249      // * u_frac = 0.5
    250      // In this case, the un-scaled output is 255 * 1.125 = 286.875.
    251      // As an integer with 6 fractional bits, that is 18360, which fits
    252      // in an int16_t. But with 7 fractional bits it would be 36720,
    253      // which is too large.
    254      tmp[i * DISFLOW_PATCH_SIZE + j] = ROUND_POWER_OF_TWO(
    255          get_cubic_value_int(arr, h_kernel), DISFLOW_INTERP_BITS - 6);
    256    }
    257  }
    258 
    259  // Vertical convolution
    260  for (int i = 0; i < DISFLOW_PATCH_SIZE; ++i) {
    261    for (int j = 0; j < DISFLOW_PATCH_SIZE; ++j) {
    262      const int *p = &tmp[i * DISFLOW_PATCH_SIZE + j];
    263      const int arr[4] = { p[-DISFLOW_PATCH_SIZE], p[0], p[DISFLOW_PATCH_SIZE],
    264                           p[2 * DISFLOW_PATCH_SIZE] };
    265      const int result = get_cubic_value_int(arr, v_kernel);
    266 
    267      // Apply kernel and round.
    268      // This time, we have to round off the 6 extra bits which were kept
    269      // earlier, but we also want to keep DISFLOW_DERIV_SCALE_LOG2 extra bits
    270      // of precision to match the scale of the dx and dy arrays.
    271      const int round_bits = DISFLOW_INTERP_BITS + 6 - DISFLOW_DERIV_SCALE_LOG2;
    272      const int warped = ROUND_POWER_OF_TWO(result, round_bits);
    273      const int src_px = src[(x + j) + (y + i) * stride] << 3;
    274      const int dt = warped - src_px;
    275      b[0] += dx[i * DISFLOW_PATCH_SIZE + j] * dt;
    276      b[1] += dy[i * DISFLOW_PATCH_SIZE + j] * dt;
    277    }
    278  }
    279 }
    280 
    281 static inline void sobel_filter(const uint8_t *src, int src_stride,
    282                                int16_t *dst, int dst_stride, int dir) {
    283  int16_t tmp_[DISFLOW_PATCH_SIZE * (DISFLOW_PATCH_SIZE + 2)];
    284  int16_t *tmp = tmp_ + DISFLOW_PATCH_SIZE;
    285 
    286  // Sobel filter kernel
    287  // This must have an overall scale factor equal to DISFLOW_DERIV_SCALE,
    288  // in order to produce correctly scaled outputs.
    289  // To work out the scale factor, we multiply two factors:
    290  //
    291  // * For the derivative filter (sobel_a), comparing our filter
    292  //    image[x - 1] - image[x + 1]
    293  //   to the standard form
    294  //    d/dx image[x] = image[x+1] - image[x]
    295  //   tells us that we're actually calculating -2 * d/dx image[2]
    296  //
    297  // * For the smoothing filter (sobel_b), all coefficients are positive
    298  //   so the scale factor is just the sum of the coefficients
    299  //
    300  // Thus we need to make sure that DISFLOW_DERIV_SCALE = 2 * sum(sobel_b)
    301  // (and take care of the - sign from sobel_a elsewhere)
    302  static const int16_t sobel_a[3] = { 1, 0, -1 };
    303  static const int16_t sobel_b[3] = { 1, 2, 1 };
    304  const int taps = 3;
    305 
    306  // horizontal filter
    307  const int16_t *h_kernel = dir ? sobel_a : sobel_b;
    308 
    309  for (int y = -1; y < DISFLOW_PATCH_SIZE + 1; ++y) {
    310    for (int x = 0; x < DISFLOW_PATCH_SIZE; ++x) {
    311      int sum = 0;
    312      for (int k = 0; k < taps; ++k) {
    313        sum += h_kernel[k] * src[y * src_stride + (x + k - 1)];
    314      }
    315      tmp[y * DISFLOW_PATCH_SIZE + x] = sum;
    316    }
    317  }
    318 
    319  // vertical filter
    320  const int16_t *v_kernel = dir ? sobel_b : sobel_a;
    321 
    322  for (int y = 0; y < DISFLOW_PATCH_SIZE; ++y) {
    323    for (int x = 0; x < DISFLOW_PATCH_SIZE; ++x) {
    324      int sum = 0;
    325      for (int k = 0; k < taps; ++k) {
    326        sum += v_kernel[k] * tmp[(y + k - 1) * DISFLOW_PATCH_SIZE + x];
    327      }
    328      dst[y * dst_stride + x] = sum;
    329    }
    330  }
    331 }
    332 
    333 // Computes the components of the system of equations used to solve for
    334 // a flow vector.
    335 //
    336 // The flow equations are a least-squares system, derived as follows:
    337 //
    338 // For each pixel in the patch, we calculate the current error `dt`,
    339 // and the x and y gradients `dx` and `dy` of the source patch.
    340 // This means that, to first order, the squared error for this pixel is
    341 //
    342 //    (dt + u * dx + v * dy)^2
    343 //
    344 // where (u, v) are the incremental changes to the flow vector.
    345 //
    346 // We then want to find the values of u and v which minimize the sum
    347 // of the squared error across all pixels. Conveniently, this fits exactly
    348 // into the form of a least squares problem, with one equation
    349 //
    350 //   u * dx + v * dy = -dt
    351 //
    352 // for each pixel.
    353 //
    354 // Summing across all pixels in a square window of size DISFLOW_PATCH_SIZE,
    355 // and absorbing the - sign elsewhere, this results in the least squares system
    356 //
    357 //   M = |sum(dx * dx)  sum(dx * dy)|
    358 //       |sum(dx * dy)  sum(dy * dy)|
    359 //
    360 //   b = |sum(dx * dt)|
    361 //       |sum(dy * dt)|
    362 static inline void compute_flow_matrix(const int16_t *dx, int dx_stride,
    363                                       const int16_t *dy, int dy_stride,
    364                                       double *M) {
    365  int tmp[4] = { 0 };
    366 
    367  for (int i = 0; i < DISFLOW_PATCH_SIZE; i++) {
    368    for (int j = 0; j < DISFLOW_PATCH_SIZE; j++) {
    369      tmp[0] += dx[i * dx_stride + j] * dx[i * dx_stride + j];
    370      tmp[1] += dx[i * dx_stride + j] * dy[i * dy_stride + j];
    371      // Don't compute tmp[2], as it should be equal to tmp[1]
    372      tmp[3] += dy[i * dy_stride + j] * dy[i * dy_stride + j];
    373    }
    374  }
    375 
    376  // Apply regularization
    377  // We follow the standard regularization method of adding `k * I` before
    378  // inverting. This ensures that the matrix will be invertible.
    379  //
    380  // Setting the regularization strength k to 1 seems to work well here, as
    381  // typical values coming from the other equations are very large (1e5 to
    382  // 1e6, with an upper limit of around 6e7, at the time of writing).
    383  // It also preserves the property that all matrix values are whole numbers,
    384  // which is convenient for integerized SIMD implementation.
    385  tmp[0] += 1;
    386  tmp[3] += 1;
    387 
    388  tmp[2] = tmp[1];
    389 
    390  M[0] = (double)tmp[0];
    391  M[1] = (double)tmp[1];
    392  M[2] = (double)tmp[2];
    393  M[3] = (double)tmp[3];
    394 }
    395 
    396 // Try to invert the matrix M
    397 // Note: Due to the nature of how a least-squares matrix is constructed, all of
    398 // the eigenvalues will be >= 0, and therefore det M >= 0 as well.
    399 // The regularization term `+ k * I` further ensures that det M >= k^2.
    400 // As mentioned in compute_flow_matrix(), here we use k = 1, so det M >= 1.
    401 // So we don't have to worry about non-invertible matrices here.
    402 static inline void invert_2x2(const double *M, double *M_inv) {
    403  double det = (M[0] * M[3]) - (M[1] * M[2]);
    404  assert(det >= 1);
    405  const double det_inv = 1 / det;
    406 
    407  M_inv[0] = M[3] * det_inv;
    408  M_inv[1] = -M[1] * det_inv;
    409  M_inv[2] = -M[2] * det_inv;
    410  M_inv[3] = M[0] * det_inv;
    411 }
    412 
    413 void aom_compute_flow_at_point_c(const uint8_t *src, const uint8_t *ref, int x,
    414                                 int y, int width, int height, int stride,
    415                                 double *u, double *v) {
    416  double M[4];
    417  double M_inv[4];
    418  int b[2];
    419  int16_t dx[DISFLOW_PATCH_SIZE * DISFLOW_PATCH_SIZE];
    420  int16_t dy[DISFLOW_PATCH_SIZE * DISFLOW_PATCH_SIZE];
    421 
    422  // Compute gradients within this patch
    423  const uint8_t *src_patch = &src[y * stride + x];
    424  sobel_filter(src_patch, stride, dx, DISFLOW_PATCH_SIZE, 1);
    425  sobel_filter(src_patch, stride, dy, DISFLOW_PATCH_SIZE, 0);
    426 
    427  compute_flow_matrix(dx, DISFLOW_PATCH_SIZE, dy, DISFLOW_PATCH_SIZE, M);
    428  invert_2x2(M, M_inv);
    429 
    430  for (int itr = 0; itr < DISFLOW_MAX_ITR; itr++) {
    431    compute_flow_vector(src, ref, width, height, stride, x, y, *u, *v, dx, dy,
    432                        b);
    433 
    434    // Solve flow equations to find a better estimate for the flow vector
    435    // at this point
    436    const double step_u = M_inv[0] * b[0] + M_inv[1] * b[1];
    437    const double step_v = M_inv[2] * b[0] + M_inv[3] * b[1];
    438    *u += fclamp(step_u * DISFLOW_STEP_SIZE, -2, 2);
    439    *v += fclamp(step_v * DISFLOW_STEP_SIZE, -2, 2);
    440 
    441    if (fabs(step_u) + fabs(step_v) < DISFLOW_STEP_SIZE_THRESOLD) {
    442      // Stop iteration when we're close to convergence
    443      break;
    444    }
    445  }
    446 }
    447 
    448 static void fill_flow_field_borders(double *flow, int width, int height,
    449                                    int stride) {
    450  // Calculate the bounds of the rectangle which was filled in by
    451  // compute_flow_field() before calling this function.
    452  // These indices are inclusive on both ends.
    453  const int left_index = FLOW_BORDER_INNER;
    454  const int right_index = (width - FLOW_BORDER_INNER - 1);
    455  const int top_index = FLOW_BORDER_INNER;
    456  const int bottom_index = (height - FLOW_BORDER_INNER - 1);
    457 
    458  // Left area
    459  for (int i = top_index; i <= bottom_index; i += 1) {
    460    double *row = flow + i * stride;
    461    const double left = row[left_index];
    462    for (int j = -FLOW_BORDER_OUTER; j < left_index; j++) {
    463      row[j] = left;
    464    }
    465  }
    466 
    467  // Right area
    468  for (int i = top_index; i <= bottom_index; i += 1) {
    469    double *row = flow + i * stride;
    470    const double right = row[right_index];
    471    for (int j = right_index + 1; j < width + FLOW_BORDER_OUTER; j++) {
    472      row[j] = right;
    473    }
    474  }
    475 
    476  // Top area
    477  const double *top_row = flow + top_index * stride - FLOW_BORDER_OUTER;
    478  for (int i = -FLOW_BORDER_OUTER; i < top_index; i++) {
    479    double *row = flow + i * stride - FLOW_BORDER_OUTER;
    480    size_t length = width + 2 * FLOW_BORDER_OUTER;
    481    memcpy(row, top_row, length * sizeof(*row));
    482  }
    483 
    484  // Bottom area
    485  const double *bottom_row = flow + bottom_index * stride - FLOW_BORDER_OUTER;
    486  for (int i = bottom_index + 1; i < height + FLOW_BORDER_OUTER; i++) {
    487    double *row = flow + i * stride - FLOW_BORDER_OUTER;
    488    size_t length = width + 2 * FLOW_BORDER_OUTER;
    489    memcpy(row, bottom_row, length * sizeof(*row));
    490  }
    491 }
    492 
    493 // Upscale one component of the flow field, from a size of
    494 // cur_width x cur_height to a size of (2*cur_width) x (2*cur_height), storing
    495 // the result back into the same buffer. This function also scales the flow
    496 // vector by 2, so that when we move to the next pyramid level down, the implied
    497 // motion vector is the same.
    498 //
    499 // The temporary buffer tmpbuf must be large enough to hold an intermediate
    500 // array of size stride * cur_height, *plus* FLOW_BORDER_OUTER rows above and
    501 // below. In other words, indices from -FLOW_BORDER_OUTER * stride to
    502 // (cur_height + FLOW_BORDER_OUTER) * stride - 1 must be valid.
    503 //
    504 // Note that the same stride is used for u before and after upscaling
    505 // and for the temporary buffer, for simplicity.
    506 //
    507 // A note on phasing:
    508 //
    509 // The flow fields at two adjacent pyramid levels are offset from each other,
    510 // and we need to account for this in the construction of the interpolation
    511 // kernels.
    512 //
    513 // Consider an 8x8 pixel patch at pyramid level n. This is split into four
    514 // patches at pyramid level n-1. Bringing these patches back up to pyramid level
    515 // n, each sub-patch covers 4x4 pixels, and between them they cover the same
    516 // 8x8 region.
    517 //
    518 // Therefore, at pyramid level n, two adjacent patches look like this:
    519 //
    520 //    + - - - - - - - + - - - - - - - +
    521 //    |               |               |
    522 //    |   x       x   |   x       x   |
    523 //    |               |               |
    524 //    |       #       |       #       |
    525 //    |               |               |
    526 //    |   x       x   |   x       x   |
    527 //    |               |               |
    528 //    + - - - - - - - + - - - - - - - +
    529 //
    530 // where # marks the center of a patch at pyramid level n (the input to this
    531 // function), and x marks the center of a patch at pyramid level n-1 (the output
    532 // of this function).
    533 //
    534 // By counting pixels (marked by +, -, and |), we can see that the flow vectors
    535 // at pyramid level n-1 are offset relative to the flow vectors at pyramid
    536 // level n, by 1/4 of the larger (input) patch size. Therefore, our
    537 // interpolation kernels need to have phases of 0.25 and 0.75.
    538 //
    539 // In addition, in order to handle the frame edges correctly, we need to
    540 // generate one output vector to the left and one to the right of each input
    541 // vector, even though these must be interpolated using different source points.
    542 static void upscale_flow_component(double *flow, int cur_width, int cur_height,
    543                                   int stride, double *tmpbuf) {
    544  const int half_len = FLOW_UPSCALE_TAPS / 2;
    545 
    546  // Check that the outer border is large enough to avoid needing to clamp
    547  // the source locations
    548  assert(half_len <= FLOW_BORDER_OUTER);
    549 
    550  // Horizontal upscale and multiply by 2
    551  for (int i = 0; i < cur_height; i++) {
    552    for (int j = 0; j < cur_width; j++) {
    553      double left = 0;
    554      for (int k = -half_len; k < half_len; k++) {
    555        left +=
    556            flow[i * stride + (j + k)] * flow_upscale_filter[0][k + half_len];
    557      }
    558      tmpbuf[i * stride + (2 * j + 0)] = 2.0 * left;
    559 
    560      // Right output pixel is 0.25 units to the right of the input pixel
    561      double right = 0;
    562      for (int k = -(half_len - 1); k < (half_len + 1); k++) {
    563        right += flow[i * stride + (j + k)] *
    564                 flow_upscale_filter[1][k + (half_len - 1)];
    565      }
    566      tmpbuf[i * stride + (2 * j + 1)] = 2.0 * right;
    567    }
    568  }
    569 
    570  // Fill in top and bottom borders of tmpbuf
    571  const double *top_row = &tmpbuf[0];
    572  for (int i = -FLOW_BORDER_OUTER; i < 0; i++) {
    573    double *row = &tmpbuf[i * stride];
    574    memcpy(row, top_row, 2 * cur_width * sizeof(*row));
    575  }
    576 
    577  const double *bottom_row = &tmpbuf[(cur_height - 1) * stride];
    578  for (int i = cur_height; i < cur_height + FLOW_BORDER_OUTER; i++) {
    579    double *row = &tmpbuf[i * stride];
    580    memcpy(row, bottom_row, 2 * cur_width * sizeof(*row));
    581  }
    582 
    583  // Vertical upscale
    584  int upscaled_width = cur_width * 2;
    585  for (int i = 0; i < cur_height; i++) {
    586    for (int j = 0; j < upscaled_width; j++) {
    587      double top = 0;
    588      for (int k = -half_len; k < half_len; k++) {
    589        top +=
    590            tmpbuf[(i + k) * stride + j] * flow_upscale_filter[0][k + half_len];
    591      }
    592      flow[(2 * i) * stride + j] = top;
    593 
    594      double bottom = 0;
    595      for (int k = -(half_len - 1); k < (half_len + 1); k++) {
    596        bottom += tmpbuf[(i + k) * stride + j] *
    597                  flow_upscale_filter[1][k + (half_len - 1)];
    598      }
    599      flow[(2 * i + 1) * stride + j] = bottom;
    600    }
    601  }
    602 }
    603 
    604 // make sure flow_u and flow_v start at 0
    605 static bool compute_flow_field(const ImagePyramid *src_pyr,
    606                               const ImagePyramid *ref_pyr, int n_levels,
    607                               FlowField *flow) {
    608  bool mem_status = true;
    609 
    610  double *flow_u = flow->u;
    611  double *flow_v = flow->v;
    612 
    613  double *tmpbuf0;
    614  double *tmpbuf;
    615 
    616  if (n_levels < 2) {
    617    // tmpbuf not needed
    618    tmpbuf0 = NULL;
    619    tmpbuf = NULL;
    620  } else {
    621    // This line must match the calculation of cur_flow_height below
    622    const int layer1_height = src_pyr->layers[1].height >> DOWNSAMPLE_SHIFT;
    623 
    624    const size_t tmpbuf_size =
    625        (layer1_height + 2 * FLOW_BORDER_OUTER) * flow->stride;
    626    tmpbuf0 = aom_malloc(tmpbuf_size * sizeof(*tmpbuf0));
    627    if (!tmpbuf0) {
    628      mem_status = false;
    629      goto free_tmpbuf;
    630    }
    631    tmpbuf = tmpbuf0 + FLOW_BORDER_OUTER * flow->stride;
    632  }
    633 
    634  // Compute flow field from coarsest to finest level of the pyramid
    635  //
    636  // Note: We stop after refining pyramid level 1 and interpolating it to
    637  // generate an initial flow field at level 0. We do *not* refine the dense
    638  // flow field at level 0. Instead, we wait until we have generated
    639  // correspondences by interpolating this flow field, and then refine the
    640  // correspondences themselves. This is both faster and gives better output
    641  // compared to refining the flow field at level 0 and then interpolating.
    642  for (int level = n_levels - 1; level >= 1; --level) {
    643    const PyramidLayer *cur_layer = &src_pyr->layers[level];
    644    const int cur_width = cur_layer->width;
    645    const int cur_height = cur_layer->height;
    646    const int cur_stride = cur_layer->stride;
    647 
    648    const uint8_t *src_buffer = cur_layer->buffer;
    649    const uint8_t *ref_buffer = ref_pyr->layers[level].buffer;
    650 
    651    const int cur_flow_width = cur_width >> DOWNSAMPLE_SHIFT;
    652    const int cur_flow_height = cur_height >> DOWNSAMPLE_SHIFT;
    653    const int cur_flow_stride = flow->stride;
    654 
    655    for (int i = FLOW_BORDER_INNER; i < cur_flow_height - FLOW_BORDER_INNER;
    656         i += 1) {
    657      for (int j = FLOW_BORDER_INNER; j < cur_flow_width - FLOW_BORDER_INNER;
    658           j += 1) {
    659        const int flow_field_idx = i * cur_flow_stride + j;
    660 
    661        // Calculate the position of a patch of size DISFLOW_PATCH_SIZE pixels,
    662        // which is centered on the region covered by this flow field entry
    663        const int patch_center_x =
    664            (j << DOWNSAMPLE_SHIFT) + UPSAMPLE_CENTER_OFFSET;  // In pixels
    665        const int patch_center_y =
    666            (i << DOWNSAMPLE_SHIFT) + UPSAMPLE_CENTER_OFFSET;  // In pixels
    667        const int patch_tl_x = patch_center_x - DISFLOW_PATCH_CENTER;
    668        const int patch_tl_y = patch_center_y - DISFLOW_PATCH_CENTER;
    669        assert(patch_tl_x >= 0);
    670        assert(patch_tl_y >= 0);
    671 
    672        aom_compute_flow_at_point(src_buffer, ref_buffer, patch_tl_x,
    673                                  patch_tl_y, cur_width, cur_height, cur_stride,
    674                                  &flow_u[flow_field_idx],
    675                                  &flow_v[flow_field_idx]);
    676      }
    677    }
    678 
    679    // Fill in the areas which we haven't explicitly computed, with copies
    680    // of the outermost values which we did compute
    681    fill_flow_field_borders(flow_u, cur_flow_width, cur_flow_height,
    682                            cur_flow_stride);
    683    fill_flow_field_borders(flow_v, cur_flow_width, cur_flow_height,
    684                            cur_flow_stride);
    685 
    686    if (level > 0) {
    687      const int upscale_flow_width = cur_flow_width << 1;
    688      const int upscale_flow_height = cur_flow_height << 1;
    689      const int upscale_stride = flow->stride;
    690 
    691      upscale_flow_component(flow_u, cur_flow_width, cur_flow_height,
    692                             cur_flow_stride, tmpbuf);
    693      upscale_flow_component(flow_v, cur_flow_width, cur_flow_height,
    694                             cur_flow_stride, tmpbuf);
    695 
    696      // If we didn't fill in the rightmost column or bottommost row during
    697      // upsampling (in order to keep the ratio to exactly 2), fill them
    698      // in here by copying the next closest column/row
    699      const PyramidLayer *next_layer = &src_pyr->layers[level - 1];
    700      const int next_flow_width = next_layer->width >> DOWNSAMPLE_SHIFT;
    701      const int next_flow_height = next_layer->height >> DOWNSAMPLE_SHIFT;
    702 
    703      // Rightmost column
    704      if (next_flow_width > upscale_flow_width) {
    705        assert(next_flow_width == upscale_flow_width + 1);
    706        for (int i = 0; i < upscale_flow_height; i++) {
    707          const int index = i * upscale_stride + upscale_flow_width;
    708          flow_u[index] = flow_u[index - 1];
    709          flow_v[index] = flow_v[index - 1];
    710        }
    711      }
    712 
    713      // Bottommost row
    714      if (next_flow_height > upscale_flow_height) {
    715        assert(next_flow_height == upscale_flow_height + 1);
    716        for (int j = 0; j < next_flow_width; j++) {
    717          const int index = upscale_flow_height * upscale_stride + j;
    718          flow_u[index] = flow_u[index - upscale_stride];
    719          flow_v[index] = flow_v[index - upscale_stride];
    720        }
    721      }
    722    }
    723  }
    724 
    725 free_tmpbuf:
    726  aom_free(tmpbuf0);
    727  return mem_status;
    728 }
    729 
    730 static FlowField *alloc_flow_field(int frame_width, int frame_height) {
    731  FlowField *flow = (FlowField *)aom_malloc(sizeof(FlowField));
    732  if (flow == NULL) return NULL;
    733 
    734  // Calculate the size of the bottom (largest) layer of the flow pyramid
    735  flow->width = frame_width >> DOWNSAMPLE_SHIFT;
    736  flow->height = frame_height >> DOWNSAMPLE_SHIFT;
    737  flow->stride = flow->width + 2 * FLOW_BORDER_OUTER;
    738 
    739  const size_t flow_size =
    740      flow->stride * (size_t)(flow->height + 2 * FLOW_BORDER_OUTER);
    741 
    742  flow->buf0 = aom_calloc(2 * flow_size, sizeof(*flow->buf0));
    743  if (!flow->buf0) {
    744    aom_free(flow);
    745    return NULL;
    746  }
    747 
    748  flow->u = flow->buf0 + FLOW_BORDER_OUTER * flow->stride + FLOW_BORDER_OUTER;
    749  flow->v = flow->u + flow_size;
    750 
    751  return flow;
    752 }
    753 
    754 static void free_flow_field(FlowField *flow) {
    755  aom_free(flow->buf0);
    756  aom_free(flow);
    757 }
    758 
    759 // Compute flow field between `src` and `ref`, and then use that flow to
    760 // compute a global motion model relating the two frames.
    761 //
    762 // Following the convention in flow_estimation.h, the flow vectors are computed
    763 // at fixed points in `src` and point to the corresponding locations in `ref`,
    764 // regardless of the temporal ordering of the frames.
    765 bool av1_compute_global_motion_disflow(
    766    TransformationType type, YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *ref,
    767    int bit_depth, int downsample_level, MotionModel *motion_models,
    768    int num_motion_models, bool *mem_alloc_failed) {
    769  // Precompute information we will need about each frame
    770  ImagePyramid *src_pyramid = src->y_pyramid;
    771  CornerList *src_corners = src->corners;
    772  ImagePyramid *ref_pyramid = ref->y_pyramid;
    773 
    774  const int src_layers =
    775      aom_compute_pyramid(src, bit_depth, DISFLOW_PYRAMID_LEVELS, src_pyramid);
    776  const int ref_layers =
    777      aom_compute_pyramid(ref, bit_depth, DISFLOW_PYRAMID_LEVELS, ref_pyramid);
    778 
    779  if (src_layers < 0 || ref_layers < 0) {
    780    *mem_alloc_failed = true;
    781    return false;
    782  }
    783  if (!av1_compute_corner_list(src, bit_depth, downsample_level, src_corners)) {
    784    *mem_alloc_failed = true;
    785    return false;
    786  }
    787 
    788  assert(src_layers == ref_layers);
    789 
    790  const int src_width = src_pyramid->layers[0].width;
    791  const int src_height = src_pyramid->layers[0].height;
    792  assert(ref_pyramid->layers[0].width == src_width);
    793  assert(ref_pyramid->layers[0].height == src_height);
    794 
    795  FlowField *flow = alloc_flow_field(src_width, src_height);
    796  if (!flow) {
    797    *mem_alloc_failed = true;
    798    return false;
    799  }
    800 
    801  if (!compute_flow_field(src_pyramid, ref_pyramid, src_layers, flow)) {
    802    *mem_alloc_failed = true;
    803    free_flow_field(flow);
    804    return false;
    805  }
    806 
    807  // find correspondences between the two images using the flow field
    808  Correspondence *correspondences =
    809      aom_malloc(src_corners->num_corners * sizeof(*correspondences));
    810  if (!correspondences) {
    811    *mem_alloc_failed = true;
    812    free_flow_field(flow);
    813    return false;
    814  }
    815 
    816  const int num_correspondences = determine_disflow_correspondence(
    817      src_pyramid, ref_pyramid, src_corners, flow, correspondences);
    818 
    819  bool result = ransac(correspondences, num_correspondences, type,
    820                       motion_models, num_motion_models, mem_alloc_failed);
    821 
    822  aom_free(correspondences);
    823  free_flow_field(flow);
    824  return result;
    825 }