jc-kynesim / rpi-ffmpeg

FFmpeg work for RPI
Other
107 stars 25 forks source link

dmabufs: don't call buf_free() if buffer has no functions #75

Closed peat-psuwit closed 11 months ago

peat-psuwit commented 11 months ago

A dmabuf_h can have no functions if it's created through dmabuf_import() or dmabuf_import_mmap(). In those cases, a simple munmap() and/or close() should handle them just fine.


This fixes playing this HEVC-encoded video, where ffmpeg re-initializes HW acceleration a few times:

https://github.com/jc-kynesim/rpi-ffmpeg/assets/6771175/b5cf97b7-d4c2-4f73-976f-301f71ececd1

jc-kynesim commented 11 months ago

I find it hard to argue with that - fix will be in shortly. Thanks

peat-psuwit commented 11 months ago

Hmm actually, I think this is causing a leak. Will have to investigate further...

Note: on my system, /dev/dma_heap/linux,cma is not usable by non-root users.

jc-kynesim commented 11 months ago

I'll check too - I've been trying to clean up leaks in general recently. Do you think it is a dmabuf leak or a general memory one?

peat-psuwit commented 11 months ago

I think it's DMABUF leak. I actually use this for long-running IP camera ingestion, and the kernel log keeps printing these lines:

rpivid feb10000.codec: rpivid_h265_stop
cma: cma_alloc: linux,cma: alloc failed, req-size: 765 pages, ret: -12
<repeated 9 times>
rpivid feb10000.codec: rpivid_h265_start: (1920x1088)
cma: cma_alloc: linux,cma: alloc failed, req-size: 768 pages, ret: -12

(this is with this PR, of course. Otherwise it would outright crash)

I think this probably is specific to the mmap codepath. The codepath is probably not tested as much, as Raspbian/Raspberry Pi OS have a udev rule which opens up linux,cma node for video group. Meanwhile, I'm running NixOS with close-to-stock configuration.

Will try to open up permission of /dev/dma_heap/linux,cma to see if it helps.

peat-psuwit commented 11 months ago

Hmm... with linux,cma node accessible, the "alloc failed" message disappeared. However, the leak is still there. Or rather, a leak exists in both configurations - not sure if it's the same one or not.

The leak is significant enough that it takes down my 8 GB Raspberry Pi in ~2 hours...

jc-kynesim commented 11 months ago

OK - thats bad - in those 2 hours how often do you end up restarting the decode? Do you have something that I can use to replicate the issue - preferably on PiOS?

peat-psuwit commented 11 months ago
$ journalctl --boot -1 | grep rpivid_h265_start | wc -l
892

That's a lot of restarts! I mean, this 60-seconds clip alone causes 15 re-initialization with ffmpeg command.

https://github.com/jc-kynesim/rpi-ffmpeg/assets/6771175/0608e018-c1bf-4649-a022-b72abc7025c8

I think a plain ffmpeg should expose the problem. I'll also record 30-minutes video from the IP camera feed to helps exposing the leak.

(update: here you are: https://junk.peat-network.xyz/imoutestvideo-30min.mp4)


BTW, this is the kernel message that appears in the re-initialization loop:

rpivid feb10000.codec: rpivid_h265_start: (1920x1088)
rpivid feb10000.codec: SPS changed
rpivid feb10000.codec: PPS changed
rpivid feb10000.codec: rpivid_h265_stop
jc-kynesim commented 11 months ago

I've pushed some new patches including your fix and a patch for an obvious fd leak in the MMAP path. I haven't found anything obvious in the "normal" dmabuf path (and valgrind doesn't find anything) but maybe you'd like to give it a go. Given your previous report I'm not confident that this will fix it as I'd expect a frames worth of cma leakage per restart to die a lot faster than the 2 hours you report given the quantity of restarts.

Separately it strikes me that whatever you are using to generate that stream is doing something odd - my best guess (without, I admit, actually checking anything) is that you have a stream built for HLS and so split into chunks each a few seconds long with an EOS at the end so every time we hit one of them ffmpeg closes and then restarts decode. If you can avoid doing that it would make the whole thing a lot more efficient - decode is very efficient but startup isn't!

peat-psuwit commented 11 months ago

Hmm... ok. With ffmpeg command line tool, I seems to be unable to reproduce any leak with the DMABUF case. However, I can reproduce the leak in the MMAP case (and can confirm that the version you just pushed fixed it). Thus, it's possible that the DMABUF case's leak is contained within the application I used (it's Zoneminder, BTW).

Anyway, since the original crash issue with the MMAP code path is now solved (by 24221a3f8210), I'll now close this PR. Thank you!


Separately it strikes me that whatever you are using to generate that stream is doing something odd ... If you can avoid doing that it would make the whole thing a lot more efficient - decode is very efficient but startup isn't!

Unfortunately it's not something I have control of. As I said, this is a stream from IP camera (branded imou, BTW). While there might be some knobs to adjust the video quality or something, I doubt there's anything to change how the stream is encoded. The stream itself is actually delivered over RTSP. I used ffmpeg on my laptop to capture them in 'copy' mode, like this:

ffmpeg -t 30:0 -i '<rtsp url>' -codec copy imoutestvideo-30min.mp4
jc-kynesim commented 11 months ago

I've looked at it a bit harder now and it looks like the h/w is getting a reinit because VPS/SPS has changed - this forces a much harder reinit than we really want - urgh... it might be possible to make the reinit not quite so drastic but its very non-trivial.