diff --git a/media/libaom/moz.yaml b/media/libaom/moz.yaml index c4ca01ba5bfa..d7e1ef50ada3 100644 --- a/media/libaom/moz.yaml +++ b/media/libaom/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: 2454213a72f194522c98610ef17057c226ffe391 (Thu Feb 06 17:19:39 2025 -0800). + release: 5f6ce718d903dca3e49c5c10db0859a394c9be84 (Fri Feb 28 09:42:44 2025 -0800). # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: 2454213a72f194522c98610ef17057c226ffe391 + revision: 5f6ce718d903dca3e49c5c10db0859a394c9be84 # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ diff --git a/third_party/aom/AUTHORS b/third_party/aom/AUTHORS index 4907baf1eb34..84c63b2f1766 100644 --- a/third_party/aom/AUTHORS +++ b/third_party/aom/AUTHORS @@ -27,6 +27,7 @@ Aniket Wanare Ankur Saxena Anupam Pandey Apurve Kumar Pandey +Aras Pranckevicius Arild Fuldseth Aron Rosenberg Arpad Panyik @@ -126,6 +127,7 @@ Jeff Faust Jeff Muizelaar Jeff Petkau Jerome Jiang +jerry Jia Jia Jian Zhou Jim Bankoski @@ -142,6 +144,7 @@ Joshua Bleecher Snyder Joshua Litt Josh Verdejo Julia Robson +Julio Barba Justin Clift Justin Lebar Katsuhisa Yuasa @@ -169,6 +172,7 @@ Luca Barbato Luca Versari Luc Trudeau Madhu Peringassery Krishnan +Mahesh Madhav Makoto Kato Mans Rullgard Marco Paniconi @@ -220,6 +224,7 @@ Peter de Rivaz Peter Kasting Philip Jägenstedt Philippe Antoine +Pradeep Kumar Priit Laes Qiu Jianlin Rachel Barker @@ -275,6 +280,7 @@ Suman Sunkara Susanna D'Souza Taekhyun Kim Takanori MATSUURA +Takuto Ikuta Tamar Levy Tao Bai Tarek AMARA @@ -319,6 +325,7 @@ Yue Chen Yunqing Wang Yury Gitman Yushin Cho +Zhaoliang Ma Zhijie Yang Zhipin Deng Zoe Liu diff --git a/third_party/aom/CHANGELOG b/third_party/aom/CHANGELOG index f828efb7bd57..fce8dc94ac9a 100644 --- a/third_party/aom/CHANGELOG +++ b/third_party/aom/CHANGELOG @@ -1,3 +1,86 @@ +2025-02-10 v3.12.0 + This release includes new codec interfaces, compression efficiency and + perceptual improvements, speedup and memory optimizations, and bug + fixes. This release is ABI compatible with the last release. + + Five internal functions (aom_free, aom_malloc, aom_wb_bytes_written, + aom_wb_write_bit, aom_wb_write_literal) that were exported by mistake + are no longer exported from the libaom shared library. The removal of + these internal functions from the ABI is a bug fix and does not break + ABI compatibility. + + Acknowledgments: The image quality optimizations in the new tuning + mode AOM_TUNE_IQ were originally developed for SVT-AV1-PSY by + Cole Ogaard, Gianni Rosato, Julio Barba, and Zakaria Djebrouni. + + - New Features + * New tuning mode AOM_TUNE_IQ (image quality) for the + AOME_SET_TUNING codec control (--tune=iq) in all-intra mode. The + feature detection macro AOM_HAVE_TUNE_IQ, if defined, indicates + that AOM_TUNE_IQ is available. The image quality optimizations in + AOM_TUNE_IQ were developed by using the SSIMULACRA 2 metric for + guidance and validated with subjective visual quality checks. + * New value 6 for the AV1E_SET_DELTAQ_MODE codec control + (--deltaq-mode): use modulation for all intra using Variance + Boost. Variance Boost is a variance adaptive quantization + implementation that modulates qindex depending on the ratio of + low-variance to high-variance 8x8 subblocks within a 64x64 + superblock, as well as the actual variance of the subblocks + themselves. + * New value 3 for the AV1E_SET_ENABLE_CDEF codec control + (--enable-cdef): Enable CDEF adaptively based on frame qindex. + * In all-intra mode, the AOME_SET_SHARPNESS codec control now also + sets the loop_filter_sharpness syntax element in the bitstream. + Larger values increasingly reduce how much the filtering can + change the sample values on block edges to favor perceived + sharpness. + * In all-intra mode, the default value of the AV1E_SET_QM_MIN codec + control is decreased to 4, and the default value of the + AV1E_SET_QM_MAX codec control is increased to 10. The default + values in good-quality and realtime modes remain unchanged (5 and + 9, respectively). + + - Compression Efficiency Improvements + * Tuning mode AOM_TUNE_IQ improves image compression efficiency on + the CLIC dataset by up to 12% for the same SSIMULACRA 2 score, up + to 14% for the same DSSIM score, and up to 17% for the same + Butteraugli score. + * ~3% BD-rate gains for speed 11 VGA camera mode. + * ~5% BD-rate gains for speed 11 on scroll clips screen mode. + + - Perceptual Quality Improvements + * Adjust temporal filter strength for better visual quality. + * RTC screen: visual quality improvements for scrolling and for + scene/slide changes. + * RTC camera mode: visual quality improvements for speed 11 VGA. + + - Speedup and Memory Optimizations + * Optimize the Arm Neon implementation of the loop filter functions + with an average uplift of 15 - 25% in microbenchmarks. + * Add the CDEF optimization for RISC-V. + * Help the compiler generate better vectorized code for variance + calculation and warped motion in generic CPU builds. + * Make several arrays const. + + - Other Improvements + * Binary size reduction: 1 - 2% compared with last release, with + CONFIG_REALTIME_ONLY enabled, CONFIG_AV1_DECODER and + CONFIG_AV1_HIGHBITDEPTH disabled. + * Build: compile source files in parallel under MSVC. + + - Bug Fixes + * Fix bug where metadata added with aom_img_add_metadata was lost + when frame scaling was used. + * Bug b:383306740: RTC: Fix to issues with scrolling for screen + content. + * Bug b:382465458: RTC: Fix to artifact for grayscale input. + * Bug b:380247338: RTC: Fix to encode_time spikes on scene/slide + changes. + * RTC: Fix to rate correction factor update for VBR screen mode. + https://groups.google.com/a/aomedia.org/g/av1-discuss/c/nJxECdg-7P8 + * Bug b:378401081: RTC: Fix to cyclic refresh update for external RC + (rate control). + 2024-10-24 v3.11.0 This release includes perceptual quality improvements, binary size reduction under certain configurations and many bug fixes. This release changes the diff --git a/third_party/aom/CMakeLists.txt b/third_party/aom/CMakeLists.txt index 1c37223cbce5..9fb72c4bfa7c 100644 --- a/third_party/aom/CMakeLists.txt +++ b/third_party/aom/CMakeLists.txt @@ -25,7 +25,9 @@ if("${AOM_ROOT}" STREQUAL "${AOM_CONFIG_DIR}") "And re-run CMake from the aom_build directory.") endif() -project(AOM C CXX) +# VERSION is the release version of the library. It should be updated at the +# same time as the LT_* variables. +project(AOM LANGUAGES C CXX VERSION 3.12.0) # GENERATED source property global visibility. if(POLICY CMP0118) @@ -58,9 +60,11 @@ endif() # passed to libtool. # # We set SO_FILE_VERSION = [c-a].a.r -set(LT_CURRENT 14) +# +# The VERSION number in project() should be updated when these variables are. +set(LT_CURRENT 15) set(LT_REVISION 0) -set(LT_AGE 11) +set(LT_AGE 12) math(EXPR SO_VERSION "${LT_CURRENT} - ${LT_AGE}") set(SO_FILE_VERSION "${SO_VERSION}.${LT_AGE}.${LT_REVISION}") unset(LT_CURRENT) @@ -285,9 +289,11 @@ else() set(target_objs_aom $) endif() add_library(aom ${target_objs_aom} $) +target_include_directories(aom PUBLIC $) if(BUILD_SHARED_LIBS) add_library(aom_static STATIC ${target_objs_aom} $) + target_include_directories(aom_static PUBLIC $) set_target_properties(aom_static PROPERTIES OUTPUT_NAME aom) if(MSVC OR (WIN32 AND NOT MINGW)) # Fix race condition between the import library and the static library. diff --git a/third_party/aom/aom/aomcx.h b/third_party/aom/aom/aomcx.h index 449ade0c4e50..9e6050e3781b 100644 --- a/third_party/aom/aom/aomcx.h +++ b/third_party/aom/aom/aomcx.h @@ -1578,6 +1578,11 @@ enum aome_enc_control_id { */ AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR = 169, + /*!\brief Codec control to enable the low complexity decode mode, unsigned + * int parameter. Value of zero means this mode is disabled. + */ + AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE = 170, + // Any new encoder control IDs should be added above. // Maximum allowed encoder control ID is 229. // No encoder control ID should be added below. @@ -2279,6 +2284,9 @@ AOM_CTRL_USE_TYPE(AV1E_SET_POSTENCODE_DROP_RTC, int) AOM_CTRL_USE_TYPE(AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, int) #define AOM_CTRL_AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR +AOM_CTRL_USE_TYPE(AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE, unsigned int) +#define AOM_CTRL_AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE + /*!\endcond */ /*! @} - end defgroup aom_encoder */ #ifdef __cplusplus diff --git a/third_party/aom/aom/src/aom_image.c b/third_party/aom/aom/src/aom_image.c index 0aab80c9de57..a33262d3561f 100644 --- a/third_party/aom/aom/src/aom_image.c +++ b/third_party/aom/aom/src/aom_image.c @@ -180,6 +180,10 @@ static aom_image_t *img_alloc_helper( img->stride[AOM_PLANE_V] = 0; } + img->cp = AOM_CICP_CP_UNSPECIFIED; + img->tc = AOM_CICP_TC_UNSPECIFIED; + img->mc = AOM_CICP_MC_UNSPECIFIED; + /* Default viewport to entire image. (This aom_img_set_rect call always * succeeds.) */ int ret = aom_img_set_rect(img, 0, 0, d_w, d_h, border); diff --git a/third_party/aom/aom_dsp/x86/synonyms.h b/third_party/aom/aom_dsp/x86/synonyms.h index bbaa0a0c4818..0f829821a996 100644 --- a/third_party/aom/aom_dsp/x86/synonyms.h +++ b/third_party/aom/aom_dsp/x86/synonyms.h @@ -46,16 +46,6 @@ static inline __m128i xx_loadu_128(const void *a) { return _mm_loadu_si128((const __m128i *)a); } -// _mm_loadu_si64 has been introduced in GCC 9, reimplement the function -// manually on older compilers. -#if !defined(__clang__) && __GNUC_MAJOR__ < 9 -static inline __m128i xx_loadu_2x64(const void *hi, const void *lo) { - __m64 hi_, lo_; - memcpy(&hi_, hi, sizeof(hi_)); - memcpy(&lo_, lo, sizeof(lo_)); - return _mm_set_epi64(hi_, lo_); -} -#else // Load 64 bits from each of hi and low, and pack into an SSE register // Since directly loading as `int64_t`s and using _mm_set_epi64 may violate // the strict aliasing rule, this takes a different approach @@ -63,7 +53,6 @@ static inline __m128i xx_loadu_2x64(const void *hi, const void *lo) { return _mm_unpacklo_epi64(_mm_loadl_epi64((const __m128i *)lo), _mm_loadl_epi64((const __m128i *)hi)); } -#endif static inline void xx_storel_32(void *const a, const __m128i v) { const int val = _mm_cvtsi128_si32(v); diff --git a/third_party/aom/aom_dsp/x86/synonyms_avx2.h b/third_party/aom/aom_dsp/x86/synonyms_avx2.h index 5b8a79f8c445..20e6a4b23a04 100644 --- a/third_party/aom/aom_dsp/x86/synonyms_avx2.h +++ b/third_party/aom/aom_dsp/x86/synonyms_avx2.h @@ -76,26 +76,11 @@ static inline __m256i yy_loadu_4x64(const void *e3, const void *e2, return yy_set_m128i(_mm_castpd_si128(v23), _mm_castpd_si128(v01)); } -#define GCC_VERSION (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) - -// _mm256_loadu2_m128i has been introduced in GCC 10.1 -#if !defined(__clang__) && GCC_VERSION < 101000 -static inline __m256i yy_loadu2_128(const void *hi, const void *lo) { - __m128i mhi = _mm_loadu_si128((const __m128i *)(hi)); - __m128i mlo = _mm_loadu_si128((const __m128i *)(lo)); - return _mm256_set_m128i(mhi, mlo); -} -#else static inline __m256i yy_loadu2_128(const void *hi, const void *lo) { __m128i mhi = _mm_loadu_si128((const __m128i *)(hi)); __m128i mlo = _mm_loadu_si128((const __m128i *)(lo)); return yy_set_m128i(mhi, mlo); } -#endif - -#undef GCC_VERSION static inline void yy_storeu2_128(void *hi, void *lo, const __m256i a) { _mm_storeu_si128((__m128i *)hi, _mm256_extracti128_si256(a, 1)); diff --git a/third_party/aom/apps/aomenc.c b/third_party/aom/apps/aomenc.c index 3d58a8946ca2..763e359c3eb3 100644 --- a/third_party/aom/apps/aomenc.c +++ b/third_party/aom/apps/aomenc.c @@ -242,6 +242,7 @@ static const int av1_arg_ctrl_map[] = { AOME_SET_CPUUSED, AV1E_SET_AUTO_INTRA_TOOLS_OFF, AV1E_ENABLE_RATE_GUIDE_DELTAQ, AV1E_SET_RATE_DISTRIBUTION_INFO, + AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE, 0 }; static const arg_def_t *const main_args[] = { @@ -454,6 +455,7 @@ static const arg_def_t *const av1_ctrl_args[] = { &g_av1_codec_arg_defs.auto_intra_tools_off, &g_av1_codec_arg_defs.enable_rate_guide_deltaq, &g_av1_codec_arg_defs.rate_distribution_info, + &g_av1_codec_arg_defs.enable_low_complexity_decode, NULL, }; @@ -554,6 +556,7 @@ struct stream_config { const char *two_pass_output; int two_pass_width; int two_pass_height; + unsigned int enable_low_complexity_decode; }; struct stream_state { @@ -1152,6 +1155,10 @@ static int parse_stream_params(struct AvxEncoderConfig *global, } else if (arg_match(&arg, &g_av1_codec_arg_defs.rate_distribution_info, argi)) { config->rate_distribution_info = arg.val; + } else if (arg_match(&arg, + &g_av1_codec_arg_defs.enable_low_complexity_decode, + argi)) { + config->enable_low_complexity_decode = arg_parse_uint(&arg); } else if (arg_match(&arg, &g_av1_codec_arg_defs.use_fixed_qp_offsets, argi)) { config->cfg.use_fixed_qp_offsets = arg_parse_uint(&arg); @@ -1562,6 +1569,14 @@ static void initialize_encoder(struct stream_state *stream, ctx_exit_on_error(&stream->encoder, "Failed to set rate distribution info"); } + if (stream->config.enable_low_complexity_decode) { + AOM_CODEC_CONTROL_TYPECHECKED(&stream->encoder, + AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE, + stream->config.enable_low_complexity_decode); + ctx_exit_on_error(&stream->encoder, + "Failed to enable low complexity decode"); + } + if (stream->config.film_grain_filename) { AOM_CODEC_CONTROL_TYPECHECKED(&stream->encoder, AV1E_SET_FILM_GRAIN_TABLE, stream->config.film_grain_filename); diff --git a/third_party/aom/av1/arg_defs.c b/third_party/aom/av1/arg_defs.c index a107e21f507d..79b4bceae656 100644 --- a/third_party/aom/av1/arg_defs.c +++ b/third_party/aom/av1/arg_defs.c @@ -705,5 +705,8 @@ const av1_codec_arg_definitions_t g_av1_codec_arg_defs = { ARG_DEF(NULL, "sb-qp-sweep", 1, "When set to 1, enable the superblock level qp sweep for a " "given lambda to minimize the rdcost."), + .enable_low_complexity_decode = + ARG_DEF(NULL, "enable-low-complexity-decode", 1, + "Enable low complexity decode (0: false (default), 1: true)"), #endif // CONFIG_AV1_ENCODER }; diff --git a/third_party/aom/av1/arg_defs.h b/third_party/aom/av1/arg_defs.h index a206036f46e3..380824aa6138 100644 --- a/third_party/aom/av1/arg_defs.h +++ b/third_party/aom/av1/arg_defs.h @@ -236,6 +236,7 @@ typedef struct av1_codec_arg_definitions { arg_def_t strict_level_conformance; arg_def_t kf_max_pyr_height; arg_def_t sb_qp_sweep; + arg_def_t enable_low_complexity_decode; #endif // CONFIG_AV1_ENCODER } av1_codec_arg_definitions_t; diff --git a/third_party/aom/av1/av1_cx_iface.c b/third_party/aom/av1/av1_cx_iface.c index 2d455324e151..7aff0a7e7c9b 100644 --- a/third_party/aom/av1/av1_cx_iface.c +++ b/third_party/aom/av1/av1_cx_iface.c @@ -164,6 +164,7 @@ struct av1_extracfg { int enable_dnl_denoising; #endif + unsigned int enable_low_complexity_decode; unsigned int chroma_subsampling_x; unsigned int chroma_subsampling_y; int reduced_tx_type_set; @@ -328,6 +329,8 @@ static const struct av1_extracfg default_extra_cfg = { 32, // noise_block_size 1, // enable_dnl_denoising #endif + + 0, // enable_low_complexity_decode 0, // chroma_subsampling_x 0, // chroma_subsampling_y 0, // reduced_tx_type_set @@ -480,15 +483,17 @@ static const struct av1_extracfg default_extra_cfg = { 32, // noise_block_size 1, // enable_dnl_denoising #endif - 0, // chroma_subsampling_x - 0, // chroma_subsampling_y - 0, // reduced_tx_type_set - 0, // use_intra_dct_only - 0, // use_inter_dct_only - 1, // use_intra_default_tx_only - 1, // enable_tx_size_search - 0, // quant_b_adapt - 0, // vbr_corpus_complexity_lap + + 0, // enable_low_complexity_decode + 0, // chroma_subsampling_x + 0, // chroma_subsampling_y + 0, // reduced_tx_type_set + 0, // use_intra_dct_only + 0, // use_inter_dct_only + 1, // use_intra_default_tx_only + 1, // enable_tx_size_search + 0, // quant_b_adapt + 0, // vbr_corpus_complexity_lap { SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, @@ -870,8 +875,19 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx, RANGE_CHECK(extra_cfg, max_reference_frames, 3, 7); RANGE_CHECK(extra_cfg, enable_reduced_reference_set, 0, 1); + + RANGE_CHECK_HI(extra_cfg, enable_low_complexity_decode, 1); RANGE_CHECK_HI(extra_cfg, chroma_subsampling_x, 1); RANGE_CHECK_HI(extra_cfg, chroma_subsampling_y, 1); + // 6.4.2 Color config semantics + // If matrix_coefficients is equal to MC_IDENTITY, it is a requirement of + // bitstream conformance that subsampling_x is equal to 0 and subsampling_y + // is equal to 0. + if (extra_cfg->matrix_coefficients == AOM_CICP_MC_IDENTITY && + (extra_cfg->chroma_subsampling_x != 0 || + extra_cfg->chroma_subsampling_y != 0)) { + ERROR("Subsampling must be 0 with AOM_CICP_MC_IDENTITY."); + } RANGE_CHECK_HI(extra_cfg, disable_trellis_quant, 3); RANGE_CHECK(extra_cfg, coeff_cost_upd_freq, 0, 3); @@ -941,6 +957,15 @@ static aom_codec_err_t validate_img(aom_codec_alg_priv_t *ctx, if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h) ERROR("Image size must match encoder init configuration size"); + // 6.4.2 Color config semantics + // If matrix_coefficients is equal to MC_IDENTITY, it is a requirement of + // bitstream conformance that subsampling_x is equal to 0 and subsampling_y + // is equal to 0. + if (ctx->oxcf.color_cfg.matrix_coefficients == AOM_CICP_MC_IDENTITY && + (img->x_chroma_shift != 0 || img->y_chroma_shift != 0)) { + ERROR("Subsampling must be 0 with AOM_CICP_MC_IDENTITY."); + } + #if CONFIG_TUNE_BUTTERAUGLI if (ctx->extra_cfg.tuning == AOM_TUNE_BUTTERAUGLI) { if (img->bit_depth > 8) { @@ -1301,6 +1326,13 @@ static void set_encoder_config(AV1EncoderConfig *oxcf, oxcf->speed < 7) oxcf->speed = 7; + // Now, low complexity decode mode is only supported for good-quality + // encoding speed 1 to 3. This can be further modified if needed. + oxcf->enable_low_complexity_decode = + extra_cfg->enable_low_complexity_decode && + cfg->g_usage == AOM_USAGE_GOOD_QUALITY && oxcf->speed >= 1 && + oxcf->speed <= 3; + // Set Color related configuration. color_cfg->color_primaries = extra_cfg->color_primaries; color_cfg->transfer_characteristics = extra_cfg->transfer_characteristics; @@ -1972,6 +2004,14 @@ static aom_codec_err_t ctrl_set_timing_info_type(aom_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static aom_codec_err_t ctrl_set_enable_low_complexity_decode( + aom_codec_alg_priv_t *ctx, va_list args) { + struct av1_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.enable_low_complexity_decode = + CAST(AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE, args); + return update_extra_cfg(ctx, &extra_cfg); +} + static aom_codec_err_t ctrl_set_enable_dual_filter(aom_codec_alg_priv_t *ctx, va_list args) { struct av1_extracfg extra_cfg = ctx->extra_cfg; @@ -4377,6 +4417,11 @@ static aom_codec_err_t encoder_set_option(aom_codec_alg_priv_t *ctx, } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_angle_delta, argv, err_string)) { extra_cfg.enable_angle_delta = arg_parse_int_helper(&arg, err_string); + } else if (arg_match_helper( + &arg, &g_av1_codec_arg_defs.enable_low_complexity_decode, argv, + err_string)) { + extra_cfg.enable_low_complexity_decode = + arg_parse_int_helper(&arg, err_string); } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.reduced_tx_type_set, argv, err_string)) { extra_cfg.reduced_tx_type_set = arg_parse_int_helper(&arg, err_string); @@ -4708,6 +4753,8 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { { AV1E_SET_POSTENCODE_DROP_RTC, ctrl_set_postencode_drop_rtc }, { AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, ctrl_set_max_consec_frame_drop_ms_cbr }, + { AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE, + ctrl_set_enable_low_complexity_decode }, // Getters { AOME_GET_LAST_QUANTIZER, ctrl_get_quantizer }, diff --git a/third_party/aom/av1/encoder/arm/highbd_pickrst_neon.c b/third_party/aom/av1/encoder/arm/highbd_pickrst_neon.c index 00f88bcf02b2..bb85a4b920f7 100644 --- a/third_party/aom/av1/encoder/arm/highbd_pickrst_neon.c +++ b/third_party/aom/av1/encoder/arm/highbd_pickrst_neon.c @@ -1902,7 +1902,7 @@ int64_t av1_highbd_pixel_proj_error_neon( for (int k = j; k < width; ++k) { int32_t v = 1 << (SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS - 1); - v += xq_active * (int32_t)((uint32_t)flt[j] - (uint16_t)(dat[k] << 4)); + v += xq_active * (int32_t)((uint32_t)flt[k] - (uint16_t)(dat[k] << 4)); const int32_t e = (v >> (SGRPROJ_RST_BITS + SGRPROJ_PRJ_BITS)) + dat[k] - src[k]; sse += ((int64_t)e * e); diff --git a/third_party/aom/av1/encoder/block.h b/third_party/aom/av1/encoder/block.h index 267541b77739..1ff945d5a866 100644 --- a/third_party/aom/av1/encoder/block.h +++ b/third_party/aom/av1/encoder/block.h @@ -1352,6 +1352,10 @@ typedef struct macroblock { //! Flag to indicate to test the superblock MV for the coding block in the // nonrd_pickmode. int sb_me_block; + //! Flag to indicate superblock selected column scroll. + int sb_col_scroll; + //! Flag to indicate superblock selected row scroll. + int sb_row_scroll; //! Motion vector from superblock MV derived from int_pro_motion() in // the variance_partitioning. int_mv sb_me_mv; diff --git a/third_party/aom/av1/encoder/encodeframe.c b/third_party/aom/av1/encoder/encodeframe.c index 215b571dcb63..479ef8518bb6 100644 --- a/third_party/aom/av1/encoder/encodeframe.c +++ b/third_party/aom/av1/encoder/encodeframe.c @@ -180,6 +180,8 @@ void av1_accumulate_rtc_counters(AV1_COMP *cpi, const MACROBLOCK *const x) { if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ) av1_accumulate_cyclic_refresh_counters(cpi->cyclic_refresh, x); cpi->rc.cnt_zeromv += x->cnt_zeromv; + cpi->rc.num_col_blscroll_last_tl0 += x->sb_col_scroll; + cpi->rc.num_row_blscroll_last_tl0 += x->sb_row_scroll; } unsigned int av1_get_perpixel_variance(const AV1_COMP *cpi, @@ -1222,6 +1224,8 @@ static inline void encode_sb_row(AV1_COMP *cpi, ThreadData *td, x->sb_me_block = 0; x->sb_me_partition = 0; x->sb_me_mv.as_int = 0; + x->sb_col_scroll = 0; + x->sb_row_scroll = 0; x->sb_force_fixed_part = 1; x->color_palette_thresh = 64; x->force_color_check_block_level = 0; diff --git a/third_party/aom/av1/encoder/encoder.h b/third_party/aom/av1/encoder/encoder.h index 170fd40892aa..c0e76b520f14 100644 --- a/third_party/aom/av1/encoder/encoder.h +++ b/third_party/aom/av1/encoder/encoder.h @@ -1041,6 +1041,9 @@ typedef struct AV1EncoderConfig { // Indicates the speed preset to be used. int speed; + // Enable the low complexity decode mode. + unsigned int enable_low_complexity_decode; + // Indicates the target sequence level index for each operating point(OP). AV1_LEVEL target_seq_level_idx[MAX_NUM_OPERATING_POINTS]; diff --git a/third_party/aom/av1/encoder/ratectrl.c b/third_party/aom/av1/encoder/ratectrl.c index ae92471b634e..2461cfbe1bdb 100644 --- a/third_party/aom/av1/encoder/ratectrl.c +++ b/third_party/aom/av1/encoder/ratectrl.c @@ -3374,7 +3374,10 @@ static void rc_scene_detection_onepass_rt(AV1_COMP *cpi, cpi, src_y, last_src_y, src_ystride, last_src_ystride, BLOCK_128X128, pos_col, pos_row, &best_intmv_col, &best_intmv_row, sw_col, sw_row); - if (y_sad < 100 && + unsigned int sad_thresh = + (abs(best_intmv_col) > 150 || abs(best_intmv_row) > 150) ? 300 + : 150; + if (y_sad < sad_thresh && (abs(best_intmv_col) > 16 || abs(best_intmv_row) > 16)) { cpi->rc.high_motion_content_screen_rtc = 0; break; @@ -3822,6 +3825,10 @@ void av1_get_one_pass_rt_params(AV1_COMP *cpi, FRAME_TYPE *const frame_type, resize_reset_rc(cpi, resize_pending_params->width, resize_pending_params->height, cm->width, cm->height); } + if (svc->temporal_layer_id == 0) { + rc->num_col_blscroll_last_tl0 = 0; + rc->num_row_blscroll_last_tl0 = 0; + } // Set the GF interval and update flag. if (!rc->rtc_external_ratectrl) set_gf_interval_update_onepass_rt(cpi, *frame_type); @@ -3901,9 +3908,16 @@ int av1_encodedframe_overshoot_cbr(AV1_COMP *cpi, int *q) { *q = cpi->rc.worst_quality; } } else { - *q = (3 * cpi->rc.worst_quality + *q) >> 2; - // For screen content use the max-q set by the user to allow for less - // overshoot on slide changes. + // Set a larger QP. + const uint64_t sad_thr = 64 * 64 * 32; + if (cm->width * cm->height >= 1280 * 720 && + (p_rc->buffer_level > (p_rc->optimal_buffer_level) >> 1) && + cpi->rc.avg_source_sad < sad_thr) { + *q = (*q + cpi->rc.worst_quality) >> 1; + } else { + *q = (3 * cpi->rc.worst_quality + *q) >> 2; + } + // If we arrive here for screen content: use the max-q set by the user. if (is_screen_content) *q = cpi->rc.worst_quality; } } diff --git a/third_party/aom/av1/encoder/ratectrl.h b/third_party/aom/av1/encoder/ratectrl.h index 0e7ede9b8444..88c048fb7e2b 100644 --- a/third_party/aom/av1/encoder/ratectrl.h +++ b/third_party/aom/av1/encoder/ratectrl.h @@ -200,6 +200,8 @@ typedef struct { int last_target_size_keyframe; int frames_since_scene_change; int perc_spatial_flat_blocks; + int num_col_blscroll_last_tl0; + int num_row_blscroll_last_tl0; int avg_frame_bandwidth; // Average frame size target for clip int min_frame_bandwidth; // Minimum allocation used for any frame diff --git a/third_party/aom/av1/encoder/var_based_part.c b/third_party/aom/av1/encoder/var_based_part.c index 8876fd64ce33..69ed01334fe9 100644 --- a/third_party/aom/av1/encoder/var_based_part.c +++ b/third_party/aom/av1/encoder/var_based_part.c @@ -1332,8 +1332,10 @@ static void do_int_pro_motion_estimation(AV1_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd = &x->e_mbd; MB_MODE_INFO *mi = xd->mi[0]; const int is_screen = cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN; - const int increase_col_sw = - source_sad_nonrd > kMedSad && !cpi->rc.high_motion_content_screen_rtc; + const int increase_col_sw = source_sad_nonrd > kMedSad && + !cpi->rc.high_motion_content_screen_rtc && + (cpi->svc.temporal_layer_id == 0 || + cpi->rc.num_col_blscroll_last_tl0 > 2); int me_search_size_col = is_screen ? increase_col_sw ? 512 : 96 : block_size_wide[cm->seq_params->sb_size] >> 1; @@ -1355,6 +1357,12 @@ static void do_int_pro_motion_estimation(AV1_COMP *cpi, MACROBLOCK *x, if (*y_sad < (y_sad_zero >> 1) && *y_sad < thresh_sad) { x->sb_me_partition = 1; x->sb_me_mv.as_int = mi->mv[0].as_int; + if (cpi->svc.temporal_layer_id == 0) { + if (abs(mi->mv[0].as_mv.col) > 16 && abs(mi->mv[0].as_mv.row) == 0) + x->sb_col_scroll = 1; + else if (abs(mi->mv[0].as_mv.row) > 16 && abs(mi->mv[0].as_mv.col) == 0) + x->sb_row_scroll = 1; + } } else { x->sb_me_partition = 0; // Fall back to using zero motion. diff --git a/third_party/aom/build/cmake/aom_install.cmake b/third_party/aom/build/cmake/aom_install.cmake index d16df9766ead..4291782da1e9 100644 --- a/third_party/aom/build/cmake/aom_install.cmake +++ b/third_party/aom/build/cmake/aom_install.cmake @@ -84,6 +84,32 @@ macro(setup_aom_install_targets) set(AOM_INSTALL_LIBS aom) endif() + set(AOM_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") + set(AOM_VERSION_CONFIG + "${AOM_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") + set(AOM_PROJECT_CONFIG "${AOM_GENERATED_DIR}/${PROJECT_NAME}Config.cmake") + set(AOM_VERSION ${PROJECT_VERSION}) + + include(CMakePackageConfigHelpers) + write_basic_package_version_file("${AOM_VERSION_CONFIG}" + VERSION ${AOM_VERSION} + COMPATIBILITY SameMajorVersion) + # AOM_TARGETS_EXPORT_NAME is used by config.cmake.in. + set(AOM_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") + set(AOM_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.cmake.in" + "${AOM_PROJECT_CONFIG}" INSTALL_DESTINATION "${AOM_CONFIG_INSTALL_DIR}" + PATH_VARS CMAKE_INSTALL_INCLUDEDIR) + + # Install cmake config files + install(FILES "${AOM_PROJECT_CONFIG}" "${AOM_VERSION_CONFIG}" + DESTINATION "${AOM_CONFIG_INSTALL_DIR}") + + install(EXPORT "${AOM_TARGETS_EXPORT_NAME}" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION "${AOM_CONFIG_INSTALL_DIR}") + # Setup the install rules. install() will automatically prepend # CMAKE_INSTALL_PREFIX to relative paths install(FILES ${AOM_INSTALL_INCS} @@ -91,6 +117,7 @@ macro(setup_aom_install_targets) install(FILES "${AOM_PKG_CONFIG_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") install(TARGETS ${AOM_INSTALL_LIBS};${AOM_INSTALL_BINS} + EXPORT "${AOM_TARGETS_EXPORT_NAME}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/third_party/aom/build/cmake/config.cmake.in b/third_party/aom/build/cmake/config.cmake.in new file mode 100644 index 000000000000..c1c247665e9e --- /dev/null +++ b/third_party/aom/build/cmake/config.cmake.in @@ -0,0 +1,14 @@ +set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@) +@PACKAGE_INIT@ + +if(@CONFIG_MULTITHREAD@) + include(CMakeFindDependencyMacro) + find_dependency(Threads REQUIRED) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@AOM_TARGETS_EXPORT_NAME@.cmake") + +set_and_check(@PROJECT_NAME@_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set(@PROJECT_NAME@_LIBRARIES "@AOM_INSTALL_LIBS@") + +check_required_components(@PROJECT_NAME@) diff --git a/third_party/aom/build/cmake/rtcd.pl b/third_party/aom/build/cmake/rtcd.pl index 6cd6a5ca3674..5d0592bdfe6f 100755 --- a/third_party/aom/build/cmake/rtcd.pl +++ b/third_party/aom/build/cmake/rtcd.pl @@ -420,27 +420,45 @@ EOF common_bottom; } +# List of architectures in low-to-high preference order. +my @PRIORITY_ARCH = qw/ + c + mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx avx2 + arm_crc32 neon neon_dotprod neon_i8mm sve sve2 + rvv + vsx + dspr2 msa +/; +my %PRIORITY_INDEX; +for (my $i = 0; $i < @PRIORITY_ARCH; $i++) { + $PRIORITY_INDEX{$PRIORITY_ARCH[$i]} = $i; +} + # # Main Driver # &require("c"); -&require(keys %required); +&require(sort { $PRIORITY_INDEX{$a} <=> $PRIORITY_INDEX{$b} } keys %required); if ($opts{arch} eq 'x86') { @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx avx2/); x86; } elsif ($opts{arch} eq 'x86_64') { @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx avx2/); - @REQUIRES = filter(qw/mmx sse sse2/); - &require(@REQUIRES); + if (keys %required == 0) { + @REQUIRES = filter(qw/mmx sse sse2/); + &require(@REQUIRES); + } x86; } elsif ($opts{arch} =~ /armv[78]\w?/) { @ALL_ARCHS = filter(qw/neon/); arm; } elsif ($opts{arch} eq 'arm64' ) { @ALL_ARCHS = filter(qw/neon arm_crc32 neon_dotprod neon_i8mm sve sve2/); - @REQUIRES = filter(qw/neon/); - &require(@REQUIRES); + if (keys %required == 0) { + @REQUIRES = filter(qw/neon/); + &require(@REQUIRES); + } arm; } elsif ($opts{arch} eq 'ppc') { @ALL_ARCHS = filter(qw/vsx/); diff --git a/third_party/aom/test/encode_api_test.cc b/third_party/aom/test/encode_api_test.cc index 5f053b31ec58..d5451a98da7a 100644 --- a/third_party/aom/test/encode_api_test.cc +++ b/third_party/aom/test/encode_api_test.cc @@ -861,6 +861,46 @@ TEST(EncodeAPI, AomediaIssue3509VbrMinSection101Percent) { ASSERT_EQ(aom_codec_destroy(&enc), AOM_CODEC_OK); } +TEST(EncodeAPI, Buganizer392929025) { + // Initialize libaom encoder. + aom_codec_iface_t *const iface = aom_codec_av1_cx(); + aom_codec_ctx_t enc; + aom_codec_enc_cfg_t cfg; + + ASSERT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME), + AOM_CODEC_OK); + + cfg.g_w = 16; + cfg.g_h = 16; + + ASSERT_EQ(aom_codec_enc_init(&enc, iface, &cfg, 0), AOM_CODEC_OK); + + ASSERT_EQ(aom_codec_control(&enc, AV1E_SET_MATRIX_COEFFICIENTS, + AOM_CICP_MC_IDENTITY), + AOM_CODEC_OK); + + // Create input image. + aom_image_t *const image = + CreateGrayImage(AOM_IMG_FMT_I420, cfg.g_w, cfg.g_h); + ASSERT_NE(image, nullptr); + + // Encode frame. + // AOM_CICP_MC_IDENTITY requires subsampling to be 0. + EXPECT_EQ( + aom_codec_encode(&enc, image, /*pts=*/0, /*duration=*/1, /*flags=*/0), + AOM_CODEC_INVALID_PARAM); + + // Attempt to reconfigure with non-zero subsampling. + EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_CHROMA_SUBSAMPLING_X, 1), + AOM_CODEC_INVALID_PARAM); + EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_CHROMA_SUBSAMPLING_Y, 1), + AOM_CODEC_INVALID_PARAM); + + // Free resources. + aom_img_free(image); + ASSERT_EQ(aom_codec_destroy(&enc), AOM_CODEC_OK); +} + class EncodeAPIParameterized : public testing::TestWithParam> {}; diff --git a/third_party/aom/test/svc_datarate_test.cc b/third_party/aom/test/svc_datarate_test.cc index 35ccd6f9bc4d..13b0ba75bb40 100644 --- a/third_party/aom/test/svc_datarate_test.cc +++ b/third_party/aom/test/svc_datarate_test.cc @@ -2732,7 +2732,7 @@ TEST_P(DatarateTestSVC, BasicRateTargetingSVC2TL1SLScreenDropFrame1920x1080) { // Check basic rate targeting for CBR, for 2 temporal layers, 1 spatial // for screen mode, with frame dropper on at low bitrates. Use small // values of rc_buf_initial/optimal/sz to trigger postencode frame drop. -// Use 1920x1080 clip. This tests runs with 4 threads. +// Use 1920x1080 clip. This test runs with 4 threads. TEST_P(DatarateTestSVC, BasicRateTargetingSVC2TL1SLScreenDropFrame1920x10804Thread) { BasicRateTargetingSVC2TL1SLScreenDropFrame1920x10804ThreadTest();