2

I am experimenting with losslessly compressing some raw video. How can I perform a frame hash on the encoded output before or while writing it to the file system? I want to make an original.hashes and a compressed.hashes. (I will compare them with another tool later.)

ffmpeg -r 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "split=3 [copyHash] [copyLossless] [otherIn]; [otherIn] {some filter here} [otherOut]" ^
-map [copyLossless] -c:v libx264rgb -qp 0 -pix_fmt rgb24 "%IMAGES_DIRECTORY%\lossless.avi" ^
-map [copyHash] -f framehash -hash SHA512 "%IMAGES_DIRECTORY%\original.hashes" ^
-map [otherOut] {some other encoding} someOtherFile.idc

ffmpeg -start_number 0 -i "%IMAGES_DIRECTORY%\lossless.avi" -pix_fmt rgb24 -f framehash -hash SHA512  "%IMAGES_DIRECTORY%\decoded.hashes"

comp original.hashes decoded.hashes

So above, I would like to avoid the second call to ffmpeg. Like if I could split the lossless.avi output of the first call to two new streams: One to the file system and one to a demuxer feeding the hash muxer.

1 Answer 1

0

First, a nitpick: you don't want to compute hashes on the encoded frame data before or while writing. You're testing the fidelity of the lossless encoding so you need to compare the decoded frame of the x264 encode with the corresponding PNG.

So, first here's how to do what you specifically asked for.

Use the tee pseudo-muxer

ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "[0]{some filter here}[otherOut]" ^
-map 0 -c:v libx264rgb -qp 0 -pix_fmt rgb24 -f tee "%IMAGES_DIRECTORY%\lossless.avi|[f=avi]pipe:" ^
-map 0 -f framehash -hash SHA512 "%IMAGES_DIRECTORY%\original.hashes" ^
-map [otherOut] {some other encoding} someOtherFile.idc | ffmpeg -f avi -i - -f framehash -hash SHA512 %IMAGES_DIRECTORY%\decoded.hashes" 

If your end goal is to check the fidelity of the lossless encoding, use

ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" ^
-filter_complex "[0]{some filter here}[otherOut]" ^
-map 0 -c:v libx264rgb -qp 0 -pix_fmt rgb24 "%IMAGES_DIRECTORY%\lossless.avi" ^
-map [otherOut] {some other encoding} someOtherFile.idc

and then

ffmpeg -framerate 30 -start_number 0 -i "%IMAGES_DIRECTORY%\%%03d.png" -i lossless.avi ^
-filter_complex "ssim" -f null -

If the result is lossless, the readout will say

SSIM R:1.000000 (inf) G:1.000000 (inf) B:1.000000 (inf) All:1.000000 (inf)
5
  • This answer made so many different things click for me (hash doesn't use raw input, -map 0 instead of split, and that's what a tee is for). Thanks! But it doesn't avoid the problem of reading lossless.avi off of the disk to decode/compare it. In fact, you are also reading the original images off of the disk twice to compare them to the decoded image. Commented Sep 9, 2016 at 19:37
  • Is there no way to take encoded packets and fork them to a muxer and a decoder in the same FFMPEG instance? Commented Sep 9, 2016 at 20:01
  • No. Encoding occurs after decoding (and filtering), so that provision isn't there. Looks like you are concerned about disk I/O. What you could do is pipe lossless avi to another ffmpeg instance which computes hashes.
    – Gyan
    Commented Sep 9, 2016 at 20:16
  • I've edited my first command, so that the AVI output is simultaneously piped to another ffmpeg instance which then computes hashes on the decoded frames.
    – Gyan
    Commented Sep 10, 2016 at 6:42
  • And here I was looking up how to split outputs on the Windows command line. (To send the lossless.avi to a file and a pipe. Ugh.) This much better, thanks! The only issue was the output filename in the tee needed to be surrounded in single quotes. Also, I'm not sure that I like SSIM, as it is much more computationally complex than a hash and the output is subject to rounding errors. I'll do a quick performance comparison, but the ideal solution is to just do a bit-for-bit comparison as both streams are flowing through memory... but a hash is close enough. Commented Sep 12, 2016 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.