1#! /bin/sh 2 3export LC_ALL=C 4 5base=$(dirname $0) 6. "${base}/md5.sh" 7 8base64=tests/base64${HOSTEXECSUF} 9 10test="${1#fate-}" 11target_samples=$2 12target_exec=$3 13target_path=$4 14command=$5 15cmp=${6:-diff} 16ref=${7:-"${base}/ref/fate/${test}"} 17fuzz=${8:-1} 18threads=${9:-1} 19thread_type=${10:-frame+slice} 20cpuflags=${11:-all} 21cmp_shift=${12:-0} 22cmp_target=${13:-0} 23size_tolerance=${14:-0} 24cmp_unit=${15:-2} 25gen=${16:-no} 26hwaccel=${17:-none} 27report_type=${18:-standard} 28keep=${19:-0} 29 30outdir="tests/data/fate" 31outfile="${outdir}/${test}" 32errfile="${outdir}/${test}.err" 33cmpfile="${outdir}/${test}.diff" 34repfile="${outdir}/${test}.rep" 35 36target_path(){ 37 test ${1} = ${1#/} && p=${target_path}/ 38 echo ${p}${1} 39} 40 41# $1=value1, $2=value2, $3=threshold 42# prints 0 if absolute difference between value1 and value2 is <= threshold 43compare(){ 44 awk "BEGIN { v = $1 - $2; printf ((v < 0 ? -v : v) > $3) }" 45} 46 47do_tiny_psnr(){ 48 psnr=$(tests/tiny_psnr${HOSTEXECSUF} "$1" "$2" $cmp_unit $cmp_shift 0) || return 1 49 val=$(expr "$psnr" : ".*$3: *\([0-9.]*\)") 50 size1=$(expr "$psnr" : '.*bytes: *\([0-9]*\)') 51 size2=$(expr "$psnr" : '.*bytes:[ 0-9]*/ *\([0-9]*\)') 52 val_cmp=$(compare $val $cmp_target $fuzz) 53 size_cmp=$(compare $size1 $size2 $size_tolerance) 54 if [ "$val_cmp" != 0 ] || [ "$size_cmp" != 0 ]; then 55 echo "$psnr" 56 if [ "$val_cmp" != 0 ]; then 57 echo "$3: |$val - $cmp_target| >= $fuzz" 58 fi 59 if [ "$size_cmp" != 0 ]; then 60 echo "size: |$size1 - $size2| >= $size_tolerance" 61 fi 62 return 1 63 fi 64} 65 66oneoff(){ 67 do_tiny_psnr "$1" "$2" MAXDIFF 68} 69 70stddev(){ 71 do_tiny_psnr "$1" "$2" stddev 72} 73 74oneline(){ 75 printf '%s\n' "$1" | diff -u -b - "$2" 76} 77 78run(){ 79 test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 80 $target_exec $target_path/"$@" 81} 82 83runecho(){ 84 test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 85 $target_exec $target_path/"$@" >&3 86} 87 88probefmt(){ 89 run ffprobe${PROGSUF}${EXECSUF} -show_entries format=format_name -print_format default=nw=1:nk=1 -v 0 "$@" 90} 91 92probetags(){ 93 run ffprobe${PROGSUF}${EXECSUF} -show_entries format_tags -v 0 "$@" 94} 95 96runlocal(){ 97 test "${V:-0}" -gt 0 && echo ${base}/"$@" ${base} >&3 98 ${base}/"$@" ${base} 99} 100 101probeframes(){ 102 run ffprobe${PROGSUF}${EXECSUF} -show_frames -v 0 "$@" 103} 104 105probechapters(){ 106 run ffprobe${PROGSUF}${EXECSUF} -show_chapters -v 0 "$@" 107} 108 109probegaplessinfo(){ 110 filename="$1" 111 shift 112 run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -show_entries format=start_time,duration:stream=index,start_pts,duration_ts -v 0 "$filename" "$@" 113 pktfile1="${outdir}/${test}.pkts" 114 framefile1="${outdir}/${test}.frames" 115 cleanfiles="$cleanfiles $pktfile1 $framefile1" 116 run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -of compact -count_packets -show_entries packet=pts,dts,duration,flags:stream=nb_read_packets -v 0 "$filename" "$@" > "$pktfile1" 117 head -n 8 "$pktfile1" 118 tail -n 9 "$pktfile1" 119 run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -of compact -count_frames -show_entries frame=pkt_pts,pkt_dts,best_effort_timestamp,pkt_duration,nb_samples:stream=nb_read_frames -v 0 "$filename" "$@" > "$framefile1" 120 head -n 8 "$framefile1" 121 tail -n 9 "$framefile1" 122} 123 124ffmpeg(){ 125 dec_opts="-hwaccel $hwaccel -threads $threads -thread_type $thread_type" 126 ffmpeg_args="-nostdin -nostats -cpuflags $cpuflags" 127 for arg in $@; do 128 [ x${arg} = x-i ] && ffmpeg_args="${ffmpeg_args} ${dec_opts}" 129 ffmpeg_args="${ffmpeg_args} ${arg}" 130 done 131 run ffmpeg${PROGSUF}${EXECSUF} ${ffmpeg_args} 132} 133 134framecrc(){ 135 ffmpeg "$@" -bitexact -f framecrc - 136} 137 138ffmetadata(){ 139 ffmpeg "$@" -bitexact -f ffmetadata - 140} 141 142framemd5(){ 143 ffmpeg "$@" -bitexact -f framemd5 - 144} 145 146crc(){ 147 ffmpeg "$@" -f crc - 148} 149 150md5pipe(){ 151 ffmpeg "$@" md5: 152} 153 154md5(){ 155 encfile="${outdir}/${test}.out" 156 cleanfiles="$cleanfiles $encfile" 157 ffmpeg "$@" $(target_path $encfile) 158 do_md5sum $encfile | awk '{print $1}' 159} 160 161pcm(){ 162 ffmpeg "$@" -vn -f s16le - 163} 164 165fmtstdout(){ 166 fmt=$1 167 shift 1 168 ffmpeg -bitexact "$@" -f $fmt - 169} 170 171enc_dec_pcm(){ 172 out_fmt=$1 173 dec_fmt=$2 174 pcm_fmt=$3 175 src_file=$(target_path $4) 176 shift 4 177 encfile="${outdir}/${test}.${out_fmt}" 178 cleanfiles=$encfile 179 encfile=$(target_path ${encfile}) 180 ffmpeg -i $src_file "$@" -f $out_fmt -y ${encfile} || return 181 ffmpeg -bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -fflags +bitexact -f ${dec_fmt} - 182} 183 184FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" 185DEC_OPTS="-threads $threads -idct simple $FLAGS" 186ENC_OPTS="-threads 1 -idct simple -dct fastint" 187 188enc_dec(){ 189 src_fmt=$1 190 srcfile=$2 191 enc_fmt=$3 192 enc_opt=$4 193 dec_fmt=$5 194 dec_opt=$6 195 ffprobe_opts=$9 196 encfile="${outdir}/${test}.${enc_fmt}" 197 decfile="${outdir}/${test}.out.${dec_fmt}" 198 cleanfiles="$cleanfiles $decfile" 199 test "$7" = -keep || cleanfiles="$cleanfiles $encfile" 200 tsrcfile=$(target_path $srcfile) 201 tencfile=$(target_path $encfile) 202 tdecfile=$(target_path $decfile) 203 ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ 204 -f $enc_fmt -y $tencfile || return 205 do_md5sum $encfile 206 echo $(wc -c $encfile) 207 ffmpeg $8 $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt $FLAGS \ 208 -f $dec_fmt -y $tdecfile || return 209 do_md5sum $decfile 210 tests/tiny_psnr${HOSTEXECSUF} $srcfile $decfile $cmp_unit $cmp_shift 211 test -z $ffprobe_opts || \ 212 run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts -v 0 $tencfile || return 213} 214 215transcode(){ 216 src_fmt=$1 217 srcfile=$2 218 enc_fmt=$3 219 enc_opt=$4 220 final_decode=$5 221 ffprobe_opts=$7 222 encfile="${outdir}/${test}.${enc_fmt}" 223 test "$6" = -keep || cleanfiles="$cleanfiles $encfile" 224 tsrcfile=$(target_path $srcfile) 225 tencfile=$(target_path $encfile) 226 ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ 227 -f $enc_fmt -y $tencfile || return 228 do_md5sum $encfile 229 echo $(wc -c $encfile) 230 ffmpeg $DEC_OPTS -i $tencfile $ENC_OPTS $FLAGS $final_decode \ 231 -f framecrc - || return 232 test -z $ffprobe_opts || \ 233 run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts -v 0 $tencfile || return 234} 235 236stream_remux(){ 237 src_fmt=$1 238 srcfile=$2 239 enc_fmt=$3 240 stream_maps=$4 241 final_decode=$5 242 ffprobe_opts=$7 243 encfile="${outdir}/${test}.${enc_fmt}" 244 test "$6" = -keep || cleanfiles="$cleanfiles $encfile" 245 tsrcfile=$(target_path $srcfile) 246 tencfile=$(target_path $encfile) 247 ffmpeg -f $src_fmt -i $tsrcfile $stream_maps -codec copy $FLAGS \ 248 -f $enc_fmt -y $tencfile || return 249 ffmpeg $DEC_OPTS -i $tencfile $ENC_OPTS $FLAGS $final_decode \ 250 -f framecrc - || return 251 test -z $ffprobe_opts || \ 252 run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts -v 0 $tencfile || return 253} 254 255# FIXME: There is a certain duplication between the avconv-related helper 256# functions above and below that should be refactored. 257ffmpeg2="$target_exec ${target_path}/ffmpeg${PROGSUF}${EXECSUF}" 258raw_src="${target_path}/tests/vsynth1/%02d.pgm" 259pcm_src="${target_path}/tests/data/asynth1.sw" 260crcfile="tests/data/$test.lavf.crc" 261target_crcfile="${target_path}/$crcfile" 262 263[ "${V-0}" -gt 0 ] && echov=echov || echov=: 264 265echov(){ 266 echo "$@" >&3 267} 268 269AVCONV_OPTS="-nostdin -nostats -y -cpuflags $cpuflags" 270COMMON_OPTS="-flags +bitexact -idct simple -sws_flags +accurate_rnd+bitexact -fflags +bitexact" 271DEC_OPTS="$COMMON_OPTS -threads $threads" 272ENC_OPTS="$COMMON_OPTS -threads 1 -dct fastint" 273 274run_avconv(){ 275 $echov $ffmpeg2 $AVCONV_OPTS $* 276 $ffmpeg2 $AVCONV_OPTS $* 277} 278 279do_avconv(){ 280 f="$1" 281 shift 282 set -- $* ${target_path}/$f 283 run_avconv $* 284 do_md5sum $f 285 echo $(wc -c $f) 286} 287 288do_avconv_crc(){ 289 f="$1" 290 shift 291 run_avconv $* -f crc "$target_crcfile" 292 echo "$f $(cat $crcfile)" 293} 294 295lavf_audio(){ 296 t="${test#lavf-}" 297 outdir="tests/data/lavf" 298 file=${outdir}/lavf.$t 299 do_avconv $file $DEC_OPTS $1 -ar 44100 -f s16le -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $2 300 do_avconv_crc $file $DEC_OPTS $3 -i $target_path/$file 301} 302 303lavf_container(){ 304 t="${test#lavf-}" 305 outdir="tests/data/lavf" 306 file=${outdir}/lavf.$t 307 do_avconv $file $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $DEC_OPTS -ar 44100 -f s16le $1 -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -b:a 64k -t 1 -qscale:v 10 $2 308 test "$3" = "disable_crc" || 309 do_avconv_crc $file $DEC_OPTS -i $target_path/$file $3 310} 311 312lavf_container_attach() { lavf_container "" "$1 -attach ${raw_src%/*}/00.pgm -metadata:s:t mimetype=image/x-portable-greymap"; } 313lavf_container_timecode_nodrop() { lavf_container "" "$1 -timecode 02:56:14:13"; } 314lavf_container_timecode_drop() { lavf_container "" "$1 -timecode 02:56:14.13 -r 30000/1001"; } 315 316lavf_container_timecode() 317{ 318 lavf_container_timecode_nodrop "$@" 319 lavf_container_timecode_drop "$@" 320 lavf_container "" "$1" 321} 322 323lavf_container_fate() 324{ 325 t="${test#lavf-fate-}" 326 outdir="tests/data/lavf-fate" 327 file=${outdir}/lavf.$t 328 input="${target_samples}/$1" 329 do_avconv $file $DEC_OPTS $2 -i "$input" "$ENC_OPTS -metadata title=lavftest" -vcodec copy -acodec copy 330 do_avconv_crc $file $DEC_OPTS -i $target_path/$file $3 331} 332 333lavf_image(){ 334 t="${test#lavf-}" 335 outdir="tests/data/images/$t" 336 mkdir -p "$outdir" 337 file=${outdir}/%02d.$t 338 run_avconv $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $1 "$ENC_OPTS -metadata title=lavftest" -frames 13 -y -qscale 10 $target_path/$file 339 do_md5sum ${outdir}/02.$t 340 do_avconv_crc $file $DEC_OPTS $2 -i $target_path/$file $2 341 echo $(wc -c ${outdir}/02.$t) 342} 343 344lavf_image2pipe(){ 345 t="${test#lavf-}" 346 t="${t%pipe}" 347 outdir="tests/data/lavf" 348 file=${outdir}/${t}pipe.$t 349 do_avconv $file $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src -f image2pipe "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 350 do_avconv_crc $file $DEC_OPTS -f image2pipe -i $target_path/$file 351} 352 353lavf_video(){ 354 t="${test#lavf-}" 355 outdir="tests/data/lavf" 356 file=${outdir}/lavf.$t 357 do_avconv $file $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $1 $2 358 do_avconv_crc $file $DEC_OPTS -i $target_path/$file $1 359} 360 361refcmp_metadata(){ 362 refcmp=$1 363 pixfmt=$2 364 fuzz=${3:-0.001} 365 ffmpeg $FLAGS $ENC_OPTS \ 366 -lavfi "testsrc2=size=300x200:rate=1:duration=5,format=${pixfmt},split[ref][tmp];[tmp]avgblur=4[enc];[enc][ref]${refcmp},metadata=print:file=-" \ 367 -f null /dev/null | awk -v ref=${ref} -v fuzz=${fuzz} -f ${base}/refcmp-metadata.awk - 368} 369 370pixfmt_conversion(){ 371 conversion="${test#pixfmt-}" 372 outdir="tests/data/pixfmt" 373 raw_dst="$outdir/$conversion.out.yuv" 374 file=${outdir}/${conversion}.yuv 375 run_avconv $DEC_OPTS -r 1 -f image2 -c:v pgmyuv -i $raw_src \ 376 $ENC_OPTS -f rawvideo -t 1 -s 352x288 -pix_fmt $conversion $target_path/$raw_dst 377 do_avconv $file $DEC_OPTS -f rawvideo -s 352x288 -pix_fmt $conversion -i $target_path/$raw_dst \ 378 $ENC_OPTS -f rawvideo -s 352x288 -pix_fmt yuv444p 379} 380 381video_filter(){ 382 filters=$1 383 shift 384 label=${test#filter-} 385 raw_src="${target_path}/tests/vsynth1/%02d.pgm" 386 printf '%-20s' $label 387 ffmpeg $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src \ 388 $FLAGS $ENC_OPTS -vf "$filters" -vcodec rawvideo -frames:v 5 $* -f nut md5: 389} 390 391pixfmts(){ 392 filter=${test#filter-pixfmts-} 393 filter=${filter%_*} 394 filter_args=$1 395 prefilter_chain=$2 396 nframes=${3:-1} 397 398 showfiltfmts="$target_exec $target_path/libavfilter/tests/filtfmts${EXECSUF}" 399 scale_exclude_fmts=${outfile}_scale_exclude_fmts 400 scale_in_fmts=${outfile}_scale_in_fmts 401 scale_out_fmts=${outfile}_scale_out_fmts 402 in_fmts=${outfile}_in_fmts 403 404 # exclude pixel formats which are not supported as input 405 $showfiltfmts scale | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$scale_in_fmts 406 $showfiltfmts scale | awk -F '[ \r]' '/^OUTPUT/{ fmt=substr($3, 5); print fmt }' | sort >$scale_out_fmts 407 comm -12 $scale_in_fmts $scale_out_fmts >$scale_exclude_fmts 408 409 $showfiltfmts $filter | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$in_fmts 410 pix_fmts=$(comm -12 $scale_exclude_fmts $in_fmts) 411 412 outertest=$test 413 for pix_fmt in $pix_fmts; do 414 test=$pix_fmt 415 video_filter "${prefilter_chain}format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt -frames:v $nframes 416 done 417 418 rm $in_fmts $scale_in_fmts $scale_out_fmts $scale_exclude_fmts 419 test=$outertest 420} 421 422gapless(){ 423 sample=$(target_path $1) 424 extra_args=$2 425 426 decfile1="${outdir}/${test}.out-1" 427 decfile2="${outdir}/${test}.out-2" 428 decfile3="${outdir}/${test}.out-3" 429 cleanfiles="$cleanfiles $decfile1 $decfile2 $decfile3" 430 431 # test packet data 432 ffmpeg $extra_args -i "$sample" -bitexact -c:a copy -f framecrc -y $(target_path $decfile1) 433 do_md5sum $decfile1 434 # test decoded (and cut) data 435 ffmpeg $extra_args -i "$sample" -bitexact -f wav md5: 436 # the same as above again, with seeking to the start 437 ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $(target_path $decfile2) 438 do_md5sum $decfile2 439 ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -f wav md5: 440 # test packet data, with seeking to a specific position 441 ffmpeg $extra_args -ss 5 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $(target_path $decfile3) 442 do_md5sum $decfile3 443} 444 445gaplessenc(){ 446 sample=$(target_path $1) 447 format=$2 448 codec=$3 449 450 file1="${outdir}/${test}.out-1" 451 cleanfiles="$cleanfiles $file1" 452 453 # test data after reencoding 454 ffmpeg -i "$sample" -bitexact -map 0:a -c:a $codec -f $format -y "$(target_path "$file1")" 455 probegaplessinfo "$(target_path "$file1")" 456} 457 458audio_match(){ 459 sample=$(target_path $1) 460 trefile=$2 461 extra_args=$3 462 463 decfile="${outdir}/${test}.wav" 464 cleanfiles="$cleanfiles $decfile" 465 466 ffmpeg -i "$sample" -bitexact $extra_args -y $(target_path $decfile) 467 tests/audiomatch${HOSTEXECSUF} $decfile $trefile 468} 469 470concat(){ 471 template=$1 472 sample=$2 473 mode=$3 474 extra_args=$4 475 476 concatfile="${outdir}/${test}.ffconcat" 477 packetfile="${outdir}/${test}.ffprobe" 478 cleanfiles="$concatfile $packetfile" 479 480 awk "{gsub(/%SRCFILE%/, \"$sample\"); print}" $template > $concatfile 481 482 if [ "$mode" = "md5" ]; then 483 run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_streams -show_packets -v 0 -safe 0 $extra_args $(target_path $concatfile) | tr -d '\r' > $packetfile 484 do_md5sum $packetfile 485 else 486 run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_streams -show_packets -v 0 -of compact=p=0:nk=1 -safe 0 $extra_args $(target_path $concatfile) 487 fi 488} 489 490venc_data(){ 491 file=$1 492 stream=$2 493 frames=$3 494 run tools/venc_data_dump${EXECSUF} ${file} ${stream} ${frames} ${threads} ${thread_type} 495} 496 497null(){ 498 : 499} 500 501# Disable globbing: command arguments may contain globbing characters and 502# must be kept verbatim 503set -f 504 505exec 3>&2 506eval $command >"$outfile" 2>$errfile 507err=$? 508 509if [ $err -gt 128 ]; then 510 sig=$(kill -l $err 2>/dev/null) 511 test "${sig}" = "${sig%[!A-Za-z]*}" || unset sig 512fi 513 514if test -e "$ref" || test $cmp = "oneline" || test $cmp = "null" || test $cmp = "grep" ; then 515 case $cmp in 516 diff) diff -u -b "$ref" "$outfile" >$cmpfile ;; 517 rawdiff)diff -u "$ref" "$outfile" >$cmpfile ;; 518 oneoff) oneoff "$ref" "$outfile" >$cmpfile ;; 519 stddev) stddev "$ref" "$outfile" >$cmpfile ;; 520 oneline)oneline "$ref" "$outfile" >$cmpfile ;; 521 grep) grep "$ref" "$errfile" >$cmpfile ;; 522 null) cat "$outfile" >$cmpfile ;; 523 esac 524 cmperr=$? 525 test $err = 0 && err=$cmperr 526 if [ "$report_type" = "ignore" ]; then 527 test $err = 0 || echo "IGNORE\t${test}" && err=0 && unset sig 528 else 529 test $err = 0 || cat $cmpfile 530 fi 531else 532 echo "reference file '$ref' not found" 533 err=1 534fi 535 536if [ $err -eq 0 ] && test $report_type = "standard" ; then 537 unset cmpo erro 538else 539 cmpo="$($base64 <$cmpfile)" 540 erro="$($base64 <$errfile)" 541fi 542echo "${test}:${sig:-$err}:$cmpo:$erro" >$repfile 543 544if test $err != 0 && test $gen != "no" ; then 545 echo "GEN $ref" 546 cp -f "$outfile" "$ref" 547 err=$? 548fi 549 550if test $err = 0; then 551 if test $keep = 0; then 552 rm -f $outfile $errfile $cmpfile $cleanfiles 553 fi 554elif test $gen = "no"; then 555 echo "Test $test failed. Look at $errfile for details." 556 test "${V:-0}" -gt 0 && cat $errfile 557else 558 echo "Updating reference failed, possibly no output file was generated." 559fi 560exit $err 561