Channel gets emptied and stays that way

yakir12
Wed, 10 Jul 2019 19:54:04 +0000
General Usage

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 @asynced 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)?

12 posts - 4 participants