mainsail-crew / moonraker-timelapse

Timelapse Plugin for moonraker
GNU General Public License v3.0
366 stars 86 forks source link

Use HW encoding capabilities #49

Open ayufan opened 2 years ago

ayufan commented 2 years ago

All recent Raspberry PIs (including the prior ones using 5.10 kernel) do support hardware acceleration of:

The RPI's with the 5.15 which is current LTS kernel shipped by default https://www.ubuntufree.com/raspberry-pi-os-is-now-powered-by-linux-5-15-lts-gets-experimental-wayland-backend-9to5linux/ as well do support hardware JPEG encoding.

The usage of hardware acceleration especially helps when using this plugin with RPI0.2W. It is possible to greatly increase the performance of encoding with the usage of h264_v4l2m2m instead of libx264 as a vcodec.

Unfortunately, hardware decoding of JPEG is not possible with ffmpeg as of today, even though there were patches https://patchwork.ffmpeg.org/project/ffmpeg/patch/01e9296a-d2ef-64f8-a501-ddc18f64fbfd@jkqxz.net/#30572.

Proposal

Allow to choose encoder between libx264 and h264_v4l2m2m

FrYakaTKoP commented 2 years ago

sorry for the late response.

Shouldn't be hard to do, even though it will probably only happen after i refactored the way how the ffmpeg call is built. It was ok as a "first" version, but concatenate a shell command like now has big limitation. Therefore i like to change to a different solution, which would allow much more flexible calling of ffmpeg.

ayufan commented 2 years ago

@FrYakaTKoP Np. It might be as easy as allowing to choose codec :) and bitrate. Those are two primary parameters to allow.

In case of h264_v4l2m2m you additionally need to specify -b:v 10M or whatever value you need.

FrYakaTKoP commented 2 years ago

could you please make example of a full command? Ideally run the plugin to generate a command and then extract that from the moonraker.log. Then modify it to use v4l2 and post both (filename, paths,etc. can be shorted/censored, i'm only interested in the structure). Maybe it's possible i make a quick hack which allows to just change the vcodec and then add the -b:v 10M to extraoutputparams

ayufan commented 2 years ago

@FrYakaTKoP Pretty easy. This is what I use on my Voron 0 and RPI3B+ (previously RPI0.2W):

diff --git a/component/timelapse.py b/component/timelapse.py
index d26a25e..dfb6b3a 100644
--- a/component/timelapse.py
+++ b/component/timelapse.py
@@ -652,9 +652,9 @@ class Timelapse:
                 + " -r " + str(fps) \
                 + " -i '" + inputfiles + "'" \
                 + filterParam \
-                + " -threads 2 -g 5" \
+                + " -threads 1 -g 5" \
                 + " -crf " + str(self.config['constant_rate_factor']) \
-                + " -vcodec libx264" \
+                + " -vcodec h264_v4l2m2m" \
                 + " -pix_fmt " + self.config['pixelformat'] \
                 + " -an" \
                 + " " + self.config['extraoutputparams'] \

And then as extraoutputparams: -b:v 10M. In general, previously encoding was unusable (on RPI0.2W) with average FPS of 0.7, now I get around 3.6 FPS (on RPI0.2W) with significantly lower CPU usage for my particular resolution of ArduCam 16MP.

The RPI+ does also have hardware MJPEG decoding, but FFMPEG does not support it as mentioned above. With that it would be able to easily encode 1920x1080p30 (on RPI0.2W) with 10-20% CPU usage.