luv

Workshop wiki

tests.lisp

libav/tests.lisp

system luv/libav/test · 15 definitions · on GitHub

defpackage#:luv.libav.tests
:use#:cl#:rove
:local-nicknames
#:libav#:luv.libav
in-package#:luv.libav.tests
deftestlibav-loads-and-agrees-with-its-headers

load-libav signals libav-version-mismatch itself when the headers this system groveled and the libraries it dlopens come from different builds, so reaching a version string at all is the claim.

ok
every
lambda
entry
destructuring-bind
name.triple
entry
and
stringpname
=3
lengthtriple
every#'integerptriple
deftesthardware-decoding-is-configured-for-this-platform

The platform's own path must be there, since decoding to a GPU surface is the reason this binding exists. Which other types FFmpeg was built with is not this system's business.

let
ok
listptypes
ok
every#'keywordptypes
#+darwin (ok (member :videotoolbox types))#+linux
ok
intersection'
:vaapi:vulkan
types
ok
equal"videotoolbox"
deftestpixel-formats-round-trip-through-ffmpegs-own-names
ok
equal"nv12"
ok
equal"yuv420p"
ok
equal"videotoolbox_vld"
deftesta-frames-groveled-layout-agrees-with-libavutil

The offsets are only trustworthy if the library reads back what Lisp wrote through them. Describe a picture through the groveled slots, then let av_frame_get_buffer act on that description: a 1920-wide NV12 frame has to come back with two planes and a stride of at least its width.

defparameter*test-pattern*
asdf:system-relative-pathname"luv/libav""libav/test-pattern.mp4"
"A ten-frame 64x48 H.264 test pattern, small enough to keep in the tree."
deftesta-file-opens-and-describes-itself
libav:with-video
ok
=64
libav:video-widthvideo
ok
=48
libav:video-heightvideo
ok
=10
libav:video-frame-ratevideo
deftestdecoding-drains-every-picture-in-the-file

The count is the claim: a decode loop that forgets to flush the codec at end of file loses the pictures still buffered inside it, and a loop that mishandles EAGAIN stops early. Ten frames in, ten frames out.

libav:with-video
let
count0
loopwhiledo
incfcount
ok
=10count

Exhausted stays exhausted.

And rewinding makes it whole again.

let
again0
loopwhiledo
incfagain
ok
=10again
deftesta-decoded-picture-converts-to-packed-rgba
libav:with-video
let
frame
libav:video-framevideo
ok
=64
libav:frame-widthframe
ok
=48
libav:frame-heightframe

Software decoding, so the picture is in ordinary memory and its planes are real.

swscale both converts and resizes, so a caller can ask for the size its surface wants rather than the size the file happens to be.

let
ok
equal'
1616
array-dimensionswords
ok
loopforindexbelow
array-total-sizewords
always
=#xff
ldb
byte824
row-major-arefwordsindex

A test pattern is not one flat colour; a conversion that silently produced an empty image would be.

let
distinct
make-hash-table
dotimes
y16
dotimes
x16
setf
gethash
arefwordsyx
distinct
t
ok
>
hash-table-countdistinct
8
deftesta-failed-call-carries-ffmpegs-own-explanation
libav:with-frame

No width, height, or format: av_frame_get_buffer has nothing to size.

handler-case
progn
fail"expected a failure"
libav:libav-error
condition
ok
eq'libav:allocate-frame-buffer
libav:libav-error-operationcondition
ok
minusp
libav:libav-error-codecondition
deftesta-silent-film-has-no-audio-track

The test pattern has no sound; asking is not an error, it is a NIL.

deftesta-films-sound-decodes-to-mono-floats

A one-second 440 Hz sine, made by ffmpeg beside the test pattern.

let
track
libav:open-audio
asdf:system-relative-pathname"luv/libav""libav/test-tone.mp4"
oktrack
unwind-protect
progn
ok
=44100
libav:audio-sample-ratetrack
ok
=1
libav:audio-channel-counttrack
ok
and
libav:audio-durationtrack
<0.9
libav:audio-durationtrack
1.2
let
total0
peak0.0
buffernil
loopwhiledo
multiple-value-bind
samplescount
setfbuffersamples
ok
<=count
lengthsamples
dotimes
indexcount
setfpeak
maxpeak
abs
arefsamplesindex
incftotalcount

About a second of it, and audibly a tone rather than silence or a decoder handing back garbage.

ok
<40000total50000
ok
<0.1peak1.01

And again from the top.