I want to use a @async
task to put!
video frames (from VideoIO
) in a Channel
and use that channel as a buffer of frames to update a Makie.Scene
with. The idea is that while the user plays with the slider
to explore a video the buffer will have all the frames the user needs and as the user uses them the task will put!
more frames in the buffer in the background.
My problem is that the channel always gets empty, even if I leave the slider alone. It’s like some background task never yields to allow that @async
ed task to fill back the buffer.
Any idea what’s going on?
Here is a bare-bone MWE (ignore the scaling and rotation of the image, just trying to keep it super simple):
using Makie, VideoIO
avf = VideoIO.testvideo("annie_oakley")
f = VideoIO.openvideo(avf)
seek(f, 5.0) # skip the beginning
img = Node(read(f))
buff = Channel{typeof(img[])}(500) # have a buffer with 500 frames
task = @async begin # this is the task that fills that buffer
while !eof(f)
put!(buff, read(f))
end
end
scene = Makie.image(img)
slider_h = slider(1:500, raw = true, camera = campixel!, start = 2)
old_slider_pos = Node(1)
lift(slider_h[end][:value]) do frame
if old_slider_pos[] ≤ frame
for i in old_slider_pos[]:frame
img[] = take!(buff)
end
old_slider_pos[] = frame
else
println("can't go back in time! Yet…")
end
end
hbox(slider_h, scene)
Now slide the slider a little to the right and then check the buff
variable, it should show something like this:
julia> buff
Channel{PermutedDimsArray{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2,(2, 1),(2, 1),Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}}}(sz_max:500,sz_curr:500)
Nice, the channel is still full, it has 500 frames ready.
OK, now be nasty and pull the slider to the right more vigorously. Check buff
again:
julia> buff
Channel{PermutedDimsArray{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2,(2, 1),(2, 1),Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}}}(sz_max:500,sz_curr:128)
Now it has lost tons of frames. It will stay like that no matter what.
Why? And how can I get it to do what I want: fill up the buffer in the background (like when the user isn’t playing with the slider)?