Add optical flow api skeleton only.
Change-Id: I0b1e47c3e4ae4cbc9d7f4284a95a629add7b98cb
diff --git a/av1/av1.cmake b/av1/av1.cmake
index ed4265f..0775040 100644
--- a/av1/av1.cmake
+++ b/av1/av1.cmake
@@ -189,6 +189,8 @@
"${AOM_ROOT}/av1/encoder/motion_search_facade.h"
"${AOM_ROOT}/av1/encoder/mv_prec.c"
"${AOM_ROOT}/av1/encoder/mv_prec.h"
+ "${AOM_ROOT}/av1/encoder/optical_flow.c"
+ "${AOM_ROOT}/av1/encoder/optical_flow.h"
"${AOM_ROOT}/av1/encoder/palette.c"
"${AOM_ROOT}/av1/encoder/palette.h"
"${AOM_ROOT}/av1/encoder/partition_search.h"
diff --git a/av1/encoder/optical_flow.c b/av1/encoder/optical_flow.c
new file mode 100644
index 0000000..90c9a5b
--- /dev/null
+++ b/av1/encoder/optical_flow.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+#include <math.h>
+#include <limits.h>
+
+#include "config/aom_config.h"
+#include "av1/common/av1_common_int.h"
+#include "av1/encoder/encoder.h"
+#include "av1/encoder/mathutils.h"
+#include "av1/encoder/optical_flow.h"
+#include "av1/encoder/reconinter_enc.h"
+#include "aom_mem/aom_mem.h"
+
+#if CONFIG_OPTICAL_FLOW_API
+
+typedef struct LOCALMV {
+ double row;
+ double col;
+} LOCALMV;
+
+// Computes optical flow by applying algorithm at
+// multiple pyramid levels of images (lower-resolution, smoothed images)
+// This accounts for larger motions.
+// Inputs:
+// from_frame Frame buffer.
+// to_frame: Frame buffer. MVs point from_frame -> to_frame.
+// from_frame_idx: Index of from_frame.
+// to_frame_idx: Index of to_frame. Return all zero MVs when idx are equal.
+// bit_depth:
+// opfl_params: contains algorithm-specific parameters.
+// mv_filter: MV_FILTER_NONE, MV_FILTER_SMOOTH, or MV_FILTER_MEDIAN.
+// method: LUCAS_KANADE,
+// mvs: pointer to MVs. Contains initialization, and modified
+// based on optical flow. Must have
+// dimensions = from_frame->y_crop_width * from_frame->y_crop_height
+void optical_flow(const YV12_BUFFER_CONFIG *from_frame,
+ const YV12_BUFFER_CONFIG *to_frame, const int from_frame_idx,
+ const int to_frame_idx, const int bit_depth,
+ const OPFL_PARAMS *opfl_params,
+ const MV_FILTER_TYPE mv_filter, const OPTFLOW_METHOD method,
+ MV *mvs) {
+ const int frame_height = from_frame->y_crop_height;
+ const int frame_width = from_frame->y_crop_width;
+ // TODO(any): deal with the case where frames are not of the same dimensions
+ assert(frame_height == to_frame->y_crop_height &&
+ frame_width == to_frame->y_crop_width);
+ if (from_frame_idx == to_frame_idx) {
+ // immediately return all zero mvs when frame indices are equal
+ for (int yy = 0; yy < frame_height; yy++) {
+ for (int xx = 0; xx < frame_width; xx++) {
+ MV mv = { .row = 0, .col = 0 };
+ mvs[yy * frame_width + xx] = mv;
+ }
+ }
+ return;
+ }
+ // Initialize double mvs based on input parameter mvs array
+ LOCALMV *localmvs = aom_malloc(frame_height * frame_width * sizeof(LOCALMV));
+ for (int i = 0; i < frame_width * frame_height; i++) {
+ MV mv = mvs[i];
+ LOCALMV localmv = { .row = ((double)mv.row) / 8,
+ .col = ((double)mv.col) / 8 };
+ localmvs[i] = localmv;
+ }
+ // Apply optical flow algorithm
+
+ // Update original mvs array
+ for (int j = 0; j < frame_height; j++) {
+ for (int i = 0; i < frame_width; i++) {
+ int idx = j * frame_width + i;
+ int new_x = localmvs[idx].row + i;
+ int new_y = localmvs[idx].col + j;
+ if ((fabs(localmvs[idx].row) >= 0.125 ||
+ fabs(localmvs[idx].col) >= 0.125)) {
+ // if mv points outside of frame (lost feature), keep old mv.
+ if (new_x < frame_width && new_x >= 0 && new_y < frame_height &&
+ new_y >= 0) {
+ MV mv = { .row = (int16_t)round(8 * localmvs[idx].row),
+ .col = (int16_t)round(8 * localmvs[idx].col) };
+ mvs[idx] = mv;
+ }
+ }
+ }
+ }
+ aom_free(localmvs);
+}
+#endif
diff --git a/av1/encoder/optical_flow.h b/av1/encoder/optical_flow.h
new file mode 100644
index 0000000..5056af3
--- /dev/null
+++ b/av1/encoder/optical_flow.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#ifndef AOM_AV1_ENCODER_OPTICAL_FLOW_H_
+#define AOM_AV1_ENCODER_OPTICAL_FLOW_H_
+
+#include "config/aom_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if CONFIG_OPTICAL_FLOW_API
+
+typedef enum { LUCAS_KANADE } OPTFLOW_METHOD;
+
+typedef enum {
+ MV_FILTER_NONE,
+ MV_FILTER_SMOOTH,
+ MV_FILTER_MEDIAN
+} MV_FILTER_TYPE;
+
+// default options for optical flow
+#define OPFL_WINDOW_SIZE 15
+#define OPFL_PYRAMID_LEVELS 3 // total levels (max is 5)
+
+// parameters specific to Lucas-Kanade
+typedef struct lk_params {
+ int window_size;
+} LK_PARAMS;
+
+// generic structure to contain parameters for all
+// optical flow algorithms
+typedef struct opfl_params {
+ int pyramid_levels;
+ LK_PARAMS *lk_params;
+} OPFL_PARAMS;
+
+void init_opfl_params(OPFL_PARAMS *opfl_params) {
+ opfl_params->pyramid_levels = OPFL_PYRAMID_LEVELS;
+ opfl_params->lk_params = NULL;
+}
+
+void init_lk_params(LK_PARAMS *lk_params) {
+ lk_params->window_size = OPFL_WINDOW_SIZE;
+}
+
+void optical_flow(const YV12_BUFFER_CONFIG *from_frame,
+ const YV12_BUFFER_CONFIG *to_frame, const int from_frame_idx,
+ const int to_frame_idx, const int bit_depth,
+ const OPFL_PARAMS *opfl_params,
+ const MV_FILTER_TYPE mv_filter, const OPTFLOW_METHOD method,
+ MV *mvs);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // AOM_AV1_ENCODER_OPTICAL_FLOW_H_
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index 3db4f53..2497ff1 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -107,6 +107,7 @@
set_aom_config_var(DECODE_HEIGHT_LIMIT 0 "Set limit for decode height.")
set_aom_config_var(DECODE_WIDTH_LIMIT 0 "Set limit for decode width.")
set_aom_config_var(CONFIG_TUNE_VMAF 0 "Enable encoding tuning for VMAF.")
+set_aom_config_var(CONFIG_OPTICAL_FLOW_API 0 "Enables optical flow API.")
# AV1 experiment flags.
set_aom_config_var(CONFIG_SPEED_STATS 0 "AV1 experiment flag.")