JuliaIO / VideoIO.jl

Reading and writing of video files in Julia via ffmpeg
https://juliaio.github.io/VideoIO.jl/stable
Other
126 stars 53 forks source link

Add frame skip & frame count functions #244

Closed IanButterworth closed 4 years ago

IanButterworth commented 4 years ago

The objective here is to provide the fastest way to 1) skip through a frame 2) skip through multiple frames 3) get the most accurate & fastest count of remaining available frames

@rdeits @yakir12 What do you think about these?

I'll add tests if they look good

IanButterworth commented 4 years ago

counttotalframes is currently under-counting by 3 (tested for n=5 and n=100)

using VideoIO
n = 100
imgstack = map(x->rand(UInt8,100,100),1:n)
props = [:priv_data => ("crf"=>"22","preset"=>"medium")]
encodedvideopath = VideoIO.encodevideo("testvideo.mp4",imgstack,framerate=30,AVCodecContextProperties=props, silent=true)

f = VideoIO.openvideo(encodedvideopath)
@show counttotalframes(f)
counttotalframes(f) = 97
yakir12 commented 4 years ago

Didn't I have a sea of similar problems with uncounted frames before... oy...

IanButterworth commented 4 years ago

It's weird because in the precision tests, we're producing a frame stack, encoding it to file, decoding it and checking every frame against the source framestack.. and those tests pass.

I could understand if it was n-1, perhaps due to the way that EOF is reported, but n-3 seems odd

IanButterworth commented 4 years ago

Ok, this is related to crf & keyframes. It works for lossless (but it's overcounting by one. I need to fix the EOF handling):

Edit: Corrected frame count

using VideoIO

function testcount(n, crf)
        imgstack = map(x->rand(UInt8,100,100),1:n)
        props = [:priv_data => ("crf"=>crf,"preset"=>"medium")]
        encodedvideopath = VideoIO.encodevideo("testvideo.mp4",imgstack,framerate=30,AVCodecContextProperties=props, silent=true)

        f = VideoIO.openvideo(encodedvideopath)
        return counttotalframes(f)
end

n = 5
testcount(n, "22")   # 1
testcount(n, "0")    # 5
testcount(n, "1")    # 1

n = 100
testcount(n, "22")   # 96
testcount(n, "0")    # 100
testcount(n, "1")    # 96
IanButterworth commented 4 years ago

So it seems if crf > 0 during encoding the total number of frames available to read back in is n-4.

Seems like an upstream issue?

IanButterworth commented 4 years ago

I'd be happy to merge this, if all agree

yakir12 commented 4 years ago

Sorry for the lack of input, looks good to me!

rdeits commented 4 years ago

:+1: