From 6c3779fe9bdb6ff1b3a64cf4a3fa3f6ba3a1d8b9 Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Thu, 15 Feb 2024 12:19:43 +0100 Subject: [PATCH 1/7] added changes to check for excessive limiter usage --- apps/decoder.c | 20 ++- lib_com/options.h | 1 + lib_dec/lib_dec.c | 86 ++++++++--- lib_dec/lib_dec.h | 21 ++- lib_rend/ivas_limiter.c | 22 ++- lib_rend/ivas_stat_rend.h | 7 +- scripts/IvasBuildAndRunChecks.py | 21 ++- scripts/pyivastest/IvasModeAnalyzer.py | 184 +++++++++++++++++++++++- scripts/pyivastest/IvasScriptsCommon.py | 5 + scripts/pyivastest/IvasSvnBuilder.py | 4 +- 10 files changed, 340 insertions(+), 31 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index 0d1c164360..924b79a09e 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -201,9 +201,15 @@ int main( #ifdef NONBE_FIX_922_PRECOMPUTED_HRTF_PROPERTIES IVAS_DEC_HRTF_STATISTICS_HANDLE *hHrtfStatistics = NULL; #endif +#ifdef LIMITER_CHECK + int32_t cnt_frames_limited; + float ratio_frames_limited; + float avg_limiter_gain; + float avg_limiter_gain_in_limited_frames; + float max_limiter_gain; +#endif #ifdef DEBUGGING int32_t noClipping; - int32_t cnt_frames_limited; #ifdef DEBUG_SBA_AUDIO_DUMP int16_t numOutChannels, numTransportChannels, pca_ingest_channels; #endif @@ -870,11 +876,19 @@ int main( goto cleanup; } -#ifdef DEBUGGING +#ifdef LIMITER_CHECK if ( ( cnt_frames_limited = IVAS_DEC_GetCntFramesLimited( hIvasDec ) ) > 0 ) { - fprintf( stdout, "Limiter applied in %d frames.\n\n", cnt_frames_limited ); + fprintf( stdout, "Total frames with Limiter application: %d\n\n", cnt_frames_limited ); + ratio_frames_limited = IVAS_DEC_GetRatioFramesLimited( hIvasDec ); + fprintf( stdout, "Ratio of frames with limiting: %0.2f\n\n", ratio_frames_limited); + IVAS_DEC_GetLimiterGainInfo( hIvasDec, &avg_limiter_gain, &max_limiter_gain, &avg_limiter_gain_in_limited_frames ); + fprintf( stdout, "Average Limiter Gain (dB): %0.2f\n", avg_limiter_gain); + fprintf( stdout, "Average Limiter Gain (limited frames only) (dB): %0.2f\n", avg_limiter_gain_in_limited_frames); + fprintf( stdout, "Max Limiter Gain (dB): %0.2f\n", max_limiter_gain); } +#endif +#ifdef DEBUGGING if ( ( noClipping = IVAS_DEC_GetNoCLipping( hIvasDec ) ) > 0 ) { fprintf( stdout, "Clipping (saturation) detected: %d samples clipped!!!\n\n", noClipping ); diff --git a/lib_com/options.h b/lib_com/options.h index e6eeefe4f4..7260c3fb64 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -150,6 +150,7 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ /*#define SPLIT_REND_WITH_HEAD_ROT */ /* Dlb,FhG: Split Rendering contributions 21 and 35 */ +#define LIMITER_CHECK #define FIX_963_USAN_ERROR /* Eri: Issue 963: USAN error in Stereo CNG, division by zero */ #define FIX_971_LOG2_IDX_GAIN_0 /* VA: prevent -Inf due to log2(ratio==0) */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 94468ef6bf..b4969bb479 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -3308,61 +3308,111 @@ static ivas_error evs_dec_main( return IVAS_ERR_OK; } +#ifdef LIMITER_CHECK -#ifdef DEBUGGING /*---------------------------------------------------------------------* - * IVAS_DEC_GetBer_detect_flag() + * IVAS_DEC_GetCntFramesLimited() * - * return BER_detect flag + * return number of frames where limiter is applied *---------------------------------------------------------------------*/ -bool IVAS_DEC_GetBerDetectFlag( +int32_t IVAS_DEC_GetCntFramesLimited( IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ ) { - if ( hIvasDec->st_ivas->BER_detect == 1 ) + if ( hIvasDec->st_ivas->hLimiter == NULL ) { - return 1; + return 0; } else { - return 0; + return hIvasDec->st_ivas->hLimiter->cnt_frames_limited; } } - /*---------------------------------------------------------------------* - * IVAS_DEC_GetNoCLipping() + * IVAS_DEC_GetRatioFramesLimited() * - * return number of clipped samples + * return number of frames where limiter is applied *---------------------------------------------------------------------*/ -int32_t IVAS_DEC_GetNoCLipping( +float IVAS_DEC_GetRatioFramesLimited( IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ ) { - return hIvasDec->st_ivas->noClipping; + if ( hIvasDec->st_ivas->hLimiter == NULL ) + { + return 0; + } + else + { + return hIvasDec->st_ivas->hLimiter->frames_limited_avg; + } } - /*---------------------------------------------------------------------* - * IVAS_DEC_GetCntFramesLimited() + * IVAS_DEC_GetRatioFramesLimited() * * return number of frames where limiter is applied *---------------------------------------------------------------------*/ -int32_t IVAS_DEC_GetCntFramesLimited( - IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ +void IVAS_DEC_GetLimiterGainInfo( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + float *gain_avg, + float *gain_max, + float *gain_avg_in_limited_frames ) { if ( hIvasDec->st_ivas->hLimiter == NULL ) { - return 0; + *gain_avg = 0.0f; + *gain_max = 0.0f; + *gain_avg_in_limited_frames = 0.0f; } else { - return hIvasDec->st_ivas->hLimiter->cnt_frames_limited; + *gain_avg = hIvasDec->st_ivas->hLimiter->gain_avg; + *gain_max = 20*log10f(1.0f/(hIvasDec->st_ivas->hLimiter->gain_max + EPSILON)); + *gain_avg_in_limited_frames = hIvasDec->st_ivas->hLimiter->gain_avg_in_limited_frames; + } + return; +} +#endif + + +#ifdef DEBUGGING +/*---------------------------------------------------------------------* + * IVAS_DEC_GetBer_detect_flag() + * + * return BER_detect flag + *---------------------------------------------------------------------*/ + +bool IVAS_DEC_GetBerDetectFlag( + IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ +) +{ + if ( hIvasDec->st_ivas->BER_detect == 1 ) + { + return 1; } + else + { + return 0; + } +} + + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetNoCLipping() + * + * return number of clipped samples + *---------------------------------------------------------------------*/ + +int32_t IVAS_DEC_GetNoCLipping( + IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ +) +{ + return hIvasDec->st_ivas->noClipping; } diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index f913d20913..0ae53f9827 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -342,16 +342,29 @@ ivas_error IVAS_DEC_GetRenderFramesizeMs( uint32_t *render_framesize /* o : render framesize in samples */ ); -#ifdef DEBUGGING -bool IVAS_DEC_GetBerDetectFlag( +#ifdef LIMITER_CHECK +int32_t IVAS_DEC_GetCntFramesLimited( IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ ); -int32_t IVAS_DEC_GetNoCLipping( +float IVAS_DEC_GetRatioFramesLimited( + IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ +); + +void IVAS_DEC_GetLimiterGainInfo( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + float *gain_avg, + float *gain_max, + float *gain_avg_in_limited_frames +); +#endif + +#ifdef DEBUGGING +bool IVAS_DEC_GetBerDetectFlag( IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ ); -int32_t IVAS_DEC_GetCntFramesLimited( +int32_t IVAS_DEC_GetNoCLipping( IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ ); diff --git a/lib_rend/ivas_limiter.c b/lib_rend/ivas_limiter.c index da214e568a..5f9a97dc8f 100644 --- a/lib_rend/ivas_limiter.c +++ b/lib_rend/ivas_limiter.c @@ -132,8 +132,13 @@ ivas_error ivas_limiter_open( hLimiter->release_heuristic = 0.f; hLimiter->attack_constant = powf( 0.01f, 1.0f / ( IVAS_LIMITER_ATTACK_SECONDS * sampling_rate ) ); hLimiter->strong_saturation_count = 0; -#ifdef DEBUGGING +#ifdef LIMITER_CHECK hLimiter->cnt_frames_limited = 0; + hLimiter->cnt_frames = 0; + hLimiter->gain_avg = 0.0f; + hLimiter->frames_limited_avg = 0.0f; + hLimiter->gain_avg_in_limited_frames = 0.0f; + hLimiter->gain_max=1.0f; #endif for ( i = 0; i < max_num_channels; ++i ) @@ -294,7 +299,7 @@ void limiter_process( * ^ * React faster when release time should be increased */ -#ifdef DEBUGGING +#ifdef LIMITER_CHECK if ( max_val > threshold ) { hLimiter->cnt_frames_limited++; @@ -379,6 +384,19 @@ void limiter_process( /* Save last gain and release heuristic values for next frame */ hLimiter->gain = gain; hLimiter->release_heuristic = releaseHeuristic; +#ifdef LIMITER_CHECK + hLimiter->cnt_frames++; + hLimiter->frames_limited_avg = (float)hLimiter->cnt_frames_limited/(float)hLimiter->cnt_frames; + hLimiter->gain_avg = hLimiter->gain_avg + (20*log10f(1.0f/(hLimiter->gain + EPSILON))-hLimiter->gain_avg)/(float)hLimiter->cnt_frames; + if ( max_val > threshold ) + { + hLimiter->gain_avg_in_limited_frames = hLimiter->gain_avg_in_limited_frames + (20*log10f(1.0f/(hLimiter->gain + EPSILON))-hLimiter->gain_avg_in_limited_frames)/(float)hLimiter->cnt_frames_limited; + } + if ( hLimiter->gain_max > hLimiter->gain ) + { + hLimiter->gain_max = hLimiter->gain; + } +#endif return; } diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 47328d279d..c6c90663ef 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1540,8 +1540,13 @@ typedef struct float release_heuristic; float attack_constant; int16_t strong_saturation_count; -#ifdef DEBUGGING +#ifdef LIMITER_CHECK int32_t cnt_frames_limited; /* counter of frames in which the limiter is applied */ + int32_t cnt_frames; + float frames_limited_avg; + float gain_avg; + float gain_avg_in_limited_frames; + float gain_max; #endif } IVAS_LIMITER, *IVAS_LIMITER_HANDLE; diff --git a/scripts/IvasBuildAndRunChecks.py b/scripts/IvasBuildAndRunChecks.py index ac0b142777..9d91900332 100755 --- a/scripts/IvasBuildAndRunChecks.py +++ b/scripts/IvasBuildAndRunChecks.py @@ -52,7 +52,7 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): nargs="*", default="all", help="List of checks to run, default all", - choices=["all", "CLANG1", "CLANG2", "CLANG3", "VALGRIND", "COMPLEXITY"], + choices=["all", "CLANG1", "CLANG2", "CLANG3", "VALGRIND", "COMPLEXITY", "LIMITER"], ) self.parser.add_argument( "--srcdir", @@ -95,6 +95,11 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): "--usan_supp_file", help="suppression file for undef behaviour sanitizer", default=None, ) + self.parser.add_argument( + "--create_limiter_info", + help="create limiter info with the given prefix", + default="", + ) def run(self): @@ -205,6 +210,20 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): self.args["create_complexity_tables"] ) + if "LIMITER" in checks and self.args["create_limiter_info"]: + cmd = ["git", "rev-parse", "HEAD"] + commit_hash = subprocess.run(cmd, capture_output=True).stdout.decode("utf8") + limiter_analyzer = br.build_and_run_dict["LIMITER"]["analyzer"] + if self.args["formats"]: + limiter_analyzer.set_format_select_list(self.args["formats"]) + if self.args["oc_dict"]: + for ivas_format in self.args["formats"]: + limiter_analyzer.set_format_output_config( + ivas_format, self.args["oc_dict"] + ) + limiter_analyzer.ls_modes() + limiter_analyzer.write_limiter_html_file(self.args["create_limiter_info"], commit_hash) + returncode = 0 for check, ret_val in zip(checks, checks_ret_val): runner = br.build_and_run_dict[check]["runner"] diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index 9f52a90636..48b056e0a0 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -41,7 +41,49 @@ from pyivastest.IvasModeCollector import IvasModeCollector from pyivastest.constants import LOG_FILE_EXT from pyivastest.IvasBaseClass import IvasBaseClass - +LIMITER_RESULTS = { + "ABSLIMITEDFRAMES": { + "keyword": "Total frames with Limiter application:", + "number_format": "{:.0f}", + "position": 0, + "keyword_suffix": False, + "strip_suffix": False, + "fail_threshold": 1000000000 + }, + "RATIOLIMITEDFRAMES": { + "keyword": "Ratio of frames with limiting:", + "number_format": "{:.5g}", + "position": 0, + "keyword_suffix": False, + "strip_suffix": False, + "fail_threshold": 0.05 + }, + "AVGLIMITERGAIN": { + "keyword": "Average Limiter Gain (dB):", + "number_format": "{:.5g}", + "position": 0, + "keyword_suffix": False, + "strip_suffix": False, + "fail_threshold": 1 + }, + "AVGLIMITERGAINLIMITEDFRAMES": { + "keyword": "Average Limiter Gain (limited frames only) (dB):", + "number_format": "{:.5g}", + "position": 0, + "keyword_suffix": False, + "strip_suffix": False, + "fail_threshold": 2 + }, + "MAXLIMITERGAIN": { + "keyword": "Max Limiter Gain (dB):", + "number_format": "{:.5g}", + "position": 0, + "max_or_add": "max", + "keyword_suffix": False, + "strip_suffix": False, + "fail_threshold": 5 + }, +} INSTRUMENTED_RESULTS = { "WMOPS": { "keyword": "total", @@ -121,6 +163,15 @@ body { table, th, td { border: 1px solid black; } +td.pass { + background-color: green; + text-color:white; +} +td.fail { + background-color: red; + text-color: white; + font-weight: bold; +} table { width: 80%; border-collapse: collapse; @@ -547,6 +598,47 @@ class IvasModeAnalyzer(IvasModeCollector): result_table.append(result_line) return result_table + def get_limiter_table( + self + ): + """ + + Parameters + ---------- + + Returns + ------- + + """ + self.select_logs() + sorted_modes = self.sort_log_modes() + + # build first line of the table + result_table = [["mode", "item"]] + for lim_result in LIMITER_RESULTS.keys(): + result_table[0].append(lim_result) + + for mode in sorted_modes: # sorted(self.selected_logs.keys()): + formatted_name = self.selected_logs[mode]["table_name"] + # enc or common only, we do not collect dec values... + + for oc in self.selected_logs[mode]["oc_list"]: + formatted_name_oc = formatted_name + " to " + oc + for item in self.selected_logs[mode]["items"]: + result_line = [formatted_name_oc, item] + if oc in self.selected_logs[mode]["items"][item]["dec"]: + dec_log_name = self.get_dec_log_file_name(item, mode, oc) + for lim_result in LIMITER_RESULTS.keys(): + result_line.append( + self.get_log_value_from_file( + dec_log_name, + LIMITER_RESULTS[lim_result]['keyword'], + LIMITER_RESULTS[lim_result]['position'], + strip_suffix=LIMITER_RESULTS[lim_result]['strip_suffix'], + )) + result_table.append(result_line) + return result_table + @staticmethod def parse_valgrind_log(filename): """ @@ -1038,6 +1130,96 @@ class IvasModeAnalyzer(IvasModeCollector): for line in page: f.write(line) + def write_limiter_html_file(self, basefilename, revision): + + # create header for table + hdr_tmpl = "{}" + tbl_cell = "{}" + tbl_cell_pass = "{}" + tbl_cell_fail = "{}" + tbl_row = "\n{}\n" + # write decoder command line + upload_location = os.environ.get("UPLOAD_LOCATION", None) + if upload_location is not None: + # environment variable is given, add check subdir + upload_location_logs = upload_location + "/" + self.check + "/logs" + upload_location_fer = upload_location + else: + # use current working copy dir to make links work also on local machines + upload_location_logs = self.dir + "/logs" + upload_location_fer = None + + bs_processing_html="" + if self.global_bitstream_processing is not None: + for processing in self.global_bitstream_processing["proc_chain"]: + if "-fer" in processing: + # fer file is the 5th argument in the processing command + fer_file = processing[4] + if upload_location_fer is not None: + fer_file_url = "{}/{}".format( + upload_location_fer, os.path.basename(fer_file) + ) + fer_file_link = "{}".format( + fer_file_url, os.path.basename(fer_file) + ) + else: + fer_file_link = os.path.basename(fer_file) + bs_processing_html += f"FER file: {fer_file_link}\n" + elif "networkSimulator_g192" in processing: + # fer file is the 1st argument in the processing command + jbm_file = processing[1] + if upload_location_fer is not None: + jbm_file_url = "{}/{}".format( + upload_location_fer, os.path.basename(jbm_file) + ) + jbm_file_link = "{}".format( + jbm_file_url, os.path.basename(jbm_file) + ) + else: + jbm_file_link = os.path.basename(jbm_file) + bs_processing_html += f"JBM file: {jbm_file_link}\n" + + limiter_table = self.get_limiter_table() + columns = ["Mode", "Item"] + html_table=list() + limiter_keys = limiter_table[0][2:] + for lim_key in limiter_keys: + columns.append(LIMITER_RESULTS[lim_key]["keyword"]) + tbl_hdr = "\n".join([hdr_tmpl.format(elem) for elem in columns]) + html_table.insert(0, "\n" + tbl_hdr + "\n") + for row_data in limiter_table[1:]: + # first two are mode, item, format normally + row_html = [tbl_cell.format(elem) for elem in row_data[0:2]] + limiter_data = row_data[2:] + row_fail = False + for col_idx in range(len(limiter_data)): + value = limiter_data[col_idx] + fail = value > LIMITER_RESULTS[limiter_keys[col_idx]]["fail_threshold"] + if fail is True: + row_html.append( + tbl_cell_fail.format(LIMITER_RESULTS[limiter_keys[col_idx]]["number_format"].format(value))) + row_fail = True + else: + row_html.append( + tbl_cell_pass.format(LIMITER_RESULTS[limiter_keys[col_idx]]["number_format"].format(value))) + if row_fail is True: + html_table.append("\n".join(row_html)) + # assemble page + page_tmpl = "{}\n\n\n{}\n{}\n{}\n\n{}\n" + table_tmpl = "\n{}\n
" + title_tmpl = "Limiter report" + fname_tmpl = "{}_{}.html" + body_tmpl = "

{} report on revision {}

{}\n{}" + + table = table_tmpl.format("\n".join(html_table)) + title = title_tmpl.format() + body = body_tmpl.format("Limiter", revision, table,bs_processing_html) + page = page_tmpl.format(HTML_DOCTYPE, HTML_META, title, HTML_STYLE, body) + fname = fname_tmpl.format(basefilename, "limiter") + with open(fname, "w") as f: + for line in page: + f.write(line) + @staticmethod def get_snr_report(file_name): SNR_report = {} diff --git a/scripts/pyivastest/IvasScriptsCommon.py b/scripts/pyivastest/IvasScriptsCommon.py index 02cf6a6b8b..a9667e1886 100644 --- a/scripts/pyivastest/IvasScriptsCommon.py +++ b/scripts/pyivastest/IvasScriptsCommon.py @@ -710,7 +710,11 @@ def runner_setup(runner, args): def analyzer_setup(analyzer, args): bs_proc_chain = {} + if args["enc_options_list"]: + analyzer.encoder_cmdline_options = args["enc_options_list"] + if args["dec_options_list"]: + analyzer.decoder_cmdline_options = args["dec_options_list"] if "fer_file" in args.keys() or "ber_file" in args.keys(): # assert that the eid-xor tool is there eid_xor_path = os.path.join(analyzer.config["utilPath"], "eid-xor") @@ -799,6 +803,7 @@ def analyzer_setup(analyzer, args): analyzer.filter = args["filter_regex"] + if __name__ == "__main__": test_parser = IvasScriptArgParser() args = test_parser.parse_args() diff --git a/scripts/pyivastest/IvasSvnBuilder.py b/scripts/pyivastest/IvasSvnBuilder.py index e57eb210da..be9966e58c 100644 --- a/scripts/pyivastest/IvasSvnBuilder.py +++ b/scripts/pyivastest/IvasSvnBuilder.py @@ -350,7 +350,7 @@ class IvasBuilder(IvasBaseClass): clean_cmd = ["make", "-C", make_dir, "clean"] build_log.write(" ".join(clean_cmd)) build_log.write("\n") - make_cmd = ["make", "-C", make_dir] + make_options + make_cmd = ["make", "-j","-C", make_dir] + make_options build_result = subprocess.run( clean_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) @@ -1219,6 +1219,8 @@ class IvasBuilderAndRunner(IvasBaseClass): "--show-reachable=yes", "--num-callers=20", ] + elif check == "LIMITER": + defines_to_enable_check.extend(["LIMITER_CHECK"]) self.add_build_and_run_config( check, -- GitLab From e913a1bb9504d77d3622356fcf1374dc7d8294af Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Fri, 16 Feb 2024 09:13:11 +0100 Subject: [PATCH 2/7] better handling of limiter results --- scripts/pyivastest/IvasModeAnalyzer.py | 50 +++++++++++++++++++------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index 48b056e0a0..81548ddf1d 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -189,6 +189,11 @@ h1 { margin-top: 1em; margin-bottom: 1em; } +h2 { + text-align: center; + margin-top: 1em; + margin-bottom: 1em; +} """ @@ -228,6 +233,8 @@ class IvasModeAnalyzer(IvasModeCollector): self.analyze_encoder = True self.analyze_decoder = True self.html_table = None + self.encoder_cmdline_options = None + self.decoder_cmdline_options = None def ls_modes(self): """ """ @@ -273,7 +280,10 @@ class IvasModeAnalyzer(IvasModeCollector): oc = os.path.splitext(f)[1][1:] f = os.path.splitext(os.path.splitext(f)[0])[0] item, suffices = f.split("".join(["_", mode])) - if item not in self.available_logs[mode]["items"]: + if ( + item not in self.available_logs[mode]["items"] + and oc in self.flat_mode_list[mode]['cmd']['dec'] + ): self.available_logs[mode]["items"].update( {item: {"enc": False, "dec": [oc]}} ) @@ -283,11 +293,15 @@ class IvasModeAnalyzer(IvasModeCollector): oc not in self.available_logs[mode]["items"][item]["dec"] and oc != "proc" + and oc in self.flat_mode_list[mode]['cmd']['dec'] ): self.available_logs[mode]["items"][item]["dec"].append( oc ) - if oc not in self.available_logs[mode]["oc_list"]: + if ( + oc not in self.available_logs[mode]["oc_list"] + and oc in self.flat_mode_list[mode]['cmd']['dec'] + ): self.available_logs[mode]["oc_list"].append(oc) @staticmethod @@ -1137,7 +1151,8 @@ class IvasModeAnalyzer(IvasModeCollector): tbl_cell = "{}" tbl_cell_pass = "{}" tbl_cell_fail = "{}" - tbl_row = "\n{}\n" + tbl_row = "\n\n{}\n\n" + table_tmpl = "\n{}\n
" # write decoder command line upload_location = os.environ.get("UPLOAD_LOCATION", None) if upload_location is not None: @@ -1149,7 +1164,13 @@ class IvasModeAnalyzer(IvasModeCollector): upload_location_logs = self.dir + "/logs" upload_location_fer = None - bs_processing_html="" + info_html_tmpl = "\n

Additional information

\n{}\n

Results

\n" + + info_table = list() + if self.decoder_cmdline_options is not None: + cmdlineoptions = " ".join(self.decoder_cmdline_options) + info_table.append(tbl_row.format("\n".join([tbl_cell.format("Additional Decoder command line options:"), + tbl_cell.format(cmdlineoptions)]))) if self.global_bitstream_processing is not None: for processing in self.global_bitstream_processing["proc_chain"]: if "-fer" in processing: @@ -1164,7 +1185,8 @@ class IvasModeAnalyzer(IvasModeCollector): ) else: fer_file_link = os.path.basename(fer_file) - bs_processing_html += f"FER file: {fer_file_link}\n" + info_table.append(tbl_row.format("\n".join([tbl_cell.format("FER file:"), + tbl_cell.format(fer_file_link)]))) elif "networkSimulator_g192" in processing: # fer file is the 1st argument in the processing command jbm_file = processing[1] @@ -1177,8 +1199,11 @@ class IvasModeAnalyzer(IvasModeCollector): ) else: jbm_file_link = os.path.basename(jbm_file) - bs_processing_html += f"JBM file: {jbm_file_link}\n" + info_table.append(tbl_row.format("\n".join([tbl_cell.format("JBM file:"), + tbl_cell.format(jbm_file_link)]))) + if info_table: + info_html=info_html_tmpl.format(table_tmpl.format("\n".join(info_table))) limiter_table = self.get_limiter_table() columns = ["Mode", "Item"] html_table=list() @@ -1203,19 +1228,18 @@ class IvasModeAnalyzer(IvasModeCollector): row_html.append( tbl_cell_pass.format(LIMITER_RESULTS[limiter_keys[col_idx]]["number_format"].format(value))) if row_fail is True: - html_table.append("\n".join(row_html)) + html_table.append(tbl_row.format("\n".join(row_html))) # assemble page page_tmpl = "{}\n\n\n{}\n{}\n{}\n\n{}\n" - table_tmpl = "\n{}\n
" - title_tmpl = "Limiter report" + title_tmpl = "Limiter report ({})" fname_tmpl = "{}_{}.html" - body_tmpl = "

