From 7ddaf2ae8ee0a83c8094a67915ebcc875ca7eab4 Mon Sep 17 00:00:00 2001 From: Christos Bampis Date: Sun, 25 Aug 2019 17:25:29 -0700 Subject: [PATCH] Revert bad commits. --- .newt.yml | 55 ------- feature/src/common/frame.c | 3 + python/src/vmaf/__init__.py | 4 +- python/src/vmaf/core/executor.py | 5 +- python/src/vmaf/core/quality_runner.py | 42 ++---- python/test/lib/libvmaf_libtest.py | 60 +------- python/test/vmafossexec_test.py | 87 +---------- wrapper/src/libvmaf.cpp | 35 ++++- wrapper/src/libvmaf.h | 32 +---- wrapper/src/main.cpp | 40 +----- wrapper/src/vmaf.cpp | 191 ++++++++----------------- wrapper/src/vmaf.h | 18 ++- 12 files changed, 127 insertions(+), 445 deletions(-) delete mode 100644 .newt.yml diff --git a/.newt.yml b/.newt.yml deleted file mode 100644 index 3c089240a..000000000 --- a/.newt.yml +++ /dev/null @@ -1,55 +0,0 @@ -app-type: debian-package - -build-image: dockerregistry.test.netflix.net:7002/engtools/newt-c-builder/xenial:latest - -build-setup: - - > - sudo apt-get update && sudo apt-get install -y - libogg-dev - python-setuptools - python-tk - python-dev - ffmpeg - - sudo easy_install pip - - sudo pip install --upgrade pip - - sudo pip install --upgrade h5py - - sudo pip install --upgrade numpy scipy matplotlib pandas nose - - sudo pip install --upgrade scikit-learn scikit-image - - sudo pip install --upgrade openpyxl - - sudo pip install --upgrade sureal - -build-step: - - # ==== make and install vmafossexec and models ==== - - make clean - - make - - sudo make install - - make testlib - - # ==== External ffmpeg path ==== - - touch $(pwd)/python/src/vmaf/externals.py - - echo "FFMPEG_PATH = '/usr/bin/ffmpeg'" > $(pwd)/python/src/vmaf/externals.py - - # ==== tests ==== - - cd python; export PYTHONPATH=$(pwd)/src:$PYTHONPATH; python -m unittest discover -t . -s test/lib -p '*_libtest.py' - - cd python; export PYTHONPATH=$(pwd)/src:$PYTHONPATH; python -m unittest discover -t . -s test -p '*_test.py' - - cd python; export PYTHONPATH=$(pwd)/src:$PYTHONPATH; python -m unittest discover -t . -s test/extra -p '*_extratest.py' - - # ==== create necessary folders ==== - - mkdir -p $(pwd)/newt_pkg/apps/transcoder/bin - - mkdir -p $(pwd)/newt_pkg/apps/transcoder/lib/pkgconfig - - mkdir -p $(pwd)/newt_pkg/usr/local/lib/ - - mkdir -p $(pwd)/newt_pkg/usr/local/include/ - - mkdir -p $(pwd)/newt_pkg/usr/local/share/model - - # ==== copy necessary folders/files ==== - - # ==== copy libvmaf files ==== - - cp $(pwd)/wrapper/libvmaf.pc $(pwd)/newt_pkg/apps/transcoder/lib/pkgconfig - - cp $(pwd)/wrapper/libvmaf.a $(pwd)/newt_pkg/usr/local/lib - - cp $(pwd)/wrapper/src/libvmaf.h $(pwd)/newt_pkg/usr/local/include - - # ==== copy model files to: /usr/local/share/model ==== - - cp -r $(pwd)/model/* $(pwd)/newt_pkg/usr/local/share/model - -package-root: "newt_pkg" diff --git a/feature/src/common/frame.c b/feature/src/common/frame.c index 5b92b5ad0..39691d6dd 100644 --- a/feature/src/common/frame.c +++ b/feature/src/common/frame.c @@ -126,6 +126,9 @@ int read_frame(float *ref_data, float *dis_data, float *temp_data, int stride_by goto fail_or_end; } + fprintf(stderr, "Frame: %d/%d\r", completed_frames++, user_data->num_frames); + + fail_or_end: return ret; } diff --git a/python/src/vmaf/__init__.py b/python/src/vmaf/__init__.py index 1116127cf..12056d7de 100644 --- a/python/src/vmaf/__init__.py +++ b/python/src/vmaf/__init__.py @@ -163,7 +163,7 @@ def call_vifdiff_feature(yuv_type, ref_path, dis_path, w, h, log_file_path, logg @staticmethod def call_vmafossexec(fmt, w, h, ref_path, dis_path, model, log_file_path, disable_clip_score, enable_transform_score, phone_model, disable_avx, n_thread, n_subsample, - psnr, ssim, ms_ssim, ci, exe=None, logger=None, additional_models=None): + psnr, ssim, ms_ssim, ci, exe=None, logger=None): if exe is None: exe = required(ExternalProgram.vmafossexec) @@ -194,8 +194,6 @@ def call_vmafossexec(fmt, w, h, ref_path, dis_path, model, log_file_path, disabl vmafossexec_cmd += ' --ms-ssim' if ci: vmafossexec_cmd += ' --ci' - if additional_models is not None: - vmafossexec_cmd += ' --additional-models ' + additional_models if logger: logger.info(vmafossexec_cmd) run_process(vmafossexec_cmd, shell=True) diff --git a/python/src/vmaf/core/executor.py b/python/src/vmaf/core/executor.py index eacbbf6db..88ce69df0 100644 --- a/python/src/vmaf/core/executor.py +++ b/python/src/vmaf/core/executor.py @@ -30,9 +30,6 @@ class Executor(TypeVersionEnabled): __metaclass__ = ABCMeta - # if optional dict is too long, executor_id needs to be trimmed - MAX_CHARS_EX_ID_OPT_DICT = 10 - @abstractmethod def _generate_result(self, asset): raise NotImplementedError @@ -83,7 +80,7 @@ def executor_id(self): if self.optional_dict is not None and len(self.optional_dict) > 0: # include optional_dict info in executor_id for result store, # as parameters in optional_dict will impact result - executor_id_ += '_{}'.format(get_normalized_string_from_dict(self.optional_dict))[0:self.MAX_CHARS_EX_ID_OPT_DICT] + executor_id_ += '_{}'.format(get_normalized_string_from_dict(self.optional_dict)) return executor_id_ def run(self, **kwargs): diff --git a/python/src/vmaf/core/quality_runner.py b/python/src/vmaf/core/quality_runner.py index ce3a74246..ddec96c63 100644 --- a/python/src/vmaf/core/quality_runner.py +++ b/python/src/vmaf/core/quality_runner.py @@ -675,44 +675,21 @@ def _generate_result(self, asset): else: ci = False - additional_models_dict = self.optional_dict['additional_models'] \ - if self.optional_dict is not None and 'additional_models' in self.optional_dict else None - - additional_models = None - # augment the feature set, if there are any additional models passed in - if additional_models_dict: - self.FEATURES += additional_models_dict.keys() - # augment also with transformed scores - self.FEATURES += map(lambda k: "{k}_transformed".format(k=k), additional_models_dict.keys()) - # get json string for additional models - additional_models = self.get_json_additional_model_string(additional_models_dict) - quality_width, quality_height = asset.quality_width_height - fmt = self._get_workfile_yuv_type(asset) - w = quality_width - h = quality_height - ref_path = asset.ref_workfile_path - dis_path = asset.dis_workfile_path - model = model_filepath - exe = self._get_exec() + fmt=self._get_workfile_yuv_type(asset) + w=quality_width + h=quality_height + ref_path=asset.ref_workfile_path + dis_path=asset.dis_workfile_path + model=model_filepath + exe=self._get_exec() logger = self.logger ExternalProgramCaller.call_vmafossexec(fmt, w, h, ref_path, dis_path, model, log_file_path, disable_clip_score, enable_transform_score, phone_model, disable_avx, n_thread, n_subsample, - psnr, ssim, ms_ssim, ci, exe, logger, additional_models) - - @staticmethod - def get_json_additional_model_string(d): - """ Returns json string representation with sorted keys for additional models. - get_json_additional_model_string({"model A": "/someA/pthA/forA/A.pkl", "model B": "/someB/pthB/forB/B.pkl"}) - """ - if d: - return "{{{0}}}".format('\\,'.join(map(lambda k: '\\"{k}\\"\\:\\"{v}\\"' - .format(k=k, v=d[k]), sorted(d.keys())))) - else: - return "" + psnr, ssim, ms_ssim, ci, exe, logger) def _get_exec(self): return None # signaling default @@ -728,9 +705,10 @@ def _get_quality_scores(self, asset): # check if vmafossexec returned additional info about the bootstrapped models # bootstrap_model_list_str is a comma-separated string of model names if 'bootstrap_model_list_str' in root.findall('params')[0].attrib: + bootstrap_model_list = [] vmaf_params = root.findall('params')[0].attrib bootstrap_model_list_str = vmaf_params['bootstrap_model_list_str'] - bootstrap_model_list = bootstrap_model_list_str.split(',') if len(bootstrap_model_list_str) > 0 else [] + bootstrap_model_list = bootstrap_model_list_str.split(',') # augment the feature set with bootstrap models self.FEATURES += bootstrap_model_list diff --git a/python/test/lib/libvmaf_libtest.py b/python/test/lib/libvmaf_libtest.py index 932dbfb8c..85ea82379 100644 --- a/python/test/lib/libvmaf_libtest.py +++ b/python/test/lib/libvmaf_libtest.py @@ -9,24 +9,6 @@ __license__ = "Apache, Version 2.0" -def set_default_576_324_videos_for_testing(): - ref_path = VmafConfig.test_resource_path("yuv", "src01_hrc00_576x324.yuv") - dis_path = VmafConfig.test_resource_path("yuv", "src01_hrc01_576x324.yuv") - asset = Asset(dataset="test", content_id=0, asset_id=0, - workdir_root=VmafConfig.workdir_path(), - ref_path=ref_path, - dis_path=dis_path, - asset_dict={'width': 576, 'height': 324}) - - asset_original = Asset(dataset="test", content_id=0, asset_id=1, - workdir_root=VmafConfig.workdir_path(), - ref_path=ref_path, - dis_path=ref_path, - asset_dict={'width': 576, 'height': 324}) - - return ref_path, dis_path, asset, asset_original - - class LibRunner(VmafossExecQualityRunner): TYPE = "TESTLIB" @@ -82,8 +64,8 @@ def test_run_testlib_runner(self): self.assertAlmostEqual(results[0]['TESTLIB_ms_ssim_score'], 0.9632498125, places=4) self.assertAlmostEqual(results[1]['TESTLIB_vif_scale0_score'], 1.0, places=4) - self.assertAlmostEqual(results[1]['TESTLIB_vif_scale1_score'], 0.999999958333, places=4) - self.assertAlmostEqual(results[1]['TESTLIB_vif_scale2_score'], 0.999999416667, places=4) + self.assertAlmostEqual(results[1]['TESTLIB_vif_scale1_score'],0.999999958333, places=4) + self.assertAlmostEqual(results[1]['TESTLIB_vif_scale2_score'],0.999999416667, places=4) self.assertAlmostEqual(results[1]['TESTLIB_vif_scale3_score'], 0.999999208333, places=4) self.assertAlmostEqual(results[1]['TESTLIB_motion2_score'], 3.8953518541666665, places=4) self.assertAlmostEqual(results[1]['TESTLIB_adm2_score'], 1.0, places=4) @@ -92,40 +74,4 @@ def test_run_testlib_runner(self): self.assertAlmostEqual(results[1]['TESTLIB_ms_ssim_score'], 1.0, places=4) self.assertAlmostEqual(results[0]['TESTLIB_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[1]['TESTLIB_score'], 99.946416604585025, places=4) - - def test_run_testlib_runner_with_thread(self): - print 'test on running TESTLIB runner with thread...' - ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing() - - self.runner = LibRunner( - [asset, asset_original], - None, fifo_mode=True, - delete_workdir=True, - result_store=None, - optional_dict={'thread': 3} - ) - self.runner.run() - - results = self.runner.results - - self.assertAlmostEqual(results[0]['TESTLIB_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[1]['TESTLIB_score'], 99.946416604585025, places=4) - - def test_run_testlib_runner_phone_model(self): - print 'test on running TESTLIB runner with phone model...' - ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing() - - self.runner = LibRunner( - [asset, asset_original], - None, fifo_mode=True, - delete_workdir=True, - result_store=None, - optional_dict={'phone_model': True} - ) - self.runner.run() - - results = self.runner.results - - self.assertAlmostEqual(results[0]['TESTLIB_score'], 92.54239166666667, places=3) - self.assertAlmostEqual(results[1]['TESTLIB_score'], 100.0, places=4) + self.assertAlmostEqual(results[1]['TESTLIB_score'],99.946416604585025, places=4) diff --git a/python/test/vmafossexec_test.py b/python/test/vmafossexec_test.py index f436dfe6d..c8fa9114c 100644 --- a/python/test/vmafossexec_test.py +++ b/python/test/vmafossexec_test.py @@ -86,90 +86,7 @@ def test_run_vmafossexec_runner_with_thread(self): results = self.runner.results self.assertAlmostEqual(results[0]['VMAFOSSEXEC_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_score'], 99.946416604585025, places=4) - - def test_run_vmafossexec_runner_with_061_additional_model(self): - print('test on running VMAFOSSEXEC runner with 0.6.1 as additional model...') - ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing() - - self.runner = VmafossExecQualityRunner( - [asset, asset_original], - None, fifo_mode=True, - delete_workdir=True, - result_store=None, - optional_dict={'additional_models': {"some_model": VmafConfig.model_path("vmaf_v0.6.1.pkl")}} - ) - self.runner.run() - - results = self.runner.results - - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_some_model_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_some_model_transformed_score'], 92.54239166666667, places=3) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_score'], 99.946416604585025, places=4) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_some_model_score'], 99.946416604585025, places=4) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_some_model_transformed_score'], 100.0, places=4) - - def test_run_vmafossexec_runner_with_061_additional_models(self): - print('test on running VMAFOSSEXEC runner with 0.6.1 as additional models...') - ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing() - - self.runner = VmafossExecQualityRunner( - [asset, asset_original], - None, fifo_mode=True, - delete_workdir=True, - result_store=None, - optional_dict={'additional_models': {"some_model": VmafConfig.model_path("vmaf_v0.6.1.pkl"), - "other_model": VmafConfig.model_path("vmaf_v0.6.1.pkl")}} - ) - self.runner.run() - - results = self.runner.results - - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_some_model_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_other_model_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_score'], 99.946416604585025, places=4) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_some_model_score'], 99.946416604585025, places=4) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_other_model_score'], 99.946416604585025, places=4) - - def test_run_vmafossexec_runner_with_4k_additional_model(self): - print('test on running VMAFOSSEXEC runner with 4k as additional model...') - ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing() - - self.runner = VmafossExecQualityRunner( - [asset, asset_original], - None, fifo_mode=True, - delete_workdir=True, - result_store=None, - optional_dict={'additional_models': {"four_k": VmafConfig.model_path("vmaf_4k_v0.6.1.pkl")}} - ) - self.runner.run() - - results = self.runner.results - - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_score'], 76.699271272486044, places=3) - self.assertAlmostEqual(results[0]['VMAFOSSEXEC_four_k_score'], 84.98462083333332, places=3) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_score'], 99.946416604585025, places=4) - self.assertAlmostEqual(results[1]['VMAFOSSEXEC_four_k_score'], 100.0, places=4) - - def test_additional_model_json_string(self): - print('test additional model json string creation...') - self.assertEquals(VmafossExecQualityRunner - .get_json_additional_model_string({}), "") - self.assertEquals(VmafossExecQualityRunner - .get_json_additional_model_string({"model A": "/someA/pthA/forA/A.pkl"}), - "{\\\"model A\\\"\\:\\\"/someA/pthA/forA/A.pkl\\\"}") - self.assertEquals(VmafossExecQualityRunner - .get_json_additional_model_string({"model A": "/someA/pthA/forA/A.pkl", - "model B": "/someB/pthB/forB/B.pkl"}), - "{\\\"model A\\\"\\:\\\"/someA/pthA/forA/A.pkl\\\"" - "\\,\\\"model B\\\"\\:\\\"/someB/pthB/forB/B.pkl\\\"}") - self.assertEquals(VmafossExecQualityRunner - .get_json_additional_model_string({"model B": "/someB/pthB/forB/B.pkl", - "model A": "/someA/pthA/forA/A.pkl"}), - "{\\\"model A\\\"\\:\\\"/someA/pthA/forA/A.pkl\\\"" - "\\,\\\"model B\\\"\\:\\\"/someB/pthB/forB/B.pkl\\\"}") + self.assertAlmostEqual(results[1]['VMAFOSSEXEC_score'],99.946416604585025, places=4) def test_run_vmafossexec_runner_with_subsample(self): print('test on running VMAFOSSEXEC runner with subsample...') @@ -460,7 +377,7 @@ def test_run_vmafossexec_runner_with_phone_model(self): None, fifo_mode=False, delete_workdir=True, optional_dict={ - 'phone_model': True, + 'phone_model':True, }, result_store=self.result_store, ) diff --git a/wrapper/src/libvmaf.cpp b/wrapper/src/libvmaf.cpp index 5cb4af6fd..2f2572b59 100644 --- a/wrapper/src/libvmaf.cpp +++ b/wrapper/src/libvmaf.cpp @@ -143,7 +143,6 @@ void StatVector::append(double e) { l.push_back(e); } - double StatVector::at(size_t idx) { return l.at(idx); @@ -230,19 +229,45 @@ extern "C" { enum vmaf_cpu cpu; // global - int compute_vmaf(double* vmaf_score, int(*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride_byte, void *user_data), - void *user_data, VmafContext *vmafContext) + int compute_vmaf(double* vmaf_score, char* fmt, int width, int height, int(*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride_byte, void *user_data), + void *user_data, char *model_path, char *log_path, char *log_fmt, int disable_clip, int disable_avx, int enable_transform, int phone_model, int do_psnr, + int do_ssim, int do_ms_ssim, char *pool_method, int n_thread, int n_subsample, int enable_conf_interval) { + bool d_c = false; + bool d_a = false; + bool e_t = false; + bool d_p = false; + bool d_s = false; + bool d_m_s = false; + + if (enable_transform || phone_model) { + e_t = true; + } + if (disable_clip) { + d_c = true; + } + if (disable_avx) { + d_a = true; + } + if (do_psnr) { + d_p = true; + } + if (do_ssim) { + d_s = true; + } + if (do_ms_ssim) { + d_m_s = true; + } cpu = cpu_autodetect(); - if (vmafContext->disable_avx) + if (disable_avx) { cpu = VMAF_CPU_NONE; } try { - double score = RunVmaf(read_frame, user_data, vmafContext); + double score = RunVmaf(fmt, width, height, read_frame, user_data, model_path, log_path, log_fmt, d_c, e_t, d_p, d_s, d_m_s, pool_method, n_thread, n_subsample, enable_conf_interval); *vmaf_score = score; return 0; } diff --git a/wrapper/src/libvmaf.h b/wrapper/src/libvmaf.h index 58c6787ee..dbe96c945 100644 --- a/wrapper/src/libvmaf.h +++ b/wrapper/src/libvmaf.h @@ -32,32 +32,9 @@ extern "C" { #endif -typedef struct { - - int width; - int height; - char *format; - char *model_path; - char *additional_model_paths; - char *log_path; - char *log_fmt; - - int n_thread; - int n_subsample; - char *pool_method; - int disable_clip; - int disable_avx; - int enable_transform; - int phone_model; - int do_psnr; - int do_ssim; - int do_ms_ssim; - int enable_conf_interval; - -} VmafContext; - -int compute_vmaf(double* vmaf_score, int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride_byte, void *user_data), - void *user_data, VmafContext *vmafContext); +int compute_vmaf(double* vmaf_score, char* fmt, int width, int height, int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride_byte, void *user_data), + void *user_data, char *model_path, char *log_path, char *log_fmt, int disable_clip, int disable_avx, int enable_transform, int phone_model, int do_psnr, + int do_ssim, int do_ms_ssim, char *pool_method, int n_thread, int n_subsample, int enable_conf_interval); #ifdef __cplusplus } @@ -130,7 +107,8 @@ class Result class IVmafQualityRunner { public: virtual Result run(Asset asset, int(*read_frame)(float *ref_data, float *main_data, float *temp_data, - int stride, void *user_data), void *user_data, VmafContext *vmafContext) = 0; + int stride, void *user_data), void *user_data, bool disable_clip, bool enable_transform, + bool do_psnr, bool do_ssim, bool do_ms_ssim, int n_thread, int n_subsample) = 0; virtual ~IVmafQualityRunner() {} }; diff --git a/wrapper/src/main.cpp b/wrapper/src/main.cpp index 6344319a5..855e6a6d0 100644 --- a/wrapper/src/main.cpp +++ b/wrapper/src/main.cpp @@ -106,7 +106,7 @@ void getMemory(int itr_ctr, int state) } #endif -int run_wrapper(char *fmt, int width, int height, char *ref_path, char *dis_path, char *model_path, char *additional_model_paths, +int run_wrapper(char *fmt, int width, int height, char *ref_path, char *dis_path, char *model_path, char *log_path, char *log_fmt, bool disable_clip, bool disable_avx, bool enable_transform, bool phone_model, bool do_psnr, bool do_ssim, bool do_ms_ssim, char *pool_method, int n_thread, int n_subsample, bool enable_conf_interval) { @@ -189,35 +189,10 @@ int run_wrapper(char *fmt, int width, int height, char *ref_path, char *dis_path s->num_frames = -1; } - // initialize context - VmafContext *vmafContext; - vmafContext = (VmafContext *)malloc(sizeof(VmafContext)); - - // fill context with data - vmafContext->format = fmt; - vmafContext->width = width; - vmafContext->height = height; - - vmafContext->model_path = model_path; - vmafContext->additional_model_paths = additional_model_paths; - vmafContext->log_path = log_path; - vmafContext->log_fmt = log_fmt; - vmafContext->disable_clip = disable_clip; - vmafContext->disable_avx = disable_avx; - vmafContext->enable_transform = enable_transform || phone_model; - vmafContext->do_psnr = do_psnr; - vmafContext->do_ssim = do_ssim; - vmafContext->do_ms_ssim = do_ms_ssim; - vmafContext->pool_method = pool_method; - vmafContext->n_thread = n_thread; - vmafContext->n_subsample = n_subsample; - vmafContext->enable_conf_interval = enable_conf_interval; - /* Run VMAF */ - ret = compute_vmaf(&score, read_frame, s, vmafContext); - - // free VMAF context - free(vmafContext); + ret = compute_vmaf(&score, fmt, width, height, read_frame, s, model_path, log_path, log_fmt, + disable_clip, disable_avx, enable_transform, phone_model, do_psnr, do_ssim, + do_ms_ssim, pool_method, n_thread, n_subsample, enable_conf_interval); fail_or_end: if (s->ref_rfile) @@ -243,7 +218,6 @@ int main(int argc, char *argv[]) char* ref_path; char* dis_path; char *model_path; - char *additional_model_paths; char *log_path = NULL; char *log_fmt = NULL; bool disable_clip = false; @@ -388,8 +362,6 @@ int main(int argc, char *argv[]) return -1; } - additional_model_paths = getCmdOption(argv + 7, argv + argc, "--additional-models"); - if (cmdOptionExists(argv + 7, argv + argc, "--ci")) { enable_conf_interval = true; @@ -401,13 +373,13 @@ int main(int argc, char *argv[]) for(itr_ctr=0;itr_ctr<1000;itr_ctr++) { getMemory(itr_ctr,1); - ret = run_wrapper(fmt, width, height, ref_path, dis_path, model_path, additional_model_paths, + ret = run_wrapper(fmt, width, height, ref_path, dis_path, model_path, log_path, log_fmt, disable_clip, disable_avx, enable_transform, phone_model, do_psnr, do_ssim, do_ms_ssim, pool_method, n_thread, n_subsample, enable_conf_interval); getMemory(itr_ctr,2); } #else - return run_wrapper(fmt, width, height, ref_path, dis_path, model_path, additional_model_paths, + return run_wrapper(fmt, width, height, ref_path, dis_path, model_path, log_path, log_fmt, disable_clip, disable_avx, enable_transform, phone_model, do_psnr, do_ssim, do_ms_ssim, pool_method, n_thread, n_subsample, enable_conf_interval); #endif diff --git a/wrapper/src/vmaf.cpp b/wrapper/src/vmaf.cpp index d8eb14ce9..cfeac3e4f 100644 --- a/wrapper/src/vmaf.cpp +++ b/wrapper/src/vmaf.cpp @@ -32,7 +32,6 @@ #include "pugixml/pugixml.hpp" #include "timer.h" #include "jsonprint.h" -#include "jsonreader.h" #include "debug.h" #define VAL_EQUAL_STR(V,S) (Stringize((V)).compare((S))==0) @@ -550,33 +549,12 @@ void VmafQualityRunner::_set_prediction_result( result.set_scores("vmaf", score); } -AdditionalModelStruct _get_additional_model_struct(char *model_paths) -{ - AdditionalModelStruct additional_model_struct; - - // read additional models, if any - if (model_paths != NULL) { - - istringstream is(model_paths); - Val additional_model_path_val; - ReadValFromJSONStream(is, additional_model_path_val); - - for (TableIterator kv_pair(additional_model_path_val); kv_pair(); ) { - additional_model_struct.model_names.push_back(kv_pair.key()); - additional_model_struct.model_paths.push_back(kv_pair.value()); - } - - additional_model_struct.num_models = additional_model_struct.model_names.size(); - - } - return additional_model_struct; -} - Result VmafQualityRunner::run(Asset asset, int (*read_frame)(float *ref_data, float *main_data, float *temp_data, - int stride, void *user_data), void *user_data, VmafContext *vmafContext) + int stride, void *user_data), void *user_data, bool disable_clip, bool enable_transform, + bool do_psnr, bool do_ssim, bool do_ms_ssim, int n_thread, int n_subsample) { - std::unique_ptr model_ptr = _load_model(vmafContext->model_path); + std::unique_ptr model_ptr = _load_model(model_path); LibsvmNusvrTrainTestModel& model = *model_ptr; dbg_printf("Initialize storage arrays...\n"); @@ -619,17 +597,17 @@ Result VmafQualityRunner::run(Asset asset, int (*read_frame)(float *ref_data, fl init_array(&ssim_array, INIT_FRAMES); init_array(&ms_ssim_array, INIT_FRAMES); /* optional output arrays */ - if (vmafContext->do_psnr) { + if (do_psnr) { psnr_array_ptr = &psnr_array; } else { psnr_array_ptr = NULL; } - if (vmafContext->do_ssim) { + if (do_ssim) { ssim_array_ptr = &ssim_array; } else { ssim_array_ptr = NULL; } - if (vmafContext->do_ms_ssim) { + if (do_ms_ssim) { ms_ssim_array_ptr = &ms_ssim_array; } else { ms_ssim_array_ptr = NULL; @@ -643,7 +621,7 @@ Result VmafQualityRunner::run(Asset asset, int (*read_frame)(float *ref_data, fl &vif_den_scale0_array, &vif_num_scale1_array, &vif_den_scale1_array, &vif_num_scale2_array, &vif_den_scale2_array, &vif_num_scale3_array, &vif_den_scale3_array, &vif_array, psnr_array_ptr, ssim_array_ptr, - ms_ssim_array_ptr, errmsg, vmafContext->n_thread, vmafContext->n_subsample); + ms_ssim_array_ptr, errmsg, n_thread, n_subsample); if (ret) { throw VmafException(errmsg); } @@ -705,7 +683,7 @@ Result VmafQualityRunner::run(Asset asset, int (*read_frame)(float *ref_data, fl StatVector adm_scale0, adm_scale1, adm_scale2, adm_scale3; StatVector psnr, ssim, ms_ssim; std::vector predictionStructs; - for (size_t i = 0; i < num_frms; i += vmafContext->n_subsample) { + for (size_t i = 0; i < num_frms; i += n_subsample) { adm2.append( (get_at(&adm_num_array, i) + ADM2_CONSTANT) / (get_at(&adm_den_array, i) + ADM2_CONSTANT)); @@ -750,13 +728,13 @@ Result VmafQualityRunner::run(Asset asset, int (*read_frame)(float *ref_data, fl dbg_printf( "Normalize features, SVM regression, denormalize score, clip...\n"); size_t num_frms_subsampled = 0; - for (size_t i = 0; i < num_frms; i += vmafContext->n_subsample) { + for (size_t i = 0; i < num_frms; i += n_subsample) { num_frms_subsampled++; } _normalize_predict_denormalize_transform_clip(model, num_frms_subsampled, adm2, adm_scale0, adm_scale1, adm_scale2, adm_scale3, motion, vif_scale0, vif_scale1, vif_scale2, vif_scale3, vif, motion2, - vmafContext->enable_transform, vmafContext->disable_clip, predictionStructs); + enable_transform, disable_clip, predictionStructs); Result result { }; result.set_scores("adm2", adm2); @@ -816,53 +794,6 @@ Result VmafQualityRunner::run(Asset asset, int (*read_frame)(float *ref_data, fl _set_prediction_result(predictionStructs, result); - // read additional models, if any - if (vmafContext->additional_model_paths != NULL) { - - AdditionalModelStruct additional_model_struct = _get_additional_model_struct(vmafContext->additional_model_paths); - - int num_additional_models = additional_model_struct.num_models; - - std::vector additional_prediction_struct, additional_prediction_struct_et; - std::unique_ptr additional_model_ptr; - StatVector additional_score, additional_score_et; - std::string additional_model_struct_et_model_name; - - // predict VMAF using additional models (calculate with and without enable_transform) - for (int additional_model_ind = 0; additional_model_ind < num_additional_models; additional_model_ind++) { - - additional_model_ptr = _load_model(additional_model_struct.model_paths.at(additional_model_ind).c_str()); - LibsvmNusvrTrainTestModel& additional_model = *additional_model_ptr; - - _normalize_predict_denormalize_transform_clip(additional_model, num_frms_subsampled, - adm2, adm_scale0, adm_scale1, adm_scale2, adm_scale3, motion, - vif_scale0, vif_scale1, vif_scale2, vif_scale3, vif, motion2, - false, vmafContext->disable_clip, additional_prediction_struct); - - _normalize_predict_denormalize_transform_clip(additional_model, num_frms_subsampled, - adm2, adm_scale0, adm_scale1, adm_scale2, adm_scale3, motion, - vif_scale0, vif_scale1, vif_scale2, vif_scale3, vif, motion2, - true, vmafContext->disable_clip, additional_prediction_struct_et); - - for (size_t frm_ind = 0; frm_ind < predictionStructs.size(); frm_ind++) { - additional_score.append(additional_prediction_struct.at(frm_ind).vmafPrediction[VmafPredictionReturnType::SCORE]); - additional_score_et.append(additional_prediction_struct_et.at(frm_ind).vmafPrediction[VmafPredictionReturnType::SCORE]); - } - - result.set_scores(additional_model_struct.model_names.at(additional_model_ind).c_str(), additional_score); - additional_model_struct_et_model_name = additional_model_struct.model_names.at(additional_model_ind) + "_transformed"; - result.set_scores(additional_model_struct_et_model_name.c_str(), additional_score_et); - - // clean up vectors - additional_score = {}; - additional_score_et = {}; - additional_prediction_struct.clear(); - additional_prediction_struct_et.clear(); - - } - - } - free_array(&adm_num_array); free_array(&adm_den_array); free_array(&adm_num_scale0_array); @@ -1019,42 +950,46 @@ void BootstrapVmafQualityRunner::_set_prediction_result( static const char VMAFOSS_DOC_VERSION[] = "1.3.14"; -double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *user_data), - void *user_data, VmafContext *vmafContext) +double RunVmaf(const char* fmt, int width, int height, + int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *user_data), + void *user_data, const char *model_path, const char *log_path, const char *log_fmt, + bool disable_clip, bool enable_transform, + bool do_psnr, bool do_ssim, bool do_ms_ssim, + const char *pool_method, int n_thread, int n_subsample, bool enable_conf_interval) { printf("Start calculating VMAF score...\n"); - if (vmafContext->width <= 0) + if (width <= 0) { throw VmafException("Invalid width value (must be > 0)"); } - if (vmafContext->height <= 0) + if (height <= 0) { throw VmafException("Invalid height value (must be > 0)"); } - if (vmafContext->n_thread < 0) + if (n_thread < 0) { throw VmafException("Invalid n_thread value (must be >= 0)"); } - - if (vmafContext->n_subsample <= 0) + if (n_subsample <= 0) { throw VmafException("Invalid n_subsample value (must be > 0)"); } - Asset asset(vmafContext->width, vmafContext->height, vmafContext->format); - std::unique_ptr runner_ptr = VmafQualityRunnerFactory::createVmafQualityRunner(vmafContext->model_path, vmafContext->enable_conf_interval); + Asset asset(width, height, fmt); + std::unique_ptr runner_ptr = VmafQualityRunnerFactory::createVmafQualityRunner(model_path, enable_conf_interval); Timer timer; timer.start(); - Result result = runner_ptr->run(asset, read_frame, user_data, vmafContext); + Result result = runner_ptr->run(asset, read_frame, user_data, disable_clip, enable_transform, + do_psnr, do_ssim, do_ms_ssim, n_thread, n_subsample); timer.stop(); - if (vmafContext->pool_method != NULL && (strcmp(vmafContext->pool_method, "min")==0)) + if (pool_method != NULL && (strcmp(pool_method, "min")==0)) { result.setScoreAggregateMethod(ScoreAggregateMethod::MINIMUM); } - else if (vmafContext->pool_method != NULL && (strcmp(vmafContext->pool_method, "harmonic_mean")==0)) + else if (pool_method != NULL && (strcmp(pool_method, "harmonic_mean")==0)) { result.setScoreAggregateMethod(ScoreAggregateMethod::HARMONIC_MEAN); } @@ -1065,7 +1000,7 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ size_t num_frames_subsampled = result.get_scores("vmaf").size(); double aggregate_vmaf = result.get_score("vmaf"); - double exec_fps = (double)num_frames_subsampled * vmafContext->n_subsample / (double)timer.elapsed(); + double exec_fps = (double)num_frames_subsampled * n_subsample / (double)timer.elapsed(); #if TIME_TEST_ENABLE double time_taken = (double)timer.elapsed(); #endif @@ -1091,23 +1026,23 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ if (result.has_scores("ms_ssim")) aggregate_ms_ssim = result.get_score("ms_ssim"); - if (vmafContext->pool_method) + if (pool_method) { - printf("VMAF score (%s) = %f\n", vmafContext->pool_method, aggregate_vmaf); + printf("VMAF score (%s) = %f\n", pool_method, aggregate_vmaf); if (aggregate_bagging) - printf("Bagging score (%s) = %f\n", vmafContext->pool_method, aggregate_bagging); + printf("Bagging score (%s) = %f\n", pool_method, aggregate_bagging); if (aggregate_stddev) - printf("StdDev score (%s) = %f\n", vmafContext->pool_method, aggregate_stddev); + printf("StdDev score (%s) = %f\n", pool_method, aggregate_stddev); if (aggregate_ci95_low) - printf("CI95_low score (%s) = %f\n", vmafContext->pool_method, aggregate_ci95_low); + printf("CI95_low score (%s) = %f\n", pool_method, aggregate_ci95_low); if (aggregate_ci95_high) - printf("CI95_high score (%s) = %f\n", vmafContext->pool_method, aggregate_ci95_high); + printf("CI95_high score (%s) = %f\n", pool_method, aggregate_ci95_high); if (aggregate_psnr) - printf("PSNR score (%s) = %f\n", vmafContext->pool_method, aggregate_psnr); + printf("PSNR score (%s) = %f\n", pool_method, aggregate_psnr); if (aggregate_ssim) - printf("SSIM score (%s) = %f\n", vmafContext->pool_method, aggregate_ssim); + printf("SSIM score (%s) = %f\n", pool_method, aggregate_ssim); if (aggregate_ms_ssim) - printf("MS-SSIM score (%s) = %f\n", vmafContext->pool_method, aggregate_ms_ssim); + printf("MS-SSIM score (%s) = %f\n", pool_method, aggregate_ms_ssim); } else // default { @@ -1128,16 +1063,6 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ printf("MS-SSIM score = %f\n", aggregate_ms_ssim); } - // print out additional models (if any) - if (vmafContext->additional_model_paths != NULL) { - AdditionalModelStruct additional_model_struct = _get_additional_model_struct(vmafContext->additional_model_paths); - for (int additional_model_ind = 0; additional_model_ind < additional_model_struct.num_models; additional_model_ind++) - { - printf("%s score = %f\n", additional_model_struct.model_names.at(additional_model_ind).c_str(), - result.get_score(additional_model_struct.model_names.at(additional_model_ind).c_str())); - } - } - int num_bootstrap_models = 0; std::string bootstrap_model_list_str = ""; @@ -1158,8 +1083,8 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ { bootstrap_model_list_str += "," + result_keys[j]; } - if (vmafContext->pool_method) { - printf("VMAF score (%s), model %s = %f\n", vmafContext->pool_method, to_zero_lead(num_bootstrap_models + 1, BOOTSTRAP_MODEL_NAME_PRECISION).c_str(), result.get_score(result_keys[j])); + if (pool_method) { + printf("VMAF score (%s), model %s = %f\n", pool_method, to_zero_lead(num_bootstrap_models + 1, BOOTSTRAP_MODEL_NAME_PRECISION).c_str(), result.get_score(result_keys[j])); } else { printf("VMAF score, model %s = %f\n", to_zero_lead(num_bootstrap_models + 1, BOOTSTRAP_MODEL_NAME_PRECISION).c_str(), result.get_score(result_keys[j])); @@ -1168,17 +1093,17 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ } } - if (vmafContext->log_path != NULL && vmafContext->log_fmt !=NULL && (strcmp(vmafContext->log_fmt, "json")==0)) + if (log_path != NULL && log_fmt !=NULL && (strcmp(log_fmt, "json")==0)) { /* output to json */ double value; OTab params; - params["model"] = _get_file_name(std::string(vmafContext->model_path)); - params["scaledWidth"] = vmafContext->width; - params["scaledHeight"] = vmafContext->height; - params["subsample"] = vmafContext->n_subsample; + params["model"] = _get_file_name(std::string(model_path)); + params["scaledWidth"] = width; + params["scaledHeight"] = height; + params["subsample"] = n_subsample; params["num_bootstrap_models"] = num_bootstrap_models; params["bootstrap_model_list_str"] = bootstrap_model_list_str; @@ -1192,7 +1117,7 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ for (size_t i_subsampled=0; i_subsampledn_subsample; + frame["frameNum"] = i_subsampled * n_subsample; OTab metrics_scores; for (size_t j=0; jlog_path); + std::ofstream log_file(log_path); JSONPrint(top, log_file, 0, true, 2); log_file.close(); } - else if (vmafContext->log_path != NULL && vmafContext->log_fmt != NULL && (strcmp(vmafContext->log_fmt, "csv") == 0)) + else if (log_path != NULL && log_fmt != NULL && (strcmp(log_fmt, "csv") == 0)) { /* output to csv */ - FILE *csv = fopen(vmafContext->log_path, "wt"); + FILE *csv = fopen(log_path, "wt"); fprintf(csv, "Frame,Width,Height,"); for (size_t j = 0; j < result_keys.size(); j++) { @@ -1235,8 +1160,8 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ fprintf(csv, "\n"); for (size_t i_subsampled = 0; i_subsampledn_subsample; - fprintf(csv, "%d,%d,%d,", frameNum, vmafContext->width, vmafContext->height); + int frameNum = i_subsampled * n_subsample; + fprintf(csv, "%d,%d,%d,", frameNum, width, height); for (size_t j = 0; jlog_path != NULL) + else if (log_path != NULL) { /* output to xml */ @@ -1254,10 +1179,10 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ xml_root.append_attribute("version") = VMAFOSS_DOC_VERSION; auto params_node = xml_root.append_child("params"); - params_node.append_attribute("model") = _get_file_name(std::string(vmafContext->model_path)).c_str(); - params_node.append_attribute("scaledWidth") = vmafContext->width; - params_node.append_attribute("scaledHeight") = vmafContext->height; - params_node.append_attribute("subsample") = vmafContext->n_subsample; + params_node.append_attribute("model") = _get_file_name(std::string(model_path)).c_str(); + params_node.append_attribute("scaledWidth") = width; + params_node.append_attribute("scaledHeight") = height; + params_node.append_attribute("subsample") = n_subsample; params_node.append_attribute("num_bootstrap_models") = num_bootstrap_models; params_node.append_attribute("bootstrap_model_list_str") = bootstrap_model_list_str.c_str(); @@ -1278,8 +1203,8 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ info_node.append_attribute("aggregateSSIM") = aggregate_ssim; if (aggregate_ms_ssim) info_node.append_attribute("aggregateMS_SSIM") = aggregate_ms_ssim; - if (vmafContext->pool_method) - info_node.append_attribute("poolMethod") = vmafContext->pool_method; + if (pool_method) + info_node.append_attribute("poolMethod") = pool_method; info_node.append_attribute("execFps") = exec_fps; #if TIME_TEST_ENABLE info_node.append_attribute("timeTaken") = time_taken; @@ -1289,14 +1214,14 @@ double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_ for (size_t i_subsampled=0; i_subsampledn_subsample; + node.append_attribute("frameNum") = (int)i_subsampled * n_subsample; for (size_t j=0; jlog_path); + xml.save_file(log_path); } return aggregate_vmaf; diff --git a/wrapper/src/vmaf.h b/wrapper/src/vmaf.h index b8f52d344..0bbf882ea 100644 --- a/wrapper/src/vmaf.h +++ b/wrapper/src/vmaf.h @@ -39,8 +39,12 @@ static const std::string BOOSTRAP_VMAF_MODEL_PREFIX = "vmaf_"; -double RunVmaf(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *user_data), - void *user_data, VmafContext *vmafContext); +double RunVmaf(const char* fmt, int width, int height, + int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *user_data), + void *user_data, const char *model_path, const char *log_path, const char *log_fmt, + bool disable_clip, bool enable_transform, + bool do_psnr, bool do_ssim, bool do_ms_ssim, + const char *pool_method, int n_thread, int n_subsample, bool enable_conf_interval); class VmafException: public std::exception { @@ -72,13 +76,6 @@ struct VmafPredictionStruct std::vector vmafMultiModelPrediction; }; -struct AdditionalModelStruct -{ - std::vector model_paths; - std::vector model_names; - int num_models; -}; - class LibsvmNusvrTrainTestModel { public: @@ -125,7 +122,8 @@ class VmafQualityRunner : public IVmafQualityRunner public: VmafQualityRunner(const char *model_path): model_path(model_path) {} virtual Result run(Asset asset, int (*read_frame)(float *ref_data, float *main_data, float *temp_data, - int stride, void *user_data), void *user_data, VmafContext *vmafContext); + int stride, void *user_data), void *user_data, bool disable_clip, bool enable_transform, + bool do_psnr, bool do_ssim, bool do_ms_ssim, int n_thread, int n_subsample); virtual ~VmafQualityRunner() {} protected: static void _transform_value(LibsvmNusvrTrainTestModel& model, double& prediction);