| 1 | #! /bin/sh |
| 2 | |
| 3 | export LC_ALL=C |
| 4 | |
| 5 | base=$(dirname $0) |
| 6 | . "${base}/md5.sh" |
| 7 | |
| 8 | base64=tests/base64 |
| 9 | |
| 10 | test="${1#fate-}" |
| 11 | target_samples=$2 |
| 12 | target_exec=$3 |
| 13 | target_path=$4 |
| 14 | command=$5 |
| 15 | cmp=${6:-diff} |
| 16 | ref=${7:-"${base}/ref/fate/${test}"} |
| 17 | fuzz=${8:-1} |
| 18 | threads=${9:-1} |
| 19 | thread_type=${10:-frame+slice} |
| 20 | cpuflags=${11:-all} |
| 21 | cmp_shift=${12:-0} |
| 22 | cmp_target=${13:-0} |
| 23 | size_tolerance=${14:-0} |
| 24 | cmp_unit=${15:-2} |
| 25 | gen=${16:-no} |
| 26 | |
| 27 | outdir="tests/data/fate" |
| 28 | outfile="${outdir}/${test}" |
| 29 | errfile="${outdir}/${test}.err" |
| 30 | cmpfile="${outdir}/${test}.diff" |
| 31 | repfile="${outdir}/${test}.rep" |
| 32 | |
| 33 | target_path(){ |
| 34 | test ${1} = ${1#/} && p=${target_path}/ |
| 35 | echo ${p}${1} |
| 36 | } |
| 37 | |
| 38 | # $1=value1, $2=value2, $3=threshold |
| 39 | # prints 0 if absolute difference between value1 and value2 is <= threshold |
| 40 | compare(){ |
| 41 | echo "scale=2; v = $1 - $2; if (v < 0) v = -v; if (v > $3) r = 1; r" | bc |
| 42 | } |
| 43 | |
| 44 | do_tiny_psnr(){ |
| 45 | psnr=$(tests/tiny_psnr "$1" "$2" $cmp_unit $cmp_shift 0) |
| 46 | val=$(expr "$psnr" : ".*$3: *\([0-9.]*\)") |
| 47 | size1=$(expr "$psnr" : '.*bytes: *\([0-9]*\)') |
| 48 | size2=$(expr "$psnr" : '.*bytes:[ 0-9]*/ *\([0-9]*\)') |
| 49 | val_cmp=$(compare $val $cmp_target $fuzz) |
| 50 | size_cmp=$(compare $size1 $size2 $size_tolerance) |
| 51 | if [ "$val_cmp" != 0 ] || [ "$size_cmp" != 0 ]; then |
| 52 | echo "$psnr" |
| 53 | return 1 |
| 54 | fi |
| 55 | } |
| 56 | |
| 57 | oneoff(){ |
| 58 | do_tiny_psnr "$1" "$2" MAXDIFF |
| 59 | } |
| 60 | |
| 61 | stddev(){ |
| 62 | do_tiny_psnr "$1" "$2" stddev |
| 63 | } |
| 64 | |
| 65 | oneline(){ |
| 66 | printf '%s\n' "$1" | diff -u -b - "$2" |
| 67 | } |
| 68 | |
| 69 | run(){ |
| 70 | test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 |
| 71 | $target_exec $target_path/"$@" |
| 72 | } |
| 73 | |
| 74 | runecho(){ |
| 75 | test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 |
| 76 | $target_exec $target_path/"$@" >&3 |
| 77 | } |
| 78 | |
| 79 | probefmt(){ |
| 80 | run ffprobe -show_entries format=format_name -print_format default=nw=1:nk=1 -v 0 "$@" |
| 81 | } |
| 82 | |
| 83 | probeframes(){ |
| 84 | run ffprobe -show_frames -v 0 "$@" |
| 85 | } |
| 86 | |
| 87 | ffmpeg(){ |
| 88 | dec_opts="-threads $threads -thread_type $thread_type" |
| 89 | ffmpeg_args="-nostats -cpuflags $cpuflags" |
| 90 | for arg in $@; do |
| 91 | [ x${arg} = x-i ] && ffmpeg_args="${ffmpeg_args} ${dec_opts}" |
| 92 | ffmpeg_args="${ffmpeg_args} ${arg}" |
| 93 | done |
| 94 | run ffmpeg ${ffmpeg_args} |
| 95 | } |
| 96 | |
| 97 | framecrc(){ |
| 98 | ffmpeg "$@" -flags +bitexact -f framecrc - |
| 99 | } |
| 100 | |
| 101 | framemd5(){ |
| 102 | ffmpeg "$@" -flags +bitexact -f framemd5 - |
| 103 | } |
| 104 | |
| 105 | crc(){ |
| 106 | ffmpeg "$@" -f crc - |
| 107 | } |
| 108 | |
| 109 | md5(){ |
| 110 | ffmpeg "$@" md5: |
| 111 | } |
| 112 | |
| 113 | pcm(){ |
| 114 | ffmpeg "$@" -vn -f s16le - |
| 115 | } |
| 116 | |
| 117 | fmtstdout(){ |
| 118 | fmt=$1 |
| 119 | shift 1 |
| 120 | ffmpeg -flags +bitexact "$@" -f $fmt - |
| 121 | } |
| 122 | |
| 123 | enc_dec_pcm(){ |
| 124 | out_fmt=$1 |
| 125 | dec_fmt=$2 |
| 126 | pcm_fmt=$3 |
| 127 | src_file=$(target_path $4) |
| 128 | shift 4 |
| 129 | encfile="${outdir}/${test}.${out_fmt}" |
| 130 | cleanfiles=$encfile |
| 131 | encfile=$(target_path ${encfile}) |
| 132 | ffmpeg -i $src_file "$@" -f $out_fmt -y ${encfile} || return |
| 133 | ffmpeg -flags +bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -f ${dec_fmt} - |
| 134 | } |
| 135 | |
| 136 | FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" |
| 137 | DEC_OPTS="-threads $threads -idct simple $FLAGS" |
| 138 | ENC_OPTS="-threads 1 -idct simple -dct fastint" |
| 139 | |
| 140 | enc_dec(){ |
| 141 | src_fmt=$1 |
| 142 | srcfile=$2 |
| 143 | enc_fmt=$3 |
| 144 | enc_opt=$4 |
| 145 | dec_fmt=$5 |
| 146 | dec_opt=$6 |
| 147 | encfile="${outdir}/${test}.${enc_fmt}" |
| 148 | decfile="${outdir}/${test}.out.${dec_fmt}" |
| 149 | cleanfiles="$cleanfiles $decfile" |
| 150 | test "$7" = -keep || cleanfiles="$cleanfiles $encfile" |
| 151 | tsrcfile=$(target_path $srcfile) |
| 152 | tencfile=$(target_path $encfile) |
| 153 | tdecfile=$(target_path $decfile) |
| 154 | ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ |
| 155 | -f $enc_fmt -y $tencfile || return |
| 156 | do_md5sum $encfile |
| 157 | echo $(wc -c $encfile) |
| 158 | ffmpeg $8 $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt $FLAGS \ |
| 159 | -f $dec_fmt -y $tdecfile || return |
| 160 | do_md5sum $decfile |
| 161 | tests/tiny_psnr $srcfile $decfile $cmp_unit $cmp_shift |
| 162 | } |
| 163 | |
| 164 | lavffatetest(){ |
| 165 | t="${test#lavf-fate-}" |
| 166 | ref=${base}/ref/lavf-fate/$t |
| 167 | ${base}/lavf-regression.sh $t lavf-fate tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$target_samples" |
| 168 | } |
| 169 | |
| 170 | lavftest(){ |
| 171 | t="${test#lavf-}" |
| 172 | ref=${base}/ref/lavf/$t |
| 173 | ${base}/lavf-regression.sh $t lavf tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$target_samples" |
| 174 | } |
| 175 | |
| 176 | video_filter(){ |
| 177 | filters=$1 |
| 178 | shift |
| 179 | label=${test#filter-} |
| 180 | raw_src="${target_path}/tests/vsynth1/%02d.pgm" |
| 181 | printf '%-20s' $label |
| 182 | ffmpeg $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src \ |
| 183 | $FLAGS $ENC_OPTS -vf "$filters" -vcodec rawvideo $* -f nut md5: |
| 184 | } |
| 185 | |
| 186 | pixfmts(){ |
| 187 | filter=${test#filter-pixfmts-} |
| 188 | filter=${filter%_*} |
| 189 | filter_args=$1 |
| 190 | prefilter_chain=$2 |
| 191 | |
| 192 | showfiltfmts="$target_exec $target_path/libavfilter/filtfmts-test" |
| 193 | scale_exclude_fmts=${outfile}_scale_exclude_fmts |
| 194 | scale_in_fmts=${outfile}_scale_in_fmts |
| 195 | scale_out_fmts=${outfile}_scale_out_fmts |
| 196 | in_fmts=${outfile}_in_fmts |
| 197 | |
| 198 | # exclude pixel formats which are not supported as input |
| 199 | $showfiltfmts scale | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$scale_in_fmts |
| 200 | $showfiltfmts scale | awk -F '[ \r]' '/^OUTPUT/{ fmt=substr($3, 5); print fmt }' | sort >$scale_out_fmts |
| 201 | comm -12 $scale_in_fmts $scale_out_fmts >$scale_exclude_fmts |
| 202 | |
| 203 | $showfiltfmts $filter | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$in_fmts |
| 204 | pix_fmts=$(comm -12 $scale_exclude_fmts $in_fmts) |
| 205 | |
| 206 | outertest=$test |
| 207 | for pix_fmt in $pix_fmts; do |
| 208 | test=$pix_fmt |
| 209 | video_filter "${prefilter_chain}format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt |
| 210 | done |
| 211 | |
| 212 | rm $in_fmts $scale_in_fmts $scale_out_fmts $scale_exclude_fmts |
| 213 | test=$outertest |
| 214 | } |
| 215 | |
| 216 | mkdir -p "$outdir" |
| 217 | |
| 218 | # Disable globbing: command arguments may contain globbing characters and |
| 219 | # must be kept verbatim |
| 220 | set -f |
| 221 | |
| 222 | exec 3>&2 |
| 223 | eval $command >"$outfile" 2>$errfile |
| 224 | err=$? |
| 225 | |
| 226 | if [ $err -gt 128 ]; then |
| 227 | sig=$(kill -l $err 2>/dev/null) |
| 228 | test "${sig}" = "${sig%[!A-Za-z]*}" || unset sig |
| 229 | fi |
| 230 | |
| 231 | if test -e "$ref" || test $cmp = "oneline" ; then |
| 232 | case $cmp in |
| 233 | diff) diff -u -b "$ref" "$outfile" >$cmpfile ;; |
| 234 | rawdiff)diff -u "$ref" "$outfile" >$cmpfile ;; |
| 235 | oneoff) oneoff "$ref" "$outfile" >$cmpfile ;; |
| 236 | stddev) stddev "$ref" "$outfile" >$cmpfile ;; |
| 237 | oneline)oneline "$ref" "$outfile" >$cmpfile ;; |
| 238 | null) cat "$outfile" >$cmpfile ;; |
| 239 | esac |
| 240 | cmperr=$? |
| 241 | test $err = 0 && err=$cmperr |
| 242 | test $err = 0 || cat $cmpfile |
| 243 | else |
| 244 | echo "reference file '$ref' not found" |
| 245 | err=1 |
| 246 | fi |
| 247 | |
| 248 | echo "${test}:${sig:-$err}:$($base64 <$cmpfile):$($base64 <$errfile)" >$repfile |
| 249 | |
| 250 | if test $err != 0 && test $gen != "no" ; then |
| 251 | echo "GEN $ref" |
| 252 | cp -f "$outfile" "$ref" |
| 253 | err=$? |
| 254 | fi |
| 255 | |
| 256 | if test $err = 0; then |
| 257 | rm -f $outfile $errfile $cmpfile $cleanfiles |
| 258 | elif test $gen = "no"; then |
| 259 | echo "Test $test failed. Look at $errfile for details." |
| 260 | test "${V:-0}" -gt 0 && cat $errfile |
| 261 | else |
| 262 | echo "Updating reference failed, possibly no output file was generated." |
| 263 | fi |
| 264 | exit $err |