Replace libvmaf with libvmaf_rc when CONFIG_USE_VMAF_RC enabled
This CL also replaces VMAF score with VMAF_NEG score during RDO in
tune=vmaf_neg mode. Got additional -0.3% VMAF_NEG gains.
baseline=psnr
avg_psnr ssim vmaf vmaf_neg
lowres_bd10 11.633 4.393 -20.757 -8.446
midres_bd10 10.772 5.555 -21.276 -7.924
midres 10.778 6.660 -17.250 -6.720
hdres 9.958 6.408 -20.309 -8.138
Change-Id: I9be2b95ab226226180a7df368d8f3dd71d55b846
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7e1f730..af89576 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -438,19 +438,6 @@
if(CONFIG_TUNE_VMAF)
find_package(PkgConfig)
- if(PKG_CONFIG_FOUND)
- pkg_check_modules(VMAF REQUIRED libvmaf)
- else()
- find_library(VMAF_LIBRARIES vmaf)
- find_path(VMAF_INCLUDE_DIRS libvmaf.h PATH_SUFFIXES libvmaf)
- if(VMAF_LIBRARIES AND VMAF_INCLUDE_DIRS)
- message(STATUS "Found VMAF library: ${VMAF_LIBRARIES}")
- message(STATUS "Found VMAF include: ${VMAF_INCLUDE_DIRS}")
- else()
- message(FATAL_ERROR "VMAF library not found.")
- endif()
- endif()
-
if(CONFIG_USE_VMAF_RC)
if(PKG_CONFIG_FOUND)
pkg_check_modules(VMAF_RC REQUIRED libvmaf_rc)
@@ -463,17 +450,29 @@
else()
message(FATAL_ERROR "CONFIG_USE_VMAF_RC error: pkg-config not found.")
endif()
+ else()
+ if(PKG_CONFIG_FOUND)
+ pkg_check_modules(VMAF REQUIRED libvmaf)
+ else()
+ find_library(VMAF_LIBRARIES vmaf)
+ find_path(VMAF_INCLUDE_DIRS libvmaf.h PATH_SUFFIXES libvmaf)
+ if(VMAF_LIBRARIES AND VMAF_INCLUDE_DIRS)
+ message(STATUS "Found VMAF library: ${VMAF_LIBRARIES}")
+ message(STATUS "Found VMAF include: ${VMAF_INCLUDE_DIRS}")
+ else()
+ message(FATAL_ERROR "VMAF library not found.")
+ endif()
+ endif()
+ target_link_libraries(aom PRIVATE ${VMAF_LDFLAGS} ${VMAF_LIBRARIES})
+ target_include_directories(aom PRIVATE ${VMAF_INCLUDE_DIRS})
+ if(VMAF_CFLAGS)
+ append_compiler_flag("${VMAF_CFLAGS}")
+ endif()
endif()
-
set_target_properties(aom PROPERTIES LINKER_LANGUAGE CXX)
if(BUILD_SHARED_LIBS)
set_target_properties(aom_static PROPERTIES LINKER_LANGUAGE CXX)
endif()
- target_link_libraries(aom PRIVATE ${VMAF_LDFLAGS} ${VMAF_LIBRARIES})
- target_include_directories(aom PRIVATE ${VMAF_INCLUDE_DIRS})
- if(VMAF_CFLAGS)
- append_compiler_flag("${VMAF_CFLAGS}")
- endif()
endif()
endif()
diff --git a/aom_dsp/vmaf.c b/aom_dsp/vmaf.c
index b0be482..ee72e57 100644
--- a/aom_dsp/vmaf.c
+++ b/aom_dsp/vmaf.c
@@ -12,7 +12,9 @@
#include "aom_dsp/vmaf.h"
#include <assert.h>
+#if !CONFIG_USE_VMAF_RC
#include <libvmaf.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -29,6 +31,12 @@
#include "aom_dsp/blend.h"
#include "aom_ports/system_state.h"
+static void vmaf_fatal_error(const char *message) {
+ fprintf(stderr, "Fatal error: %s\n", message);
+ exit(EXIT_FAILURE);
+}
+
+#if !CONFIG_USE_VMAF_RC
typedef struct FrameData {
const YV12_BUFFER_CONFIG *source;
const YV12_BUFFER_CONFIG *distorted;
@@ -36,11 +44,6 @@
int bit_depth;
} FrameData;
-static void vmaf_fatal_error(const char *message) {
- fprintf(stderr, "Fatal error: %s\n", message);
- exit(EXIT_FAILURE);
-}
-
// A callback function used to pass data to VMAF.
// Returns 0 after reading a frame.
// Returns 2 when there is no more frame to read.
@@ -173,6 +176,7 @@
aom_clear_system_state();
}
+#endif
#if CONFIG_USE_VMAF_RC
void aom_init_vmaf_rc(VmafModel **vmaf_model, const char *model_path) {
diff --git a/aom_dsp/vmaf.h b/aom_dsp/vmaf.h
index 775c9cb..607d4bd 100644
--- a/aom_dsp/vmaf.h
+++ b/aom_dsp/vmaf.h
@@ -46,6 +46,15 @@
#endif
} TuneVMAFInfo;
+#if CONFIG_USE_VMAF_RC
+void aom_init_vmaf_rc(VmafModel **vmaf_model, const char *model_path);
+
+void aom_calc_vmaf_rc(VmafModel *vmaf_model, const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *distorted, int bit_depth,
+ int cal_vmaf_neg, double *vmaf);
+
+void aom_close_vmaf_rc(VmafModel *vmaf_model);
+#else
void aom_calc_vmaf(const char *model_path, const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *distorted, int bit_depth,
double *vmaf);
@@ -55,15 +64,6 @@
int (*read_frame)(float *ref_data, float *main_data, float *temp_data,
int stride_byte, void *user_data),
int frame_width, int frame_height, int bit_depth, double *vmaf);
-
-#if CONFIG_USE_VMAF_RC
-void aom_init_vmaf_rc(VmafModel **vmaf_model, const char *model_path);
-
-void aom_calc_vmaf_rc(VmafModel *vmaf_model, const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *distorted, int bit_depth,
- int cal_vmaf_neg, double *vmaf);
-
-void aom_close_vmaf_rc(VmafModel *vmaf_model);
#endif // CONFIG_USE_VMAF_RC
#endif // AOM_AOM_DSP_VMAF_H_
diff --git a/av1/encoder/tune_vmaf.c b/av1/encoder/tune_vmaf.c
index 62c29d4..ec63379 100644
--- a/av1/encoder/tune_vmaf.c
+++ b/av1/encoder/tune_vmaf.c
@@ -16,6 +16,9 @@
#include "aom_ports/system_state.h"
#include "av1/encoder/extend.h"
#include "av1/encoder/rdopt.h"
+#if CONFIG_USE_VMAF_RC
+#include "config/aom_scale_rtcd.h"
+#endif
static const double kBaselineVmaf = 97.42773;
@@ -160,8 +163,16 @@
YV12_BUFFER_CONFIG *const sharpened) {
const int bit_depth = cpi->td.mb.e_mbd.bd;
double new_vmaf;
+
+#if CONFIG_USE_VMAF_RC
+ aom_calc_vmaf_rc(cpi->vmaf_info.vmaf_model, source, sharpened, bit_depth,
+ cpi->oxcf.tune_cfg.tuning == AOM_TUNE_VMAF_NEG_MAX_GAIN,
+ &new_vmaf);
+#else
aom_calc_vmaf(cpi->oxcf.tune_cfg.vmaf_model_path, source, sharpened,
bit_depth, &new_vmaf);
+#endif
+
const double sharpened_var = frame_average_variance(cpi, sharpened);
return source_variance / sharpened_var * (new_vmaf - kBaselineVmaf);
}
@@ -447,6 +458,7 @@
aom_clear_system_state();
}
+#if !CONFIG_USE_VMAF_RC
typedef struct FrameData {
const YV12_BUFFER_CONFIG *source, *blurred;
int block_w, block_h, num_rows, num_cols, row, col, bit_depth;
@@ -531,6 +543,7 @@
return 2;
}
}
+#endif
void av1_set_mb_vmaf_rdmult_scaling(AV1_COMP *cpi) {
AV1_COMMON *cm = &cpi->common;
@@ -567,6 +580,15 @@
cm->features.byte_alignment);
gaussian_blur(bit_depth, &resized_source, &blurred);
+#if CONFIG_USE_VMAF_RC
+ YV12_BUFFER_CONFIG recon;
+ memset(&recon, 0, sizeof(recon));
+ aom_alloc_frame_buffer(&recon, resized_y_width, resized_y_height, 1, 1,
+ cm->seq_params.use_highbitdepth,
+ cpi->oxcf.border_in_pixels,
+ cm->features.byte_alignment);
+ aom_yv12_copy_frame(&resized_source, &recon, 1);
+#else
double *scores = aom_malloc(sizeof(*scores) * (num_rows * num_cols));
memset(scores, 0, sizeof(*scores) * (num_rows * num_cols));
FrameData frame_data;
@@ -582,6 +604,7 @@
aom_calc_vmaf_multi_frame(&frame_data, cpi->oxcf.tune_cfg.vmaf_model_path,
update_frame, resized_y_width, resized_y_height,
bit_depth, scores);
+#endif
// Loop through each 'block_size' block.
for (int row = 0; row < num_rows; ++row) {
@@ -596,12 +619,47 @@
uint8_t *const blurred_buf =
blurred.y_buffer + row_offset_y * blurred.y_stride + col_offset_y;
- const double vmaf = scores[index];
- const double dvmaf = kBaselineVmaf - vmaf;
unsigned int sse;
cpi->fn_ptr[resized_block_size].vf(orig_buf, resized_source.y_stride,
blurred_buf, blurred.y_stride, &sse);
+#if CONFIG_USE_VMAF_RC
+ uint8_t *const recon_buf =
+ recon.y_buffer + row_offset_y * recon.y_stride + col_offset_y;
+ // Set recon buf
+ if (cpi->common.seq_params.use_highbitdepth) {
+ highbd_unsharp_rect(CONVERT_TO_SHORTPTR(blurred_buf), blurred.y_stride,
+ CONVERT_TO_SHORTPTR(blurred_buf), blurred.y_stride,
+ CONVERT_TO_SHORTPTR(recon_buf), recon.y_stride,
+ resized_block_w, resized_block_h, 0.0, bit_depth);
+ } else {
+ unsharp_rect(blurred_buf, blurred.y_stride, blurred_buf,
+ blurred.y_stride, recon_buf, recon.y_stride,
+ resized_block_w, resized_block_h, 0.0);
+ }
+
+ double vmaf;
+ aom_calc_vmaf_rc(
+ cpi->vmaf_info.vmaf_model, &resized_source, &recon, bit_depth,
+ cpi->oxcf.tune_cfg.tuning == AOM_TUNE_VMAF_NEG_MAX_GAIN, &vmaf);
+
+ // Restore recon buf
+ if (cpi->common.seq_params.use_highbitdepth) {
+ highbd_unsharp_rect(
+ CONVERT_TO_SHORTPTR(orig_buf), resized_source.y_stride,
+ CONVERT_TO_SHORTPTR(orig_buf), resized_source.y_stride,
+ CONVERT_TO_SHORTPTR(recon_buf), recon.y_stride, resized_block_w,
+ resized_block_h, 0.0, bit_depth);
+ } else {
+ unsharp_rect(orig_buf, resized_source.y_stride, orig_buf,
+ resized_source.y_stride, recon_buf, recon.y_stride,
+ resized_block_w, resized_block_h, 0.0);
+ }
+#else
+ const double vmaf = scores[index];
+#endif
+ const double dvmaf = kBaselineVmaf - vmaf;
+
const double mse =
(double)sse / (double)(resized_y_width * resized_y_height);
double weight;
@@ -620,7 +678,9 @@
aom_free_frame_buffer(&resized_source);
aom_free_frame_buffer(&blurred);
+#if !CONFIG_USE_VMAF_RC
aom_free(scores);
+#endif
aom_clear_system_state();
}
@@ -882,8 +942,14 @@
void av1_update_vmaf_curve(AV1_COMP *cpi, YV12_BUFFER_CONFIG *source,
YV12_BUFFER_CONFIG *recon) {
const int bit_depth = cpi->td.mb.e_mbd.bd;
+#if CONFIG_USE_VMAF_RC
+ aom_calc_vmaf_rc(cpi->vmaf_info.vmaf_model, source, recon, bit_depth,
+ cpi->oxcf.tune_cfg.tuning == AOM_TUNE_VMAF_NEG_MAX_GAIN,
+ &cpi->vmaf_info.last_frame_vmaf);
+#else
aom_calc_vmaf(cpi->oxcf.tune_cfg.vmaf_model_path, source, recon, bit_depth,
&cpi->vmaf_info.last_frame_vmaf);
+#endif
if (cpi->common.seq_params.use_highbitdepth) {
assert(source->flags & YV12_FLAG_HIGHBITDEPTH);
assert(recon->flags & YV12_FLAG_HIGHBITDEPTH);