From e4a29f041f5513d4731240b7e0944daa6a2d50b3 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Mon, 1 Jun 2026 14:11:11 -0700 Subject: [PATCH 1/5] Fix static analyzer failures in C-only build Add asserts / checks to ensure certain conditions cannot occur --- av2/av2_cx_iface.c | 5 ++++- av2/common/cfl.c | 3 +++ av2/common/convolve.c | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/av2/av2_cx_iface.c b/av2/av2_cx_iface.c index 845d11b06e..95aef2d7b0 100644 --- a/av2/av2_cx_iface.c +++ b/av2/av2_cx_iface.c @@ -2853,15 +2853,18 @@ static avm_codec_err_t encoder_init(avm_codec_ctx_t *ctx) { &priv->cpi, &priv->buffer_pool, &priv->oxcf, &priv->pkt_list.head, priv->frame_stats_buffer, ENCODE_STAGE, *num_lap_buffers, -1, &priv->stats_buf_context); + if (res != AVM_CODEC_OK) return res; // Create another compressor if look ahead is enabled - if (res == AVM_CODEC_OK && *num_lap_buffers) { + if (*num_lap_buffers) { res = create_context_and_bufferpool( &priv->cpi_lap, &priv->buffer_pool_lap, &priv->oxcf, NULL, priv->frame_stats_buffer, LAP_STAGE, *num_lap_buffers, clamp(lap_lag_in_frames, 0, MAX_LAG_BUFFERS), &priv->stats_buf_context); + if (res != AVM_CODEC_OK) return res; } + assert(priv->cpi->common.ibp_directional_weights != NULL); init_ibp_info(priv->cpi->common.ibp_directional_weights); } } diff --git a/av2/common/cfl.c b/av2/common/cfl.c index f04b2246bb..b264a4e2c3 100644 --- a/av2/common/cfl.c +++ b/av2/common/cfl.c @@ -748,6 +748,7 @@ CFL_GET_SUBSAMPLE_COLOCATED_FUNCTION(c) static INLINE av2_cfl_subsample_hbd_fn cfl_subsampling_hbd(TX_SIZE tx_size, int sub_x, int sub_y) { + assert(tx_size < TX_SIZES_ALL); if (sub_x == 1) { if (sub_y == 1) { return av2_cfl_get_luma_subsampling_420_hbd(tx_size); @@ -815,6 +816,7 @@ void cfl_store(MACROBLOCKD *const xd, CFL_CTX *cfl, const uint16_t *input, cfl_luma_subsampling_420_hbd_121_c(input, input_stride, recon_buf_q3, width, height); } else { + assert(tx_size < TX_SIZES_ALL); av2_cfl_get_luma_subsampling_420_hbd_121(tx_size)(input, input_stride, recon_buf_q3); } @@ -833,6 +835,7 @@ void cfl_store(MACROBLOCKD *const xd, CFL_CTX *cfl, const uint16_t *input, cfl_luma_subsampling_420_hbd_colocated_c(input, input_stride, recon_buf_q3, width, height); } else { + assert(tx_size < TX_SIZES_ALL); av2_cfl_get_luma_subsampling_420_hbd_colocated(tx_size)( input, input_stride, recon_buf_q3); } diff --git a/av2/common/convolve.c b/av2/common/convolve.c index e58910aa70..fb8d041682 100644 --- a/av2/common/convolve.c +++ b/av2/common/convolve.c @@ -55,6 +55,7 @@ void av2_highbd_convolve_x_sr_c(const uint16_t *src, int src_stride, const InterpFilterParams *filter_params_x, const int subpel_x_qn, ConvolveParams *conv_params, int bd) { + assert(filter_params_x != NULL); const int fo_horiz = filter_params_x->taps / 2 - 1; const int bits = FILTER_BITS - conv_params->round_0; @@ -82,6 +83,7 @@ void av2_highbd_convolve_y_sr_c(const uint16_t *src, int src_stride, uint16_t *dst, int dst_stride, int w, int h, const InterpFilterParams *filter_params_y, const int subpel_y_qn, int bd) { + assert(filter_params_y != NULL); const int fo_vert = filter_params_y->taps / 2 - 1; // vertical filter const int16_t *y_filter = av2_get_interp_filter_subpel_kernel( From 1ee9c76d7e13d5129064e36d792218322d76eca5 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Mon, 1 Jun 2026 14:56:29 -0700 Subject: [PATCH 2/5] Only enable avmdec_av2_ivf_multithread test when CONFIG_MULTITHREAD is on --- test/avmdec.sh | 6 +++++- test/tools_common.sh | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/test/avmdec.sh b/test/avmdec.sh index 534a88f226..27bc53e6ef 100755 --- a/test/avmdec.sh +++ b/test/avmdec.sh @@ -178,7 +178,6 @@ avmdec_random_access_kf2() { avmdec_tests="avmdec_av2_ivf avmdec_av2_ivf_error_resilient - avmdec_av2_ivf_multithread avmdec_avm_ivf_pipe_input avmdec_av2_obu avmdec_av2_webm @@ -186,4 +185,9 @@ avmdec_tests="avmdec_av2_ivf avmdec_random_access_kf1 avmdec_random_access_kf2" +if [ "$(avm_multithread_available)" = "yes" ]; then + avmdec_tests="${avmdec_tests} + avmdec_av2_ivf_multithread" +fi + run_tests avmdec_verify_environment "${avmdec_tests}" diff --git a/test/tools_common.sh b/test/tools_common.sh index 4b818dbac4..3608a2c022 100755 --- a/test/tools_common.sh +++ b/test/tools_common.sh @@ -197,6 +197,12 @@ av2_encode_available() { [ "$(avm_config_option_enabled CONFIG_AV2_ENCODER)" = "yes" ] && echo yes } +# Echoes yes to stdout when avm_config_option_enabled() reports yes for +# CONFIG_MULTITHREAD. +avm_multithread_available() { + [ "$(avm_config_option_enabled CONFIG_MULTITHREAD)" = "yes" ] && echo yes +} + # Echoes "fast" encode params for use with avmenc. avmenc_encode_test_fast_params() { echo "--cpu-used=5 From e31e13660d0e4746b923847d1bf7c25756136293 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Tue, 2 Jun 2026 14:52:46 -0700 Subject: [PATCH 3/5] When CONFIG_MULTITHREAD=0, force unit tests to use 1 thread. Also, - Remove multi-threaded tests from compilation - Ensure that encoder API doesn't allow specifying more than 1 thread. --- avm_util/avm_thread.h | 5 +++++ test/encode_small_width_height_test.cc | 16 ++++++++++++++++ test/multi_layer_test.cc | 5 +++++ test/ras_frame_pruning_test.cc | 16 ++++++++++++++++ test/test.cmake | 8 ++++++-- 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/avm_util/avm_thread.h b/avm_util/avm_thread.h index 80e8b781ae..441ebeb101 100644 --- a/avm_util/avm_thread.h +++ b/avm_util/avm_thread.h @@ -24,7 +24,12 @@ extern "C" { #endif +#if CONFIG_MULTITHREAD #define MAX_NUM_THREADS 64 +#else +#define MAX_NUM_THREADS 1 +#endif // CONFIG_MULTITHREAD + #if defined(__APPLE__) #define MIN_THREAD_STACK_SIZE (1 << 22) #endif // __APPLE__ diff --git a/test/encode_small_width_height_test.cc b/test/encode_small_width_height_test.cc index bbb78103c2..4bfa555769 100644 --- a/test/encode_small_width_height_test.cc +++ b/test/encode_small_width_height_test.cc @@ -39,7 +39,11 @@ TEST(EncodeSmallWidthHeight, SmallWidthMultiThreaded) { avm_codec_iface_t *iface = avm_codec_av2_cx(); avm_codec_enc_cfg_t cfg; EXPECT_EQ(AVM_CODEC_OK, avm_codec_enc_config_default(iface, &cfg, 0)); +#if CONFIG_MULTITHREAD cfg.g_threads = 2; +#else + cfg.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg.g_w = kWidth; cfg.g_h = kHeight; avm_codec_ctx_t enc; @@ -63,7 +67,11 @@ TEST(EncodeSmallWidthHeight, SmallWidthMultiThreadedSpeed0) { avm_codec_iface_t *iface = avm_codec_av2_cx(); avm_codec_enc_cfg_t cfg; EXPECT_EQ(AVM_CODEC_OK, avm_codec_enc_config_default(iface, &cfg, 0)); +#if CONFIG_MULTITHREAD cfg.g_threads = 2; +#else + cfg.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg.g_w = kWidth; cfg.g_h = kHeight; avm_codec_ctx_t enc; @@ -87,7 +95,11 @@ TEST(EncodeSmallWidthHeight, SmallHeightMultiThreaded) { avm_codec_iface_t *iface = avm_codec_av2_cx(); avm_codec_enc_cfg_t cfg; EXPECT_EQ(AVM_CODEC_OK, avm_codec_enc_config_default(iface, &cfg, 0)); +#if CONFIG_MULTITHREAD cfg.g_threads = 2; +#else + cfg.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg.g_w = kWidth; cfg.g_h = kHeight; avm_codec_ctx_t enc; @@ -111,7 +123,11 @@ TEST(EncodeSmallWidthHeight, SmallHeightMultiThreadedSpeed0) { avm_codec_iface_t *iface = avm_codec_av2_cx(); avm_codec_enc_cfg_t cfg; EXPECT_EQ(AVM_CODEC_OK, avm_codec_enc_config_default(iface, &cfg, 0)); +#if CONFIG_MULTITHREAD cfg.g_threads = 2; +#else + cfg.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg.g_w = kWidth; cfg.g_h = kHeight; avm_codec_ctx_t enc; diff --git a/test/multi_layer_test.cc b/test/multi_layer_test.cc index ae631f22e2..a7a7b73536 100644 --- a/test/multi_layer_test.cc +++ b/test/multi_layer_test.cc @@ -31,7 +31,11 @@ class MultiLayerTest : public ::libavm_test::CodecTestWithParam, cfg_.rc_end_usage = AVM_Q; cfg_.rc_min_quantizer = 210; cfg_.rc_max_quantizer = 210; +#if CONFIG_MULTITHREAD cfg_.g_threads = 2; +#else + cfg_.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg_.g_profile = MAIN_420_10_IP2; cfg_.g_lag_in_frames = 0; cfg_.g_bit_depth = AVM_BITS_8; @@ -51,6 +55,7 @@ class MultiLayerTest : public ::libavm_test::CodecTestWithParam, start_decoding_tl1_ = 0; pyramid_level_one_ = false; key_frame_on_ml_layers_ = 0; + init_flags_ = AVM_CODEC_USE_PER_FRAME_STATS; } int GetNumEmbeddedLayers() override { return num_embedded_layers_; } diff --git a/test/ras_frame_pruning_test.cc b/test/ras_frame_pruning_test.cc index ec340ac098..46a189879f 100644 --- a/test/ras_frame_pruning_test.cc +++ b/test/ras_frame_pruning_test.cc @@ -321,7 +321,11 @@ class MultiLayer2TemporalDecodeBaseOnlyRASPruningTest cfg_.rc_end_usage = AVM_Q; cfg_.rc_min_quantizer = 210; cfg_.rc_max_quantizer = 210; +#if CONFIG_MULTITHREAD cfg_.g_threads = 2; +#else + cfg_.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg_.g_profile = MAIN_420_10_IP2; cfg_.g_lag_in_frames = 0; cfg_.g_bit_depth = AVM_BITS_8; @@ -466,7 +470,11 @@ class MultiLayer3TemporalDecodeBaseOnlyRASPruningTest cfg_.rc_end_usage = AVM_Q; cfg_.rc_min_quantizer = 210; cfg_.rc_max_quantizer = 210; +#if CONFIG_MULTITHREAD cfg_.g_threads = 2; +#else + cfg_.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg_.g_profile = MAIN_420_10_IP2; cfg_.g_lag_in_frames = 0; cfg_.g_bit_depth = AVM_BITS_8; @@ -743,7 +751,11 @@ class MultiLayerTest3Embedded3TemporalDropSL2RASPruningTest cfg_.rc_end_usage = AVM_Q; cfg_.rc_min_quantizer = 210; cfg_.rc_max_quantizer = 210; +#if CONFIG_MULTITHREAD cfg_.g_threads = 2; +#else + cfg_.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg_.g_profile = MAIN_420_10_IP2; cfg_.g_lag_in_frames = 0; cfg_.g_bit_depth = AVM_BITS_8; @@ -933,7 +945,11 @@ class MultiLayerTest2Embedded2TempDropTL1RASPruningTest cfg_.rc_end_usage = AVM_Q; cfg_.rc_min_quantizer = 210; cfg_.rc_max_quantizer = 210; +#if CONFIG_MULTITHREAD cfg_.g_threads = 2; +#else + cfg_.g_threads = 1; +#endif // CONFIG_MULTITHREAD cfg_.g_profile = MAIN_420_10_IP2; cfg_.g_lag_in_frames = 0; cfg_.g_bit_depth = AVM_BITS_8; diff --git a/test/test.cmake b/test/test.cmake index 49c61873c7..3f68ac459f 100644 --- a/test/test.cmake +++ b/test/test.cmake @@ -122,11 +122,9 @@ if(NOT BUILD_SHARED_LIBS) "${AVM_ROOT}/test/brt_test.cc" "${AVM_ROOT}/test/ci_test.cc" "${AVM_ROOT}/test/cnn_test.cc" - "${AVM_ROOT}/test/decode_multithreaded_test.cc" "${AVM_ROOT}/test/divu_small_test.cc" "${AVM_ROOT}/test/dr_prediction_test.cc" "${AVM_ROOT}/test/ec_test.cc" - "${AVM_ROOT}/test/ethread_test.cc" "${AVM_ROOT}/test/fgm_test.cc" "${AVM_ROOT}/test/film_grain_table_test.cc" "${AVM_ROOT}/test/frame_multi_qmatrix_test.cc" @@ -154,6 +152,12 @@ if(NOT BUILD_SHARED_LIBS) "${AVM_ROOT}/test/temporal_filter_test.cc" "${AVM_ROOT}/test/tile_config_test.cc" "${AVM_ROOT}/test/tile_independence_test.cc") + + if(CONFIG_MULTITHREAD) + list(APPEND AVM_UNIT_TEST_COMMON_SOURCES + "${AVM_ROOT}/test/decode_multithreaded_test.cc" + "${AVM_ROOT}/test/ethread_test.cc") + endif() endif() list(APPEND AVM_UNIT_TEST_COMMON_INTRIN_NEON From 2b81e251406e66aa0ed79d5ea8969dae65e98913 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Wed, 3 Jun 2026 10:25:57 -0700 Subject: [PATCH 4/5] av2_update_states_c(): Avoid integer wrap-around #5025 --- av2/encoder/trellis_quant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/av2/encoder/trellis_quant.c b/av2/encoder/trellis_quant.c index d718527ad9..fb2536bc4e 100644 --- a/av2/encoder/trellis_quant.c +++ b/av2/encoder/trellis_quant.c @@ -685,7 +685,7 @@ void av2_update_states_c(const tcq_node_t *decision, int col, for (int i = 0; i < TCQ_N_STATES; i++) { int prevId = decision[i].prevId; int absLevel = decision[i].absLevel; - tcq_ctx->lev_new[col][i] = AVMMIN(absLevel, MAX_VAL_BR_CTX); + tcq_ctx->lev_new[col][i] = AVMMIN(AVMMAX(0, absLevel), MAX_VAL_BR_CTX); tcq_ctx->prev_st[col][i] = prevId; if (prevId < 0) { tcq_ctx->orig_st[i] = -1; From ae55ddd4b514abb3a113cba751c5fe428c92c987 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Mon, 1 Jun 2026 12:31:05 -0700 Subject: [PATCH 5/5] [non-normative] Change default build settings This patch changes the default build settings to disable both multi-threading and SIMD on the normative branch, as requested by the AOMedia Codec Working Group. --- CMakeLists.txt | 6 ++++++ cmake/avm_config_defaults.cmake | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 331ecddd4d..42fd4c5d8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,12 @@ if(NOT EMSCRIPTEN) endif() endif() +if(NOT AVM_TARGET_CPU) + set(AVM_TARGET_CPU generic) + message("Forcing generic build for normative branch; set AVM_TARGET_CPU to " + "the target CPU type to allow for an optimized build.") +endif() + # Library version info. Update LT_CURRENT, LT_REVISION and LT_AGE when making a # public release by following the guidelines in the libtool document: # https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info diff --git a/cmake/avm_config_defaults.cmake b/cmake/avm_config_defaults.cmake index aa6ba3e3f7..20ebbbe94c 100644 --- a/cmake/avm_config_defaults.cmake +++ b/cmake/avm_config_defaults.cmake @@ -78,7 +78,7 @@ set_avm_config_var(CONFIG_GPROF 0 "Enable gprof support.") set_avm_config_var(CONFIG_LIBYUV 1 "Enables libyuv scaling/conversion support.") set_avm_config_var(CONFIG_LANCZOS_RESAMPLE 1 "Enables lanczos resize support.") -set_avm_config_var(CONFIG_MULTITHREAD 1 "Multithread support.") +set_avm_config_var(CONFIG_MULTITHREAD 0 "Multithread support.") set_avm_config_var(CONFIG_OS_SUPPORT 0 "Internal flag.") set_avm_config_var(CONFIG_PIC 0 "Build with PIC enabled.") set_avm_config_var(CONFIG_RUNTIME_CPU_DETECT 1 "Runtime CPU detection support.")