{} report on revision {}

{}\n{}" + body_tmpl = "

{} report ({}) on revision {}

{}\n{}" table = table_tmpl.format("\n".join(html_table)) - title = title_tmpl.format() - body = body_tmpl.format("Limiter", revision, table,bs_processing_html) + title = title_tmpl.format(" ".join(basefilename.split("_"))) + body = body_tmpl.format("Limiter", " ".join(basefilename.split("_")), revision, info_html, table) page = page_tmpl.format(HTML_DOCTYPE, HTML_META, title, HTML_STYLE, body) - fname = fname_tmpl.format(basefilename, "limiter") + fname = fname_tmpl.format("limiter", basefilename) with open(fname, "w") as f: for line in page: f.write(line) -- GitLab From 2c67d0b4ceb619ffdcf01bb5ab9c84745525a910 Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Fri, 16 Feb 2024 11:11:52 +0100 Subject: [PATCH 3/7] only write limiter table file if at least one condition failed --- scripts/pyivastest/IvasModeAnalyzer.py | 31 ++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index 0fb60766e1..9e6e8ca535 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -1224,6 +1224,7 @@ class IvasModeAnalyzer(IvasModeCollector): columns.append(LIMITER_RESULTS[lim_key]["keyword"]) tbl_hdr = "\n".join([hdr_tmpl.format(elem) for elem in columns]) html_table.insert(0, "\n" + tbl_hdr + "\n") + have_fail = FALSE for row_data in limiter_table[1:]: # first two are mode, item, format normally row_html = [tbl_cell.format(elem) for elem in row_data[0:2]] @@ -1241,20 +1242,22 @@ class IvasModeAnalyzer(IvasModeCollector): tbl_cell_pass.format(LIMITER_RESULTS[limiter_keys[col_idx]]["number_format"].format(value))) if row_fail is True: html_table.append(tbl_row.format("\n".join(row_html))) - # assemble page - page_tmpl = "{}\n\n\n{}\n{}\n{}\n\n{}\n" - title_tmpl = "Limiter report ({})" - fname_tmpl = "{}_{}.html" - body_tmpl = "

