blob: 29a36cea3ad01a6c9cca493907b4f2ae2614f4ff
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 | hwaccel=${17:-none} |
27 | |
28 | outdir="tests/data/fate" |
29 | outfile="${outdir}/${test}" |
30 | errfile="${outdir}/${test}.err" |
31 | cmpfile="${outdir}/${test}.diff" |
32 | repfile="${outdir}/${test}.rep" |
33 | |
34 | target_path(){ |
35 | test ${1} = ${1#/} && p=${target_path}/ |
36 | echo ${p}${1} |
37 | } |
38 | |
39 | # $1=value1, $2=value2, $3=threshold |
40 | # prints 0 if absolute difference between value1 and value2 is <= threshold |
41 | compare(){ |
42 | awk "BEGIN { v = $1 - $2; printf ((v < 0 ? -v : v) > $3) }" |
43 | } |
44 | |
45 | do_tiny_psnr(){ |
46 | psnr=$(tests/tiny_psnr "$1" "$2" $cmp_unit $cmp_shift 0) || return 1 |
47 | val=$(expr "$psnr" : ".*$3: *\([0-9.]*\)") |
48 | size1=$(expr "$psnr" : '.*bytes: *\([0-9]*\)') |
49 | size2=$(expr "$psnr" : '.*bytes:[ 0-9]*/ *\([0-9]*\)') |
50 | val_cmp=$(compare $val $cmp_target $fuzz) |
51 | size_cmp=$(compare $size1 $size2 $size_tolerance) |
52 | if [ "$val_cmp" != 0 ] || [ "$size_cmp" != 0 ]; then |
53 | echo "$psnr" |
54 | if [ "$val_cmp" != 0 ]; then |
55 | echo "$3: |$val - $cmp_target| >= $fuzz" |
56 | fi |
57 | if [ "$size_cmp" != 0 ]; then |
58 | echo "size: |$size1 - $size2| >= $size_tolerance" |
59 | fi |
60 | return 1 |
61 | fi |
62 | } |
63 | |
64 | oneoff(){ |
65 | do_tiny_psnr "$1" "$2" MAXDIFF |
66 | } |
67 | |
68 | stddev(){ |
69 | do_tiny_psnr "$1" "$2" stddev |
70 | } |
71 | |
72 | oneline(){ |
73 | printf '%s\n' "$1" | diff -u -b - "$2" |
74 | } |
75 | |
76 | run(){ |
77 | test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 |
78 | $target_exec $target_path/"$@" |
79 | } |
80 | |
81 | runecho(){ |
82 | test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 |
83 | $target_exec $target_path/"$@" >&3 |
84 | } |
85 | |
86 | probefmt(){ |
87 | run ffprobe${PROGSUF} -show_entries format=format_name -print_format default=nw=1:nk=1 -v 0 "$@" |
88 | } |
89 | |
90 | runlocal(){ |
91 | test "${V:-0}" -gt 0 && echo ${base}/"$@" ${base} >&3 |
92 | ${base}/"$@" ${base} |
93 | } |
94 | |
95 | probeframes(){ |
96 | run ffprobe${PROGSUF} -show_frames -v 0 "$@" |
97 | } |
98 | |
99 | probechapters(){ |
100 | run ffprobe${PROGSUF} -show_chapters -v 0 "$@" |
101 | } |
102 | |
103 | probegaplessinfo(){ |
104 | filename="$1" |
105 | shift |
106 | run ffprobe${PROGSUF} -bitexact -select_streams a -show_entries format=start_time,duration:stream=index,start_pts,duration_ts -v 0 "$filename" "$@" |
107 | pktfile1="${outdir}/${test}.pkts" |
108 | framefile1="${outdir}/${test}.frames" |
109 | cleanfiles="$cleanfiles $pktfile1 $framefile1" |
110 | run ffprobe${PROGSUF} -bitexact -select_streams a -of compact -count_packets -show_entries packet=pts,dts,duration:stream=nb_read_packets -v 0 "$filename" "$@" > "$pktfile1" |
111 | head -n 8 "$pktfile1" |
112 | tail -n 9 "$pktfile1" |
113 | run ffprobe${PROGSUF} -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" |
114 | head -n 8 "$framefile1" |
115 | tail -n 9 "$framefile1" |
116 | } |
117 | |
118 | ffmpeg(){ |
119 | dec_opts="-hwaccel $hwaccel -threads $threads -thread_type $thread_type" |
120 | ffmpeg_args="-nostdin -nostats -cpuflags $cpuflags" |
121 | for arg in $@; do |
122 | [ x${arg} = x-i ] && ffmpeg_args="${ffmpeg_args} ${dec_opts}" |
123 | ffmpeg_args="${ffmpeg_args} ${arg}" |
124 | done |
125 | run ffmpeg${PROGSUF} ${ffmpeg_args} |
126 | } |
127 | |
128 | framecrc(){ |
129 | ffmpeg "$@" -flags +bitexact -fflags +bitexact -f framecrc - |
130 | } |
131 | |
132 | ffmetadata(){ |
133 | ffmpeg "$@" -flags +bitexact -fflags +bitexact -f ffmetadata - |
134 | } |
135 | |
136 | framemd5(){ |
137 | ffmpeg "$@" -flags +bitexact -fflags +bitexact -f framemd5 - |
138 | } |
139 | |
140 | crc(){ |
141 | ffmpeg "$@" -f crc - |
142 | } |
143 | |
144 | md5(){ |
145 | ffmpeg "$@" md5: |
146 | } |
147 | |
148 | pcm(){ |
149 | ffmpeg "$@" -vn -f s16le - |
150 | } |
151 | |
152 | fmtstdout(){ |
153 | fmt=$1 |
154 | shift 1 |
155 | ffmpeg -flags +bitexact -fflags +bitexact "$@" -f $fmt - |
156 | } |
157 | |
158 | enc_dec_pcm(){ |
159 | out_fmt=$1 |
160 | dec_fmt=$2 |
161 | pcm_fmt=$3 |
162 | src_file=$(target_path $4) |
163 | shift 4 |
164 | encfile="${outdir}/${test}.${out_fmt}" |
165 | cleanfiles=$encfile |
166 | encfile=$(target_path ${encfile}) |
167 | ffmpeg -i $src_file "$@" -f $out_fmt -y ${encfile} || return |
168 | ffmpeg -flags +bitexact -fflags +bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -fflags +bitexact -f ${dec_fmt} - |
169 | } |
170 | |
171 | FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" |
172 | DEC_OPTS="-threads $threads -idct simple $FLAGS" |
173 | ENC_OPTS="-threads 1 -idct simple -dct fastint" |
174 | |
175 | enc_dec(){ |
176 | src_fmt=$1 |
177 | srcfile=$2 |
178 | enc_fmt=$3 |
179 | enc_opt=$4 |
180 | dec_fmt=$5 |
181 | dec_opt=$6 |
182 | encfile="${outdir}/${test}.${enc_fmt}" |
183 | decfile="${outdir}/${test}.out.${dec_fmt}" |
184 | cleanfiles="$cleanfiles $decfile" |
185 | test "$7" = -keep || cleanfiles="$cleanfiles $encfile" |
186 | tsrcfile=$(target_path $srcfile) |
187 | tencfile=$(target_path $encfile) |
188 | tdecfile=$(target_path $decfile) |
189 | ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ |
190 | -f $enc_fmt -y $tencfile || return |
191 | do_md5sum $encfile |
192 | echo $(wc -c $encfile) |
193 | ffmpeg $8 $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt $FLAGS \ |
194 | -f $dec_fmt -y $tdecfile || return |
195 | do_md5sum $decfile |
196 | tests/tiny_psnr $srcfile $decfile $cmp_unit $cmp_shift |
197 | } |
198 | |
199 | transcode(){ |
200 | src_fmt=$1 |
201 | srcfile=$2 |
202 | enc_fmt=$3 |
203 | enc_opt=$4 |
204 | final_decode=$5 |
205 | encfile="${outdir}/${test}.${enc_fmt}" |
206 | test "$7" = -keep || cleanfiles="$cleanfiles $encfile" |
207 | tsrcfile=$(target_path $srcfile) |
208 | tencfile=$(target_path $encfile) |
209 | ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ |
210 | -f $enc_fmt -y $tencfile || return |
211 | do_md5sum $encfile |
212 | echo $(wc -c $encfile) |
213 | ffmpeg $DEC_OPTS -i $encfile $ENC_OPTS $FLAGS $final_decode \ |
214 | -f framecrc - || return |
215 | } |
216 | |
217 | lavffatetest(){ |
218 | t="${test#lavf-fate-}" |
219 | ref=${base}/ref/lavf-fate/$t |
220 | ${base}/lavf-regression.sh $t lavf-fate tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$target_samples" |
221 | } |
222 | |
223 | lavftest(){ |
224 | t="${test#lavf-}" |
225 | ref=${base}/ref/lavf/$t |
226 | ${base}/lavf-regression.sh $t lavf tests/vsynth1 "$target_exec" "$target_path" "$threads" "$thread_type" "$cpuflags" "$target_samples" |
227 | } |
228 | |
229 | video_filter(){ |
230 | filters=$1 |
231 | shift |
232 | label=${test#filter-} |
233 | raw_src="${target_path}/tests/vsynth1/%02d.pgm" |
234 | printf '%-20s' $label |
235 | ffmpeg $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src \ |
236 | $FLAGS $ENC_OPTS -vf "$filters" -vcodec rawvideo -frames:v 5 $* -f nut md5: |
237 | } |
238 | |
239 | pixfmts(){ |
240 | filter=${test#filter-pixfmts-} |
241 | filter=${filter%_*} |
242 | filter_args=$1 |
243 | prefilter_chain=$2 |
244 | nframes=${3:-1} |
245 | |
246 | showfiltfmts="$target_exec $target_path/libavfilter/tests/filtfmts" |
247 | scale_exclude_fmts=${outfile}_scale_exclude_fmts |
248 | scale_in_fmts=${outfile}_scale_in_fmts |
249 | scale_out_fmts=${outfile}_scale_out_fmts |
250 | in_fmts=${outfile}_in_fmts |
251 | |
252 | # exclude pixel formats which are not supported as input |
253 | $showfiltfmts scale | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$scale_in_fmts |
254 | $showfiltfmts scale | awk -F '[ \r]' '/^OUTPUT/{ fmt=substr($3, 5); print fmt }' | sort >$scale_out_fmts |
255 | comm -12 $scale_in_fmts $scale_out_fmts >$scale_exclude_fmts |
256 | |
257 | $showfiltfmts $filter | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$in_fmts |
258 | pix_fmts=$(comm -12 $scale_exclude_fmts $in_fmts) |
259 | |
260 | outertest=$test |
261 | for pix_fmt in $pix_fmts; do |
262 | test=$pix_fmt |
263 | video_filter "${prefilter_chain}format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt -frames:v $nframes |
264 | done |
265 | |
266 | rm $in_fmts $scale_in_fmts $scale_out_fmts $scale_exclude_fmts |
267 | test=$outertest |
268 | } |
269 | |
270 | gapless(){ |
271 | sample=$(target_path $1) |
272 | extra_args=$2 |
273 | |
274 | decfile1="${outdir}/${test}.out-1" |
275 | decfile2="${outdir}/${test}.out-2" |
276 | decfile3="${outdir}/${test}.out-3" |
277 | cleanfiles="$cleanfiles $decfile1 $decfile2 $decfile3" |
278 | |
279 | # test packet data |
280 | ffmpeg $extra_args -i "$sample" -flags +bitexact -fflags +bitexact -c:a copy -f framecrc -y $decfile1 |
281 | do_md5sum $decfile1 |
282 | # test decoded (and cut) data |
283 | ffmpeg $extra_args -i "$sample" -flags +bitexact -fflags +bitexact -f wav md5: |
284 | # the same as above again, with seeking to the start |
285 | ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -flags +bitexact -fflags +bitexact -c:a copy -f framecrc -y $decfile2 |
286 | do_md5sum $decfile2 |
287 | ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -flags +bitexact -fflags +bitexact -f wav md5: |
288 | # test packet data, with seeking to a specific position |
289 | ffmpeg $extra_args -ss 5 -seek_timestamp 1 -i "$sample" -flags +bitexact -fflags +bitexact -c:a copy -f framecrc -y $decfile3 |
290 | do_md5sum $decfile3 |
291 | } |
292 | |
293 | gaplessenc(){ |
294 | sample=$(target_path $1) |
295 | format=$2 |
296 | codec=$3 |
297 | |
298 | file1="${outdir}/${test}.out-1" |
299 | cleanfiles="$cleanfiles $file1" |
300 | |
301 | # test data after reencoding |
302 | ffmpeg -i "$sample" -flags +bitexact -fflags +bitexact -map 0:a -c:a $codec -f $format -y "$file1" |
303 | probegaplessinfo "$file1" |
304 | } |
305 | |
306 | audio_match(){ |
307 | sample=$(target_path $1) |
308 | trefile=$(target_path $2) |
309 | extra_args=$3 |
310 | |
311 | decfile="${outdir}/${test}.wav" |
312 | cleanfiles="$cleanfiles $decfile" |
313 | |
314 | ffmpeg -i "$sample" -flags +bitexact -fflags +bitexact $extra_args -y $decfile |
315 | tests/audiomatch $decfile $trefile |
316 | } |
317 | |
318 | concat(){ |
319 | template=$1 |
320 | sample=$2 |
321 | mode=$3 |
322 | extra_args=$4 |
323 | |
324 | concatfile="${outdir}/${test}.ffconcat" |
325 | packetfile="${outdir}/${test}.ffprobe" |
326 | cleanfiles="$concatfile $packetfile" |
327 | |
328 | awk "{gsub(/%SRCFILE%/, \"$sample\"); print}" $template > $concatfile |
329 | |
330 | if [ "$mode" = "md5" ]; then |
331 | run ffprobe${PROGSUF} -bitexact -show_streams -show_packets -v 0 -fflags keepside -safe 0 $extra_args $concatfile | tr -d '\r' > $packetfile |
332 | do_md5sum $packetfile |
333 | else |
334 | run ffprobe${PROGSUF} -bitexact -show_streams -show_packets -v 0 -of compact=p=0:nk=1 -fflags keepside -safe 0 $extra_args $concatfile |
335 | fi |
336 | } |
337 | |
338 | mkdir -p "$outdir" |
339 | |
340 | # Disable globbing: command arguments may contain globbing characters and |
341 | # must be kept verbatim |
342 | set -f |
343 | |
344 | exec 3>&2 |
345 | eval $command >"$outfile" 2>$errfile |
346 | err=$? |
347 | |
348 | if [ $err -gt 128 ]; then |
349 | sig=$(kill -l $err 2>/dev/null) |
350 | test "${sig}" = "${sig%[!A-Za-z]*}" || unset sig |
351 | fi |
352 | |
353 | if test -e "$ref" || test $cmp = "oneline" || test $cmp = "grep" ; then |
354 | case $cmp in |
355 | diff) diff -u -b "$ref" "$outfile" >$cmpfile ;; |
356 | rawdiff)diff -u "$ref" "$outfile" >$cmpfile ;; |
357 | oneoff) oneoff "$ref" "$outfile" >$cmpfile ;; |
358 | stddev) stddev "$ref" "$outfile" >$cmpfile ;; |
359 | oneline)oneline "$ref" "$outfile" >$cmpfile ;; |
360 | grep) grep "$ref" "$errfile" >$cmpfile ;; |
361 | null) cat "$outfile" >$cmpfile ;; |
362 | esac |
363 | cmperr=$? |
364 | test $err = 0 && err=$cmperr |
365 | test $err = 0 || cat $cmpfile |
366 | else |
367 | echo "reference file '$ref' not found" |
368 | err=1 |
369 | fi |
370 | |
371 | if [ $err -eq 0 ]; then |
372 | unset cmpo erro |
373 | else |
374 | cmpo="$($base64 <$cmpfile)" |
375 | erro="$($base64 <$errfile)" |
376 | fi |
377 | echo "${test}:${sig:-$err}:$cmpo:$erro" >$repfile |
378 | |
379 | if test $err != 0 && test $gen != "no" ; then |
380 | echo "GEN $ref" |
381 | cp -f "$outfile" "$ref" |
382 | err=$? |
383 | fi |
384 | |
385 | if test $err = 0; then |
386 | rm -f $outfile $errfile $cmpfile $cleanfiles |
387 | elif test $gen = "no"; then |
388 | echo "Test $test failed. Look at $errfile for details." |
389 | test "${V:-0}" -gt 0 && cat $errfile |
390 | else |
391 | echo "Updating reference failed, possibly no output file was generated." |
392 | fi |
393 | exit $err |
394 |