blob: 9770d71c1e37eb49c9d93c57d8913538ee94714c [file] [log] [blame]
/*
* Copyright (c) 2017, 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 AV1_COMMON_OPTICAL_FLOW_REF_H_
#define AV1_COMMON_OPTICAL_FLOW_REF_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "./aom_config.h"
#include "av1/common/alloccommon.h"
#include "av1/common/onyxc_int.h"
#if CONFIG_OPFL
// Constant MACRO defs
#define AVG_MF_BORDER 4
#define OPFL_MF_FRAME_BORDER 32
#define MAX_MV_LENGTH_1D 160
#define DERIVATIVE_FILTER_LENGTH 7
// OPFL parameters
#define MAX_OPFL_LEVEL 3 // levels in pyramid, maximum 3
#define MAX_ITER_OPTICAL_FLOW 3 // for each level number of iteration
#define USE_BLK_DERIVATIVE 1
#define OF_A_SQUARED 25 // Laplacian parameter
#define FAST_OPTICAL_FLOW 0 // Use fast iterative method
#define MAX_ITER_FAST_OPFL 15 // this has to be an odd number for now.
#define USE_MEDIAN_FILTER 1
#define FRAME_LEVEL_OPFL 1
#define OPFL_BLOCK_SIZE 16
// MACROs for Debug
#define NO_BITSTREAM 0
#define DUMP_OPFL 0
#define OPFL_OUTPUT_TIME 0
// Experimental MACROs
#define OPFL_INIT_WT 1
#define OPFL_MV_PRED 1
#define OPFL_TPL 1
#define OPFL_TPL_NEIGHBOR 1
#define OPFL_BOUND_HANDLING 1
#define OPFL_CONF_WTS 1
#define OPFL_EXP_INIT 1
#define OPFL_DERIVE_INIT_MV 1
#define OPFL_CHECK_INIT_MV 0
#define OPFL_INIT_MOTION_SEARCH 0
#define OPFL_EXP_DERV 0
#define MAX_NUM_REF_PAIR 9
// Experimental MACROs not used for now
#define OPTICAL_FLOW_DIFF_THRES 10.0 // Thres to detect pixel difference
#define OPTICAL_FLOW_REF_THRES 0.3 // Thres to determine reference usage
#define OPTICAL_FLOW_TRUST_MV_THRES 0.3 // Thres to trust motion field
#define OPFL_ANNEAL_FACTOR 1.0 // Annealing factor for laplacian multiplier
typedef enum opfl_blend_method {
OPFL_SIMPLE_BLEND = 0,
OPFL_NEAREST_SINGLE,
OPFL_DIFF_SINGLE,
OPFL_DIFF_SELECT,
} OPFL_BLEND_METHOD;
#define OPFL_BLEND_METHOD_USED OPFL_SIMPLE_BLEND
// motion field struct with double precision
typedef struct db_mv {
double row;
double col;
} DB_MV;
typedef struct opfl_buffer_struct {
DB_MV *init_mv_buf[MAX_OPFL_LEVEL]; // initialization of motion field
#if OPFL_INIT_WT
double *init_mv_wts[MAX_OPFL_LEVEL];
#endif
YV12_BUFFER_CONFIG *ref0_buf[MAX_OPFL_LEVEL];
YV12_BUFFER_CONFIG *ref1_buf[MAX_OPFL_LEVEL];
YV12_BUFFER_CONFIG *ref0_warped_buf[MAX_OPFL_LEVEL];
YV12_BUFFER_CONFIG *ref1_warped_buf[MAX_OPFL_LEVEL];
YV12_BUFFER_CONFIG *dst_buf;
int initialized;
double dst_pos;
int left_offset;
int right_offset;
int cur_offset;
MV_REFERENCE_FRAME opfl_refs[2];
DB_MV *mf_last[MAX_OPFL_LEVEL];
DB_MV *mf_new[MAX_OPFL_LEVEL];
DB_MV *mf_med[MAX_OPFL_LEVEL]; // for motion field after median filter
DB_MV *mf_frame; // motion field buffer for the whole frame
DB_MV *mf_frame_start; // points to the start of motion field buffer
int mf_frame_stride;
double *Ex;
double *Ey;
double *Et;
double *ori_Ex0_buf[MAX_OPFL_LEVEL];
double *ori_Ey0_buf[MAX_OPFL_LEVEL];
double *ori_Et0_buf[MAX_OPFL_LEVEL];
double *ori_Ex1_buf[MAX_OPFL_LEVEL];
double *ori_Ey1_buf[MAX_OPFL_LEVEL];
double *ori_Et1_buf[MAX_OPFL_LEVEL];
YV12_BUFFER_CONFIG *buffer0[MAX_OPFL_LEVEL];
YV12_BUFFER_CONFIG *buffer1[MAX_OPFL_LEVEL];
int *done_flag;
} OPFL_BUFFER_STRUCT;
typedef struct opfl_block_info {
int starth;
int startw;
int blk_width;
int blk_height;
int upbound;
int lowerbound;
int leftbound;
int rightbound;
} OPFL_BLK_INFO;
int av1_get_opfl_ref(AV1_COMMON *cm);
void av1_opfl_set_buf(AV1_COMMON *cm, OPFL_BUFFER_STRUCT *buf_struct);
void av1_optical_flow_get_ref(OPFL_BUFFER_STRUCT *buf_struct,
OPFL_BLK_INFO blk_info);
void av1_opfl_alloc_buf(AV1_COMMON *cm, OPFL_BUFFER_STRUCT *buf_struct);
void av1_opfl_free_buf(OPFL_BUFFER_STRUCT *buf_struct);
int get_num_MV_between_refs(AV1_COMMON *cm, int left_idx, int left_offset,
int right_idx, int right_offset);
void opfl_select_best_ref_pairs(AV1_COMMON *cm, int *left_idx, int *left_offset,
int *left_chosen, int *right_idx,
int *right_offset, int *right_chosen,
int left_most_idx, int right_most_idx);
void opfl_get_closest_refs(AV1_COMMON *cm, int *left_idx_ptr,
int *left_offset_ptr, int *left_chosen_ptr,
int *right_idx_ptr, int *right_offset_ptr,
int *right_chosen_ptr);
void opfl_set_init_motion(AV1_COMMON *cm, OPFL_BUFFER_STRUCT *buf_struct,
int left_idx, int right_idx, int left_offset,
int right_offset, int_mv *left_mv, int_mv *right_mv);
void opfl_find_init_motion(AV1_COMMON *cm, int left_idx, int right_idx,
int left_offset, int right_offset, int_mv *left_mv);
void opfl_derive_init_mv(AV1_COMMON *cm, OPFL_BUFFER_STRUCT *buf_struct,
int left_idx, int right_idx, int left_offset,
int right_offset, int_mv *left_mv, int_mv *right_mv);
void opfl_update_init_motion(AV1_COMMON *cm, OPFL_BUFFER_STRUCT *buf_struct,
int_mv *left_mv, int_mv *right_mv, int left_offset,
int right_offset, int_mv *left_cand_mv,
int_mv *right_cand_mv, int left_cand_offset,
int right_cand_offset, int *is_first_valid,
int_mv *left_final_mv, int_mv *right_final_mv);
void refine_motion_field(OPFL_BUFFER_STRUCT *buf_struct, DB_MV *mf_last,
DB_MV *mf_new, int level, double dstpos, int usescale,
OPFL_BLK_INFO blk_info);
double iterate_update_mv(OPFL_BUFFER_STRUCT *buf_struct, DB_MV *mf_last,
DB_MV *mf_new, int level, double dstpos,
double as_scale, int usescale, OPFL_BLK_INFO blk_info,
int numWarpedRounds);
double iterate_update_mv_fast(OPFL_BUFFER_STRUCT *buf_struct, DB_MV *mf_last,
DB_MV *mf_new, int level, double dstpos,
double as_scale, int usescale,
OPFL_BLK_INFO blk_info);
void interp_optical_flow(YV12_BUFFER_CONFIG *ref0, YV12_BUFFER_CONFIG *ref1,
DB_MV *mf, YV12_BUFFER_CONFIG *dst, double dst_pos,
OPFL_BLK_INFO blk_info);
void warp_optical_flow_back(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *ref,
DB_MV *mf_start, int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos, int level, int usescale,
OPFL_BLK_INFO blk_info);
void warp_optical_flow_back_bilinear(YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *ref, DB_MV *mf_start,
int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos, int level, int usescale,
OPFL_BLK_INFO blk_info);
void warp_optical_flow_fwd(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *ref,
DB_MV *mf_start, int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos, int level, int usescale,
OPFL_BLK_INFO blk_info);
void warp_optical_flow_fwd_bilinear(YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *ref, DB_MV *mf_start,
int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos, int level, int usescale,
OPFL_BLK_INFO blk_info);
void warp_optical_flow(YV12_BUFFER_CONFIG *src0, YV12_BUFFER_CONFIG *src1,
DB_MV *mf_start, int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos, OPFL_BLEND_METHOD method,
OPFL_BLK_INFO blk_info);
void warp_optical_flow_diff_select(YV12_BUFFER_CONFIG *src0,
YV12_BUFFER_CONFIG *src1, DB_MV *mf_start,
int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos);
void warp_optical_flow_bilateral(YV12_BUFFER_CONFIG *src0,
YV12_BUFFER_CONFIG *src1, DB_MV *mf_start,
int mvstr, YV12_BUFFER_CONFIG *dst,
double dstpos, OPFL_BLK_INFO blk_info);
uint8_t get_sub_pel_y(uint8_t *src, int stride, double di, double dj);
uint8_t get_sub_pel_uv(uint8_t *src, int stride, double di, double dj);
void opfl_get_derivatives(double *Ex, double *Ey, double *Et,
YV12_BUFFER_CONFIG *buffer0,
YV12_BUFFER_CONFIG *buffer1,
YV12_BUFFER_CONFIG *buffer_init0,
YV12_BUFFER_CONFIG *buffer_init1, double dstpos,
int level, int usescale, OPFL_BLK_INFO blk_info);
void opfl_get_derivatives_nowarp(double *Ex, double *Ey,
OPFL_BUFFER_STRUCT *buf_struct, DB_MV *mf,
double dstpos, int level,
OPFL_BLK_INFO blk_info);
void opfl_fill_mv(int_mv *pmv, int width, int height);
void fill_create_motion_field(int_mv *mv_left, int_mv *mv_right, DB_MV *mf,
int width, int height, int mvwid, int mvhgt,
int mfstr);
void opfl_init_motion_search(int_mv *mv_left, int_mv *mv_right, DB_MV *mf,
int width, int height, int mvwid, int mvhgt,
int mfstr, double dstpos, OPFL_BLK_INFO *blk_info,
uint8_t *y0, uint8_t *y1, int srcstr);
void create_motion_field(int_mv *mv_left, int_mv *mv_right, DB_MV *mf,
#if OPFL_INIT_WT
double *mv_wts,
#endif
int width, int height, int mvwid, int mvhgt, int mfstr,
double dstpos);
void pad_motion_field_border(DB_MV *mf_start, int width, int height,
int stride);
double iter_median_double(double *x, double *left, double *right, int length,
int mididx);
int ref_mode_filter_3x3(int *center, int stride, double dstpos);
void upscale_mv_by_2(DB_MV *src, int srcw, int srch, int srcs, DB_MV *dst,
int dsts);
void extend_plane_opfl(uint8_t *const src, int src_stride, int width,
int height, int extend_top, int extend_left,
int extend_bottom, int extend_right);
int write_image_opfl(const YV12_BUFFER_CONFIG *const ref_buf, char *file_name);
int opfl_round_double_2_int(double x);
int opfl_floor_double_2_int(double x);
int opfl_ceil_double_2_int(double x);
void opfl_extend_frame_mf(OPFL_BUFFER_STRUCT *buf_struct,
OPFL_BLK_INFO blk_info);
#endif // CONFIG_OPFL
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AV1_COMMON_OPTICAL_FLOW_REF_H_