1#!/bin/sh
2##
3##  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
4##
5##  Use of this source code is governed by a BSD-style license
6##  that can be found in the LICENSE file in the root of the source
7##  tree. An additional intellectual property rights grant can be found
8##  in the file PATENTS.  All contributing project authors may
9##  be found in the AUTHORS file in the root of the source tree.
10##
11##  This file performs a stress test. It runs (STRESS_ONEPASS_MAX_JOBS,
12##  default=5) one, (STRESS_TWOPASS_MAX_JOBS, default=5) two pass &
13##  (STRESS_RT_MAX_JOBS, default=5) encodes and (STRESS_<codec>_DECODE_MAX_JOBS,
14##  default=30) decodes in parallel.
15
16. $(dirname $0)/tools_common.sh
17
18YUV="${LIBVPX_TEST_DATA_PATH}/niklas_1280_720_30.yuv"
19VP8="${LIBVPX_TEST_DATA_PATH}/tos_vp8.webm"
20VP9="${LIBVPX_TEST_DATA_PATH}/vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm"
21DATA_URL="http://downloads.webmproject.org/test_data/libvpx/"
22SHA1_FILE="$(dirname $0)/test-data.sha1"
23
24# Set sha1sum to proper sha program (sha1sum, shasum, sha1). This code is
25# cribbed from libs.mk.
26[ -x "$(which sha1sum)" ] && sha1sum=sha1sum
27[ -x "$(which shasum)" ] && sha1sum=shasum
28[ -x "$(which sha1)" ] && sha1sum=sha1
29
30# Download a file from the url and check its sha1sum.
31download_and_check_file() {
32  # Get the file from the file path.
33  local readonly root="${1#${LIBVPX_TEST_DATA_PATH}/}"
34
35  # Download the file using curl. Trap to insure non partial file.
36  (trap "rm -f $1" INT TERM \
37    && eval "curl --retry 1 -L -o $1 ${DATA_URL}${root} ${devnull}")
38
39  # Check the sha1 sum of the file.
40  if [ -n "${sha1sum}" ]; then
41    set -e
42    grep ${root} ${SHA1_FILE} \
43      | (cd ${LIBVPX_TEST_DATA_PATH}; ${sha1sum} -c);
44  fi
45}
46
47# Environment check: Make sure input is available.
48stress_verify_environment() {
49  if [ ! -e "${SHA1_FILE}" ] ; then
50    echo "Missing ${SHA1_FILE}"
51    return 1
52  fi
53  for file in "${YUV}" "${VP8}" "${VP9}"; do
54    if [ ! -e "${file}" ] ; then
55      download_and_check_file "${file}"
56    fi
57  done
58  if [ ! -e "${YUV}" ] || [ ! -e "${VP8}" ] || [ ! -e "${VP9}" ] ; then
59    elog "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
60    return 1
61  fi
62  if [ -z "$(vpx_tool_path vpxenc)" ]; then
63    elog "vpxenc not found. It must exist in LIBVPX_BIN_PATH or its parent."
64    return 1
65  fi
66  if [ -z "$(vpx_tool_path vpxdec)" ]; then
67    elog "vpxdec not found. It must exist in LIBVPX_BIN_PATH or its parent."
68    return 1
69  fi
70}
71
72# This function runs tests on libvpx that run multiple encodes and decodes
73# in parallel in hopes of catching synchronization and/or threading issues.
74stress() {
75  local readonly decoder="$(vpx_tool_path vpxdec)"
76  local readonly encoder="$(vpx_tool_path vpxenc)"
77  local readonly codec="$1"
78  local readonly webm="$2"
79  local readonly decode_count="$3"
80  local readonly threads="$4"
81  local readonly enc_args="$5"
82  local pids=""
83  local rt_max_jobs=${STRESS_RT_MAX_JOBS:-5}
84  local onepass_max_jobs=${STRESS_ONEPASS_MAX_JOBS:-5}
85  local twopass_max_jobs=${STRESS_TWOPASS_MAX_JOBS:-5}
86
87  # Enable job control, so we can run multiple processes.
88  set -m
89
90  # Start $onepass_max_jobs encode jobs in parallel.
91  for i in $(seq ${onepass_max_jobs}); do
92    bitrate=$(($i * 20 + 300))
93    eval "${VPX_TEST_PREFIX}" "${encoder}" "--codec=${codec} -w 1280 -h 720" \
94      "${YUV}" "-t ${threads} --limit=150 --test-decode=fatal --passes=1" \
95      "--target-bitrate=${bitrate} -o ${VPX_TEST_OUTPUT_DIR}/${i}.1pass.webm" \
96      "${enc_args}" ${devnull} &
97    pids="${pids} $!"
98  done
99
100  # Start $twopass_max_jobs encode jobs in parallel.
101  for i in $(seq ${twopass_max_jobs}); do
102    bitrate=$(($i * 20 + 300))
103    eval "${VPX_TEST_PREFIX}" "${encoder}" "--codec=${codec} -w 1280 -h 720" \
104      "${YUV}" "-t ${threads} --limit=150 --test-decode=fatal --passes=2" \
105      "--target-bitrate=${bitrate} -o ${VPX_TEST_OUTPUT_DIR}/${i}.2pass.webm" \
106      "${enc_args}" ${devnull} &
107    pids="${pids} $!"
108  done
109
110  # Start $rt_max_jobs rt encode jobs in parallel.
111  for i in $(seq ${rt_max_jobs}); do
112    bitrate=$(($i * 20 + 300))
113    eval "${VPX_TEST_PREFIX}" "${encoder}" "--codec=${codec} -w 1280 -h 720" \
114      "${YUV}" "-t ${threads} --limit=150 --test-decode=fatal " \
115      "--target-bitrate=${bitrate} --lag-in-frames=0 --error-resilient=1" \
116      "--kf-min-dist=3000 --kf-max-dist=3000 --cpu-used=-6 --static-thresh=1" \
117      "--end-usage=cbr --min-q=2 --max-q=56 --undershoot-pct=100" \
118      "--overshoot-pct=15 --buf-sz=1000 --buf-initial-sz=500" \
119      "--buf-optimal-sz=600 --max-intra-rate=900 --resize-allowed=0" \
120      "--drop-frame=0 --passes=1 --rt --noise-sensitivity=4" \
121      "-o ${VPX_TEST_OUTPUT_DIR}/${i}.rt.webm" ${devnull} &
122    pids="${pids} $!"
123  done
124
125  # Start $decode_count decode jobs in parallel.
126  for i in $(seq "${decode_count}"); do
127    eval "${decoder}" "-t ${threads}" "${webm}" "--noblit" ${devnull} &
128    pids="${pids} $!"
129  done
130
131  # Wait for all parallel jobs to finish.
132  fail=0
133  for job in "${pids}"; do
134    wait $job || fail=$(($fail + 1))
135  done
136  return $fail
137}
138
139vp8_stress_test() {
140  local vp8_max_jobs=${STRESS_VP8_DECODE_MAX_JOBS:-40}
141  if [ "$(vp8_decode_available)" = "yes" -a \
142       "$(vp8_encode_available)" = "yes" ]; then
143    stress vp8 "${VP8}" "${vp8_max_jobs}" 4
144  fi
145}
146
147vp9_stress() {
148  local vp9_max_jobs=${STRESS_VP9_DECODE_MAX_JOBS:-25}
149
150  if [ "$(vp9_decode_available)" = "yes" -a \
151       "$(vp9_encode_available)" = "yes" ]; then
152    stress vp9 "${VP9}" "${vp9_max_jobs}" "$@"
153  fi
154}
155
156vp9_stress_test() {
157  for threads in 4 8 100; do
158    vp9_stress "$threads" "--row-mt=0"
159  done
160}
161
162vp9_stress_test_row_mt() {
163  for threads in 4 8 100; do
164    vp9_stress "$threads" "--row-mt=1"
165  done
166}
167
168run_tests stress_verify_environment \
169  "vp8_stress_test vp9_stress_test vp9_stress_test_row_mt"
170