{} report ({}) on revision {}

{}\n{}" - - table = table_tmpl.format("\n".join(html_table)) - title = title_tmpl.format(" ".join(basefilename.split("_"))) - body = body_tmpl.format("Limiter", " ".join(basefilename.split("_")), revision, info_html, table) - page = page_tmpl.format(HTML_DOCTYPE, HTML_META, title, HTML_STYLE, body) - fname = fname_tmpl.format("limiter", basefilename) - with open(fname, "w") as f: - for line in page: - f.write(line) + have_fail = True + # assemble page if something failed + if have_fail is True: + page_tmpl = "{}\n\n\n{}\n{}\n{}\n\n{}\n" + title_tmpl = "Limiter report ({})" + fname_tmpl = "{}_{}.html" + body_tmpl = "

{} report ({}) on revision {}

{}\n{}" + + table = table_tmpl.format("\n".join(html_table)) + title = title_tmpl.format(" ".join(basefilename.split("_"))) + body = body_tmpl.format("Limiter", " ".join(basefilename.split("_")), revision, info_html, table) + page = page_tmpl.format(HTML_DOCTYPE, HTML_META, title, HTML_STYLE, body) + fname = fname_tmpl.format("limiter", basefilename) + with open(fname, "w") as f: + for line in page: + f.write(line) @staticmethod def get_snr_report(file_name): -- GitLab From 278e234b48c9bdad01b82fe7f18bdaf1663b6736 Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Fri, 16 Feb 2024 12:25:30 +0100 Subject: [PATCH 4/7] fix typi --- scripts/pyivastest/IvasModeAnalyzer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index 9e6e8ca535..f3b018edc2 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -1224,7 +1224,7 @@ class IvasModeAnalyzer(IvasModeCollector): columns.append(LIMITER_RESULTS[lim_key]["keyword"]) tbl_hdr = "\n".join([hdr_tmpl.format(elem) for elem in columns]) html_table.insert(0, "\n" + tbl_hdr + "\n") - have_fail = FALSE + have_fail = False for row_data in limiter_table[1:]: # first two are mode, item, format normally row_html = [tbl_cell.format(elem) for elem in row_data[0:2]] @@ -1239,7 +1239,7 @@ class IvasModeAnalyzer(IvasModeCollector): row_fail = True else: row_html.append( - tbl_cell_pass.format(LIMITER_RESULTS[limiter_keys[col_idx]]["number_format"].format(value))) + tbl_cell_pass.format(LIMITER_Rcd ESULTS[limiter_keys[col_idx]]["number_format"].format(value))) if row_fail is True: html_table.append(tbl_row.format("\n".join(row_html))) have_fail = True -- GitLab From 12d25b3e3b4711cdf63bce1736e262761025f8b5 Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Fri, 16 Feb 2024 12:27:13 +0100 Subject: [PATCH 5/7] fix error --- scripts/pyivastest/IvasModeAnalyzer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index f3b018edc2..ddb2fac81f 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -1239,7 +1239,7 @@ class IvasModeAnalyzer(IvasModeCollector): row_fail = True else: row_html.append( - tbl_cell_pass.format(LIMITER_Rcd ESULTS[limiter_keys[col_idx]]["number_format"].format(value))) + tbl_cell_pass.format(LIMITER_RESULTS[limiter_keys[col_idx]]["number_format"].format(value))) if row_fail is True: html_table.append(tbl_row.format("\n".join(row_html))) have_fail = True -- GitLab From 82c559c3542815589d8fd3b1b38f213fae4fad9e Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Fri, 23 Feb 2024 10:18:40 +0100 Subject: [PATCH 6/7] also write limiter statistics to csv file --- scripts/pyivastest/IvasModeAnalyzer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/pyivastest/IvasModeAnalyzer.py b/scripts/pyivastest/IvasModeAnalyzer.py index ddb2fac81f..f3c3e1b613 100644 --- a/scripts/pyivastest/IvasModeAnalyzer.py +++ b/scripts/pyivastest/IvasModeAnalyzer.py @@ -1199,7 +1199,7 @@ class IvasModeAnalyzer(IvasModeCollector): fer_file_link = os.path.basename(fer_file) info_table.append(tbl_row.format("\n".join([tbl_cell.format("FER file:"), tbl_cell.format(fer_file_link)]))) - elif "networkSimulator_g192" in processing: + elif "networkSimulator_g192" in processing[0]: # fer file is the 1st argument in the processing command jbm_file = processing[1] if upload_location_fer is not None: @@ -1213,10 +1213,11 @@ class IvasModeAnalyzer(IvasModeCollector): jbm_file_link = os.path.basename(jbm_file) info_table.append(tbl_row.format("\n".join([tbl_cell.format("JBM file:"), tbl_cell.format(jbm_file_link)]))) - + info_html="" if info_table: info_html=info_html_tmpl.format(table_tmpl.format("\n".join(info_table))) limiter_table = self.get_limiter_table() + columns = ["Mode", "Item"] html_table=list() limiter_keys = limiter_table[0][2:] @@ -1259,6 +1260,9 @@ class IvasModeAnalyzer(IvasModeCollector): for line in page: f.write(line) + limiter_table=[[str(x) if not isinstance(x,str) else x for x in line] for line in limiter_table] + self.write_csv_file(os.path.realpath(f"limiter_{basefilename}"), limiter_table) + @staticmethod def get_snr_report(file_name): SNR_report = {} -- GitLab From b6e510fcc620d31baeadf74fb037a6852cbe96e0 Mon Sep 17 00:00:00 2001 From: Stefan Bayer Date: Fri, 23 Feb 2024 10:22:10 +0100 Subject: [PATCH 7/7] always print limiter statistics --- apps/decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/decoder.c b/apps/decoder.c index 4f64978fd7..cff06f1a9c 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -894,7 +894,7 @@ int main( } #ifdef LIMITER_CHECK - if ( ( cnt_frames_limited = IVAS_DEC_GetCntFramesLimited( hIvasDec ) ) > 0 ) + if ( ( cnt_frames_limited = IVAS_DEC_GetCntFramesLimited( hIvasDec ) ) >= 0 ) { fprintf( stdout, "Total frames with Limiter application: %d\n\n", cnt_frames_limited ); ratio_frames_limited = IVAS_DEC_GetRatioFramesLimited( hIvasDec ); -- GitLab