|  | #!/bin/sh | 
|  | ## Copyright (c) 2023, Alliance for Open Media. All rights reserved. | 
|  | ## | 
|  | ## This source code is subject to the terms of the BSD 2 Clause License and | 
|  | ## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | 
|  | ## was not distributed with this source code in the LICENSE file, you can | 
|  | ## obtain it at www.aomedia.org/license/software. If the Alliance for Open | 
|  | ## Media Patent License 1.0 was not distributed with this source code in the | 
|  | ## PATENTS file, you can obtain it at www.aomedia.org/license/patent. | 
|  | ## | 
|  | ##  This script checks the bit exactness between C and SIMD | 
|  | ##  implementations of AV1 encoder. | 
|  | ## | 
|  | . $(dirname $0)/tools_common.sh | 
|  |  | 
|  | PRESETS="good rt" | 
|  | LOWBD_CIF_CLIP="yuv_raw_input" | 
|  | LOWBD_480p_CLIP="yuv_480p_raw_input" | 
|  | LOWBD_720p_CLIP="y4m_720p_input" | 
|  | HIGHBD_CLIP="y4m_360p_10bit_input" | 
|  | SC_CLIP="y4m_screen_input" | 
|  | OUT_FILE_SUFFIX=".ivf" | 
|  | SCRIPT_DIR=$(dirname "$0") | 
|  | LIBAOM_SOURCE_DIR=$(cd ${SCRIPT_DIR}/..; pwd) | 
|  |  | 
|  | # Clips used in test. | 
|  | YUV_RAW_INPUT="${LIBAOM_TEST_DATA_PATH}/hantro_collage_w352h288.yuv" | 
|  | YUV_480P_RAW_INPUT="${LIBAOM_TEST_DATA_PATH}/niklas_640_480_30.yuv" | 
|  | Y4M_360P_10BIT_INPUT="${LIBAOM_TEST_DATA_PATH}/crowd_run_360p_10_150f.y4m" | 
|  | Y4M_720P_INPUT="${LIBAOM_TEST_DATA_PATH}/niklas_1280_720_30.y4m" | 
|  | Y4M_SCREEN_INPUT="${LIBAOM_TEST_DATA_PATH}/wikipedia_420_360p_60f.y4m" | 
|  |  | 
|  | # Number of frames to test. | 
|  | AV1_ENCODE_C_VS_SIMD_TEST_FRAME_LIMIT=35 | 
|  |  | 
|  | # Create a temporary directory for output files. | 
|  | if [ -n "${TMPDIR}" ]; then | 
|  | AOM_TEST_TEMP_ROOT="${TMPDIR}" | 
|  | elif [ -n "${TEMPDIR}" ]; then | 
|  | AOM_TEST_TEMP_ROOT="${TEMPDIR}" | 
|  | else | 
|  | AOM_TEST_TEMP_ROOT=/tmp | 
|  | fi | 
|  |  | 
|  | AOM_TEST_OUTPUT_DIR="${AOM_TEST_TEMP_ROOT}/av1_test_$$" | 
|  |  | 
|  | if ! mkdir -p "${AOM_TEST_OUTPUT_DIR}" || \ | 
|  | [ ! -d "${AOM_TEST_OUTPUT_DIR}" ]; then | 
|  | echo "${0##*/}: Cannot create output directory, giving up." | 
|  | echo "${0##*/}:   AOM_TEST_OUTPUT_DIR=${AOM_TEST_OUTPUT_DIR}" | 
|  | exit 1 | 
|  | fi | 
|  |  | 
|  | elog() { | 
|  | echo "$@" 1>&2 | 
|  | } | 
|  |  | 
|  | # Echoes path to $1 when it's executable and exists in ${AOM_TEST_OUTPUT_DIR}, | 
|  | # or an empty string. Caller is responsible for testing the string once the | 
|  | # function returns. | 
|  | av1_enc_tool_path() { | 
|  | local target="$1" | 
|  | local preset="$2" | 
|  | local tool_path="${AOM_TEST_OUTPUT_DIR}/build_target_${target}/aomenc_${preset}" | 
|  |  | 
|  | if [ ! -x "${tool_path}" ]; then | 
|  | tool_path="" | 
|  | fi | 
|  | echo "${tool_path}" | 
|  | } | 
|  |  | 
|  | # Environment check: Make sure input and source directories are available. | 
|  | av1_c_vs_simd_enc_verify_environment () { | 
|  | if [ ! -e "${YUV_RAW_INPUT}" ]; then | 
|  | elog "libaom test data must exist in LIBAOM_TEST_DATA_PATH." | 
|  | return 1 | 
|  | fi | 
|  | if [ ! -e "${Y4M_360P_10BIT_INPUT}" ]; then | 
|  | elog "libaom test data must exist in LIBAOM_TEST_DATA_PATH." | 
|  | return 1 | 
|  | fi | 
|  | if [ ! -e "${YUV_480P_RAW_INPUT}" ]; then | 
|  | elog "libaom test data must exist in LIBAOM_TEST_DATA_PATH." | 
|  | return 1 | 
|  | fi | 
|  | if [ ! -e "${Y4M_720P_INPUT}" ]; then | 
|  | elog "libaom test data must exist in LIBAOM_TEST_DATA_PATH." | 
|  | return 1 | 
|  | fi | 
|  | if [ ! -e "${Y4M_SCREEN_INPUT}" ]; then | 
|  | elog "libaom test data must exist in LIBAOM_TEST_DATA_PATH." | 
|  | return 1 | 
|  | fi | 
|  | if [ ! -d "$LIBAOM_SOURCE_DIR" ]; then | 
|  | elog "LIBAOM_SOURCE_DIR does not exist." | 
|  | return 1 | 
|  | fi | 
|  | } | 
|  |  | 
|  | # This is not needed since tools_common.sh does the same cleanup. | 
|  | # Keep the code here for our reference. | 
|  | # cleanup() { | 
|  | #  rm -rf  ${AOM_TEST_OUTPUT_DIR} | 
|  | # } | 
|  |  | 
|  | # Echo AOM_SIMD_CAPS_MASK for different instruction set architecture. | 
|  | avx2() { | 
|  | echo "0x1FF" | 
|  | } | 
|  |  | 
|  | avx() { | 
|  | echo "0x17F" | 
|  | } | 
|  |  | 
|  | sse4_2() { | 
|  | echo "0x13F" | 
|  | } | 
|  |  | 
|  | sse4_1() { | 
|  | echo "0x03F" | 
|  | } | 
|  |  | 
|  | ssse3() { | 
|  | echo "0x01F" | 
|  | } | 
|  |  | 
|  | sse3() { | 
|  | echo "0x00F" | 
|  | } | 
|  |  | 
|  | sse2() { | 
|  | echo "0x007" | 
|  | } | 
|  |  | 
|  | get_bitrates() { | 
|  | local content=$1 | 
|  | local preset=$2 | 
|  |  | 
|  | # Bit-rates: | 
|  | local bitrate_lowres_good="300" | 
|  | local bitrate_480p_good="500" | 
|  | local bitrate_720p_good="1000" | 
|  | local bitrate_scc_360p_good="500" | 
|  | local bitrate_lowres_rt="200" | 
|  | local bitrate_480p_rt="300" | 
|  | local bitrate_720p_rt="600" | 
|  | local bitrate_scc_360p_rt="300" | 
|  | local bitrate_hbd_360p="500" | 
|  |  | 
|  | if [ "${preset}" = "good" ]; then | 
|  | if [ "${content}" = "yuv_raw_input" ]; then | 
|  | echo "${bitrate_lowres_good}" | 
|  | elif [ "${content}" = "yuv_480p_raw_input" ]; then | 
|  | echo "${bitrate_480p_good}" | 
|  | elif [ "${content}" = "y4m_720p_input" ]; then | 
|  | echo "${bitrate_720p_good}" | 
|  | elif [ "${content}" = "y4m_screen_input" ]; then | 
|  | echo "${bitrate_scc_360p_good}" | 
|  | elif [ "${content}" = "y4m_360p_10bit_input" ]; then | 
|  | echo "${bitrate_hbd_360p}" | 
|  | else | 
|  | elog "Invalid content" | 
|  | fi | 
|  | elif  [ "${preset}" = "rt" ]; then | 
|  | if [ "${content}" = "yuv_raw_input" ]; then | 
|  | echo "${bitrate_lowres_rt}" | 
|  | elif [ "${content}" = "yuv_480p_raw_input" ]; then | 
|  | echo "${bitrate_480p_rt}" | 
|  | elif [ "${content}" = "y4m_720p_input" ]; then | 
|  | echo "${bitrate_720p_rt}" | 
|  | elif [ "${content}" = "y4m_screen_input" ]; then | 
|  | echo "${bitrate_scc_360p_rt}" | 
|  | elif [ "${content}" = "y4m_360p_10bit_input" ]; then | 
|  | echo "${bitrate_hbd_360p}" | 
|  | else | 
|  | elog "Invalid content" | 
|  | fi | 
|  | else | 
|  | elog "invalid preset" | 
|  | fi | 
|  | } | 
|  |  | 
|  | # Echo clip details to be used as input to aomenc. | 
|  | yuv_raw_input() { | 
|  | echo ""${YUV_RAW_INPUT}" | 
|  | --width=352 | 
|  | --height=288 | 
|  | --bit-depth=8" | 
|  | } | 
|  |  | 
|  | y4m_360p_10bit_input() { | 
|  | echo ""${Y4M_360P_10BIT_INPUT}" | 
|  | --bit-depth=10" | 
|  | } | 
|  |  | 
|  | yuv_480p_raw_input() { | 
|  | echo ""${YUV_480P_RAW_INPUT}" | 
|  | --width=640 | 
|  | --height=480 | 
|  | --bit-depth=8" | 
|  | } | 
|  |  | 
|  | y4m_720p_input() { | 
|  | echo ""${Y4M_720P_INPUT}" | 
|  | --bit-depth=8" | 
|  | } | 
|  |  | 
|  | y4m_screen_input() { | 
|  | echo ""${Y4M_SCREEN_INPUT}" | 
|  | --tune-content=screen | 
|  | --enable-palette=1 | 
|  | --bit-depth=8" | 
|  | } | 
|  |  | 
|  | has_x86_isa_extn() { | 
|  | instruction_set=$1 | 
|  | if ! grep -q "$instruction_set" /proc/cpuinfo; then | 
|  | # This instruction set is not supported. | 
|  | return 1 | 
|  | fi | 
|  | } | 
|  |  | 
|  | # Echo good encode params for use with AV1 encoder. | 
|  | av1_encode_good_params() { | 
|  | echo "--good \ | 
|  | --ivf \ | 
|  | --profile=0 \ | 
|  | --static-thresh=0 \ | 
|  | --threads=1 \ | 
|  | --tile-columns=0 \ | 
|  | --tile-rows=0 \ | 
|  | --verbose \ | 
|  | --end-usage=vbr \ | 
|  | --kf-max-dist=160 \ | 
|  | --kf-min-dist=0 \ | 
|  | --max-q=63 \ | 
|  | --min-q=0 \ | 
|  | --overshoot-pct=100 \ | 
|  | --undershoot-pct=100 \ | 
|  | --passes=2 \ | 
|  | --arnr-maxframes=7 \ | 
|  | --arnr-strength=5 \ | 
|  | --auto-alt-ref=1 \ | 
|  | --drop-frame=0 \ | 
|  | --frame-parallel=0 \ | 
|  | --lag-in-frames=35 \ | 
|  | --maxsection-pct=2000 \ | 
|  | --minsection-pct=0 \ | 
|  | --sharpness=0" | 
|  | } | 
|  |  | 
|  | # Echo realtime encode params for use with AV1 encoder. | 
|  | av1_encode_rt_params() { | 
|  | echo "--rt \ | 
|  | --ivf \ | 
|  | --profile=0 \ | 
|  | --static-thresh=0 \ | 
|  | --threads=1 \ | 
|  | --tile-columns=0 \ | 
|  | --tile-rows=0 \ | 
|  | --verbose \ | 
|  | --end-usage=cbr \ | 
|  | --kf-max-dist=90000 \ | 
|  | --max-q=58 \ | 
|  | --min-q=2 \ | 
|  | --overshoot-pct=50 \ | 
|  | --undershoot-pct=50 \ | 
|  | --passes=1 \ | 
|  | --aq-mode=3 \ | 
|  | --buf-initial-sz=500 \ | 
|  | --buf-optimal-sz=600 \ | 
|  | --buf-sz=1000 \ | 
|  | --coeff-cost-upd-freq=3 \ | 
|  | --dv-cost-upd-freq=3 \ | 
|  | --mode-cost-upd-freq=3 \ | 
|  | --mv-cost-upd-freq=3 \ | 
|  | --deltaq-mode=0 \ | 
|  | --enable-global-motion=0 \ | 
|  | --enable-obmc=0 \ | 
|  | --enable-order-hint=0 \ | 
|  | --enable-ref-frame-mvs=0 \ | 
|  | --enable-tpl-model=0 \ | 
|  | --enable-warped-motion=0 \ | 
|  | --lag-in-frames=0 \ | 
|  | --max-intra-rate=300 \ | 
|  | --noise-sensitivity=0" | 
|  | } | 
|  |  | 
|  | # Configures for the given target in AOM_TEST_OUTPUT_DIR/build_target_${target} | 
|  | # directory. | 
|  | av1_enc_build() { | 
|  | local target="$1" | 
|  | local cmake_command="$2" | 
|  | local tmp_build_dir=${AOM_TEST_OUTPUT_DIR}/build_target_${target} | 
|  | if [ -d "$tmp_build_dir" ]; then | 
|  | rm -rf $tmp_build_dir | 
|  | fi | 
|  |  | 
|  | mkdir -p $tmp_build_dir | 
|  | cd $tmp_build_dir | 
|  |  | 
|  | local cmake_common_args="--fresh -DCONFIG_EXCLUDE_SIMD_MISMATCH=1 \ | 
|  | -DCMAKE_BUILD_TYPE=Release \ | 
|  | -DENABLE_CCACHE=1 \ | 
|  | '-DCMAKE_C_FLAGS_RELEASE=-O3 -g' \ | 
|  | '-DCMAKE_CXX_FLAGS_RELEASE=-O3 -g' \ | 
|  | -DENABLE_DOCS=0 -DENABLE_TESTS=0 -DENABLE_TOOLS=0" | 
|  |  | 
|  | for preset in $PRESETS; do | 
|  | echo "Building target[${preset} encoding]: ${target}" | 
|  | if [ "${preset}" = "good" ]; then | 
|  | local cmake_extra_args="-DCONFIG_AV1_HIGHBITDEPTH=1" | 
|  | elif [ "${preset}" = "rt" ]; then | 
|  | local cmake_extra_args="-DCONFIG_REALTIME_ONLY=1 -DCONFIG_AV1_HIGHBITDEPTH=0" | 
|  | else | 
|  | elog "Invalid preset" | 
|  | return 1 | 
|  | fi | 
|  | if ! eval "$cmake_command" "${cmake_common_args}" "${cmake_extra_args}" \ | 
|  | ${devnull}; then | 
|  | elog "cmake failure" | 
|  | return 1 | 
|  | fi | 
|  | if ! eval make -j$(nproc) aomenc ${devnull}; then | 
|  | elog "build failure" | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | mv aomenc aomenc_${preset} | 
|  | done | 
|  | echo "Done building target: ${target}" | 
|  | } | 
|  |  | 
|  | compare_enc_output() { | 
|  | local target=$1 | 
|  | local cpu=$2 | 
|  | local clip=$3 | 
|  | local bitrate=$4 | 
|  | local preset=$5 | 
|  | if ! diff -q ${AOM_TEST_OUTPUT_DIR}/Out-generic-"${clip}"-${preset}-${bitrate}kbps-cpu${cpu}${OUT_FILE_SUFFIX} \ | 
|  | ${AOM_TEST_OUTPUT_DIR}/Out-${target}-"${clip}"-${preset}-${bitrate}kbps-cpu${cpu}${OUT_FILE_SUFFIX}; then | 
|  | elog "C vs ${target} encode mismatches for ${clip}, at ${bitrate} kbps, speed ${cpu}, ${preset} preset" | 
|  | return 1 | 
|  | fi | 
|  | } | 
|  |  | 
|  | av1_enc_test() { | 
|  | local encoder="$1" | 
|  | local arch="$2" | 
|  | local target="$3" | 
|  | local preset="$4" | 
|  | if [ -z "$(av1_enc_tool_path "${target}"  "${preset}")" ]; then | 
|  | elog "aomenc_${preset} not found. It must exist in ${AOM_TEST_OUTPUT_DIR}/build_target_${target} path" | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | if [ "${preset}" = "good" ]; then | 
|  | case "${arch}" in | 
|  | arm64) | 
|  | # Speed 0 is not tested as arm64 is run under emulation. | 
|  | local min_cpu_used=1 | 
|  | local max_cpu_used=6 | 
|  | ;; | 
|  | x86) | 
|  | # x86 has a good amount of overlap with x86-64. Only a few values are | 
|  | # tested to improve the runtime of the script. | 
|  | local min_cpu_used=2 | 
|  | local max_cpu_used=3 | 
|  | ;; | 
|  | *) | 
|  | local min_cpu_used=0 | 
|  | local max_cpu_used=6 | 
|  | ;; | 
|  | esac | 
|  | local test_params=av1_encode_good_params | 
|  | elif [ "${preset}" = "rt" ]; then | 
|  | local min_cpu_used=5 | 
|  | local max_cpu_used=11 | 
|  | local test_params=av1_encode_rt_params | 
|  | else | 
|  | elog "Invalid preset" | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | for cpu in $(seq $min_cpu_used $max_cpu_used); do | 
|  | if [ "${preset}" = "good" ]; then | 
|  | if [ "${arch}" = "x86_64" -o "${arch}" = "arm64" ]; then | 
|  | if [ "${cpu}" -lt 2 ]; then | 
|  | local test_clips="${LOWBD_CIF_CLIP} ${HIGHBD_CLIP}" | 
|  | elif [ "${cpu}" -lt 5 ]; then | 
|  | local test_clips="${LOWBD_480p_CLIP} ${HIGHBD_CLIP}" | 
|  | else | 
|  | local test_clips="${LOWBD_720p_CLIP} ${HIGHBD_CLIP}" | 
|  | fi | 
|  | elif [ "${arch}" = "x86" ]; then | 
|  | local test_clips="${LOWBD_CIF_CLIP} ${HIGHBD_CLIP}" | 
|  | else | 
|  | elog "Unknown architecture: ${arch}" | 
|  | return 1 | 
|  | fi | 
|  | elif [ "${preset}" = "rt" ]; then | 
|  | if [ "${cpu}" -lt 8 ]; then | 
|  | local test_clips="${LOWBD_CIF_CLIP} ${SC_CLIP}" | 
|  | else | 
|  | local test_clips="${LOWBD_480p_CLIP} ${SC_CLIP}" | 
|  | fi | 
|  | else | 
|  | elog "Invalid preset" | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | for clip in ${test_clips}; do | 
|  | local test_bitrates=$(get_bitrates ${clip} ${preset}) | 
|  | for bitrate in ${test_bitrates}; do | 
|  | eval "${encoder}" $($clip) $($test_params) \ | 
|  | "--limit=${AV1_ENCODE_C_VS_SIMD_TEST_FRAME_LIMIT}" \ | 
|  | "--cpu-used=${cpu}" "--target-bitrate=${bitrate}" "-o" \ | 
|  | ${AOM_TEST_OUTPUT_DIR}/Out-${target}-"${clip}"-${preset}-${bitrate}kbps-cpu${cpu}${OUT_FILE_SUFFIX} \ | 
|  | ${devnull} | 
|  |  | 
|  | if [ "${target}" != "generic" ]; then | 
|  | if ! compare_enc_output ${target} $cpu ${clip} $bitrate ${preset}; then | 
|  | # Found a mismatch | 
|  | return 1 | 
|  | fi | 
|  | fi | 
|  | done | 
|  | done | 
|  | done | 
|  | } | 
|  |  | 
|  | av1_test_generic() { | 
|  | local arch=$1 | 
|  | local target="generic" | 
|  | if [ $arch = "x86_64" ]; then | 
|  | local cmake_command="cmake $LIBAOM_SOURCE_DIR -DAOM_TARGET_CPU=${target}" | 
|  | elif [ $arch = "x86" ]; then | 
|  | # As AV1 encode output differs for x86 32-bit and 64-bit platforms | 
|  | # (BUG=aomedia:3479), the x86 32-bit C-only build is generated separately. | 
|  | # The cmake command line option -DENABLE_MMX=0 flag disables all SIMD | 
|  | # optimizations, and generates a C-only binary. | 
|  | local cmake_command="cmake $LIBAOM_SOURCE_DIR -DENABLE_MMX=0 \ | 
|  | -DCMAKE_TOOLCHAIN_FILE=${LIBAOM_SOURCE_DIR}/build/cmake/toolchains/i686-linux-gcc.cmake" | 
|  | fi | 
|  |  | 
|  | echo "Build for: Generic ${arch}" | 
|  | if ! av1_enc_build "${target}" "${cmake_command}"; then | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | for preset in $PRESETS; do | 
|  | local encoder="$(av1_enc_tool_path "${target}" "${preset}")" | 
|  | av1_enc_test $encoder "${arch}" "${target}" "${preset}" | 
|  | done | 
|  | } | 
|  |  | 
|  | # This function encodes AV1 bitstream by enabling SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, AVX, AVX2 as | 
|  | # there are no functions with MMX, SSE and AVX512 specialization. | 
|  | # The value of environment variable 'AOM_SIMD_CAPS_MASK' controls enabling of different instruction | 
|  | # set extension optimizations. The value of the flag 'AOM_SIMD_CAPS_MASK' and the corresponding | 
|  | # instruction set extension optimization enabled are as follows: | 
|  | # SSE4_2 AVX2 AVX SSE4_1 SSSE3 SSE3 SSE2 SSE MMX | 
|  | #   1     1    1    1      1    1    1    1   1  -> 0x1FF -> Enable AVX2 and lower variants | 
|  | #   1     0    1    1      1    1    1    1   1  -> 0x17F -> Enable AVX and lower variants | 
|  | #   1     0    0    1      1    1    1    1   1  -> 0x13F -> Enable SSE4_2 and lower variants | 
|  | #   0     0    0    1      1    1    1    1   1  -> 0x03F -> Enable SSE4_1 and lower variants | 
|  | #   0     0    0    0      1    1    1    1   1  -> 0x01F -> Enable SSSE3 and lower variants | 
|  | #   0     0    0    0      0    1    1    1   1  -> 0x00F -> Enable SSE3 and lower variants | 
|  | #   0     0    0    0      0    0    1    1   1  -> 0x007 -> Enable SSE2 and lower variants | 
|  | #   0     0    0    0      0    0    0    1   1  -> 0x003 -> Enable SSE and lower variants | 
|  | #   0     0    0    0      0    0    0    0   1  -> 0x001 -> Enable MMX | 
|  | ## NOTE: In x86_64 platform, it is not possible to enable sse/mmx/c using "AOM_SIMD_CAPS_MASK" as | 
|  | #  all x86_64 platforms implement sse2. | 
|  | av1_test_x86() { | 
|  | local arch=$1 | 
|  |  | 
|  | if ! uname -m | grep -q "x86"; then | 
|  | elog "Machine architecture is not x86 or x86_64" | 
|  | return 0 | 
|  | fi | 
|  |  | 
|  | if [ $arch = "x86" ]; then | 
|  | local target="x86-linux" | 
|  | local cmake_command="cmake \ | 
|  | $LIBAOM_SOURCE_DIR \ | 
|  | -DCMAKE_TOOLCHAIN_FILE=${LIBAOM_SOURCE_DIR}/build/cmake/toolchains/i686-linux-gcc.cmake" | 
|  | elif [ $arch = "x86_64" ]; then | 
|  | local target="x86_64-linux" | 
|  | local cmake_command="cmake $LIBAOM_SOURCE_DIR" | 
|  | fi | 
|  |  | 
|  | # Available x86 isa variants: "avx2 avx sse4_2 sse4_1 ssse3 sse3 sse2" | 
|  | local x86_isa_variants="avx2 sse4_2 sse2" | 
|  |  | 
|  | echo "Build for x86: ${target}" | 
|  | if ! av1_enc_build "${target}" "${cmake_command}"; then | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | for preset in $PRESETS; do | 
|  | local encoder="$(av1_enc_tool_path "${target}" "${preset}")" | 
|  | for isa in $x86_isa_variants; do | 
|  | # Note that if has_x86_isa_extn returns 1, it is false, and vice versa. | 
|  | if ! has_x86_isa_extn $isa; then | 
|  | echo "${isa} is not supported in this machine" | 
|  | continue | 
|  | fi | 
|  | export AOM_SIMD_CAPS_MASK=$($isa) | 
|  | if ! av1_enc_test $encoder "${arch}" "${target}" "${preset}"; then | 
|  | # Found a mismatch | 
|  | return 1 | 
|  | fi | 
|  | unset AOM_SIMD_CAPS_MASK | 
|  | done | 
|  | done | 
|  | } | 
|  |  | 
|  | av1_test_arm() { | 
|  | local arch="arm64" | 
|  | local target="arm64-linux-gcc" | 
|  | local cmake_command="cmake $LIBAOM_SOURCE_DIR \ | 
|  | -DCMAKE_TOOLCHAIN_FILE=$LIBAOM_SOURCE_DIR/build/cmake/toolchains/${target}.cmake \ | 
|  | -DCMAKE_C_FLAGS=-Wno-maybe-uninitialized" | 
|  | echo "Build for arm64: ${target}" | 
|  | if ! av1_enc_build "${target}" "${cmake_command}"; then | 
|  | return 1 | 
|  | fi | 
|  |  | 
|  | for preset in $PRESETS; do | 
|  | local encoder="$(av1_enc_tool_path "${target}" "${preset}")" | 
|  | if ! av1_enc_test "qemu-aarch64 -L /usr/aarch64-linux-gnu ${encoder}" "${arch}" "${target}" "${preset}"; then | 
|  | # Found a mismatch | 
|  | return 1 | 
|  | fi | 
|  | done | 
|  | } | 
|  |  | 
|  | av1_c_vs_simd_enc_test () { | 
|  | # Test x86 (32 bit) | 
|  | # x86 requires the i686-linux-gnu toolchain: | 
|  | # $ sudo apt-get install g++-i686-linux-gnu | 
|  | echo "av1 test for x86 (32 bit): Started." | 
|  | # Encode 'C' only | 
|  | av1_test_generic "x86" | 
|  | # Encode with SIMD optimizations enabled | 
|  | if ! av1_test_x86 "x86"; then | 
|  | echo "av1 test for x86 (32 bit): Done, test failed." | 
|  | return 1 | 
|  | else | 
|  | echo "av1 test for x86 (32 bit): Done, all tests passed." | 
|  | fi | 
|  |  | 
|  | # Test x86_64 (64 bit) | 
|  | if [ "$(eval uname -m)" = "x86_64" ]; then | 
|  | echo "av1 test for x86_64 (64 bit): Started." | 
|  | # Encode 'C' only | 
|  | av1_test_generic "x86_64" | 
|  | # Encode with SIMD optimizations enabled | 
|  | if ! av1_test_x86 "x86_64"; then | 
|  | echo "av1 test for x86_64 (64 bit): Done, test failed." | 
|  | return 1 | 
|  | else | 
|  | echo "av1 test for x86_64 (64 bit): Done, all tests passed." | 
|  | fi | 
|  | fi | 
|  |  | 
|  | # Test ARM | 
|  | echo "av1_test_arm: Started." | 
|  | if ! av1_test_arm; then | 
|  | echo "av1 test for arm: Done, test failed." | 
|  | return 1 | 
|  | else | 
|  | echo "av1 test for arm: Done, all tests passed." | 
|  | fi | 
|  | } | 
|  |  | 
|  | run_tests av1_c_vs_simd_enc_verify_environment av1_c_vs_simd_enc_test |