Tell ffmpeg to drop frames to reduce memory usage?

3

1

I'm transcoding real-time footage from a security camera from MJPEG into MPEG2, using ffmpeg.

Unfortunately the machine doing the transcoding can't really keep up (100% CPU use) however it's "good enough" and I don't mind the occasional dropped frame. But for some reason ffmpeg is not dropping any frames, so the memory usage keeps increasing as the process lags behind the incoming frames, and then the machine runs out of memory and the video starts getting badly corrupted.

Is there some way to tell ffmpeg to drop frames more aggressively? The problems happen when the memory use reaches 1.9GB, so I tried using monit to restart the process when the memory goes above 1.5GB, however then it gets restarted every 10 minutes which breaks the preferred 15-minute length of each transcoded file.

This is the command I am using:

ffmpeg -overrun_nonfatal 1 -y -i udp://1.2.3.4
    -c mpeg2video -b:v 2M -vf transpose=2
    -preset ultrafast -an -r 30
    out.mkv

The manpage says the -r option can be used as an output option to drop frames, however I am doing this and it appears that it only drops frames to match the output framerate (30fps here) rather than dropping frames to catch up with the input stream.

The -vsync option also looks like it does a similar thing, trying to match a framerate rather than minimise buffering.

-frame_drop_threshold looks more promising, but again this seems to be about dropping frames to keep up with timestamps rather than trying to keep up with realtime encoding.

Is there some other option I can use that will tell ffmpeg to drop frames as needed in order to avoid using up so much memory? I imagine this would be in the realtime/streaming/low latency options but I can't seem to find anything!

Malvineous

Posted 2018-04-03T02:11:40.507

Reputation: 1 881

You may want to try an additional -r XX before your first -i to try and cap how fast the input is read. – Anaksunaman – 2018-04-03T05:35:56.780

Input -r is to regenerate input timestamps. – Gyan – 2018-04-03T06:19:01.143

You can slow processing speed by adding -vf realtime and see if that makes a difference – Gyan – 2018-04-03T06:28:19.023

@Mulvya: The manpage says -vf realtime is similar to -re in that it slows down processing to real time. The processing is already running slower than realtime (about 0.8x) so I don't think this would make any difference, unless I'm misunderstanding how it causes frames to be dropped? – Malvineous – 2018-04-03T07:52:48.273

It doesn't cause frames to be dropped. The idea was to see if slowing down encoding smoothed out memory use. – Gyan – 2018-04-03T08:44:04.193

@Mulvya: Unfortunately slowing down the encoding just makes it worse, because the unprocessed input frames just build up more quickly and use up more memory. The problem is that I need to speed up encoding so that it can work through the incoming data more quickly (getting it out of memory and onto disk), and dropping frames was one way I thought of doing this. – Malvineous – 2018-04-04T03:37:49.427

Answers

3

I've discovered this as being a problem for my environment when capturing from camera and streaming FULL HD and while network hit some bottleneck ffmpeg rtbufsize fills pretty quickly and ffmpeg starts to drop frames. This sounds like the solution for your problem.

The libavformat library provides some generic global options, which can be set on all the muxers and demuxersock:

rtbufsizeinteger (input)

    Set max memory used for buffering real-time frames.

Source: FFmpeg Formats Documentation

Assuming you want a 150 MB limited buffer, try this:

ffmpeg -rtbufsize 150M -overrun_nonfatal 1 -y -i udp://1.2.3.4 -c mpeg2video -b:v 2M -vf transpose=2 -preset ultrafast -an -r 30 out.mkv

That means, while the machine cannot keep up, it start to fill the incoming data to RAM, thus filling the buffer, which when it reaches the limit it will start to heavily drop the frames.

Desktop

Posted 2018-04-03T02:11:40.507

Reputation: 61