Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#5222 closed defect (invalid)

ffmpeg crashing for large "-filter_complex_script" inputs

Reported by: jsniff Owned by:
Priority: important Component: undetermined
Version: git-master Keywords: ffmpeg, video, crash
Cc: Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no

Description (last modified by richardpl)

We're experiencing an issue where ffmpeg seg faults for very large "-filter_complex_script" input files (roughly 3MB). The input file consists of a very large number of drawbox filters. The same processing pipeline works fine for smaller files, but seems to have an issue as the file size increases. Is there a hard limit to how large this file can be? If so, is there a "magic number" somewhere that we can increase and re-compile from source?

Does anyone have any other thoughts or advice?

Thanks in advance!

Change History (45)

comment:1 Changed 3 years ago by richardpl

  • Description modified (diff)
  • Summary changed from ffmpeg crashing for large “-filter_complex_script” inputs to ffmpeg crashing for large "-filter_complex_script" inputs

Please provide such files.
There should not be limit.

comment:2 Changed 3 years ago by jsniff

I will post such files in a few hrs.

comment:3 Changed 3 years ago by richardpl

  • Reproduced by developer set
  • Status changed from new to open
  • Version changed from unspecified to git-master

comment:4 Changed 3 years ago by jsniff

Here is filter file: https://www.dropbox.com/s/2fdbsc810qxsxyf/video_filters.1454607985?dl=0
We are using ffmpeg version 2.7.2. The video file is sensitive for us to release, but we've confirmed that for this particular filter file, the seg fault seems to occur with any video file, as long as there are more than 69,700 frames (the filters file references frames up to that point).
Let me know your experience!

comment:5 Changed 3 years ago by richardpl

This is certainly the wrong and inefficient way to do it. I will write filter which will read new filtergraph from each line of file.

So you would only need to change this script to split each drawbox into separate line and move enable option in front of line, something like this:

0,0 drawbox=......... # filter 0th frame
1,5 drawbox=......... # filter 1-5 frames

etc.

comment:6 Changed 3 years ago by jsniff

Thanks for your help. We’re open to any solution that you would propose. Fundamentally, the boxes need to change each frame. They seldom stay in the same place from frame to frame. So if the seg fault is due to the number of boxes being drawn, simply extending the boxes for multiple frames might not reduce the amount of input that ffmpeg is processing

comment:7 Changed 3 years ago by mbradshaw

  • Resolution set to invalid
  • Status changed from open to closed

You're getting a stack overflow from generating so many stack frames from all your nested filters[1].

This isn't a bug in FFmpeg, but instead a limitation of your computer. I'm closing as invalid.

[1]: http://stackoverflow.com/questions/35258868/ffmpeg-crashes-for-large-filter-complex-script-inputs#comment58235562_35258868

comment:8 Changed 3 years ago by richardpl

I wrote filter that reads filter graphs from input file, with it you can define millions of lines in file with something like this:

ffmpeg -i input.video -vf graphhint=graphs.txt output.video

Where graphs.txt is textual file consisting of lines like this:

0,0 drawbox=x=5:y=2:w=3:h=5
1,1 drawbox=x=6:y=3:w=4:h=5
2,22 drawbox=...

you get an idea, the '0,0' part means frames in range 0 to 0.

comment:9 Changed 3 years ago by jsniff

@richardpl I am trying that approach now

comment:10 Changed 3 years ago by ubitux

The script works for me here (memory consumption is about +200M). Can you provide a gdb backtrace?

BTW, you can use enable='eq(n,123)' instead of enable='between(n,123,123)'

comment:11 Changed 3 years ago by jsniff

@ubitux

what script? what command did you use? I'm trying @richardpl's approach now.

Last edited 3 years ago by jsniff (previous) (diff)

comment:12 Changed 3 years ago by ubitux

I used ffmpeg -f lavfi -i color=white:s=hd720 -filter_script video_filters.1454607985 -c:v ffv1 -y out.nut (and stopped manually after about 2 minutes of encoded video.

richarpl's approach is probably better, but it shouldn't crash.

comment:13 Changed 3 years ago by jsniff

@richardpl whenever i run your command, I get the error, No such filter: 'graphhint'. How can I get such a filter?

Last edited 3 years ago by jsniff (previous) (diff)

comment:14 Changed 3 years ago by richardpl

@jsniff: its patch on ffmpeg-devel, not yet pushed upstream.

comment:15 Changed 3 years ago by jsniff

@richardpl So it's not possible to test?

comment:16 Changed 3 years ago by richardpl

It is possible to test, just need to download patch, apply it and reconfigure and rebuild ffmpeg.

comment:17 Changed 3 years ago by jsniff

Last edited 3 years ago by jsniff (previous) (diff)

comment:18 Changed 3 years ago by richardpl

@jsniff yes

comment:19 Changed 3 years ago by jsniff

@richardpl great. i will try now.

comment:20 Changed 3 years ago by jsniff

@richardpl, if you don't mind me asking, how do you apply the patch? I stripped away that .patch file until the diff at beginning and the -- at the end.
I tried following some advice at links below after some googling, but it doesn't work for me. eg, patch -pl < attachment.patch results in " strip count l is not a number". Where attachment.patch is the file stripped down at the above link.

https://github.com/vivienschilis/ffmpeg-head

http://tipok.org.ua/node/24

comment:21 Changed 3 years ago by richardpl

If you have git installed use: git apply attachment.patch in ffmpeg directory.

patch -p1 < attachment.patch works to, note it is 1 and not l.

comment:22 Changed 3 years ago by jsniff

@richardpl I don't have git installed. Is there another way? Also, for ffmpeg directory. You mean I have to put patch file in same directory as where "which ffmpeg" directory is?

Last edited 3 years ago by jsniff (previous) (diff)

comment:23 Changed 3 years ago by richardpl

patch doeesn need to be in same directory, but can be for shorter command,
so put patch in ffmpeg directory and run this:

patch -p1 < attachment.patch

comment:24 Changed 3 years ago by jsniff

@richardpl, I have installed git. But when I do that, I get following errors:

error: doc/filters.texi: No such file or directory
error: libavfilter/Makefile: No such file or directory
error: libavfilter/allfilters.c: No such file or directory

When I just do patch -p1 < attachment.patch, without git, I get following error:

can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:


|diff --git a/doc/filters.texi b/doc/filters.texi
|index 8ae402a..241ded0 100644

a/doc/filters.texi

|+++ b/doc/filters.texi

comment:26 Changed 3 years ago by jsniff

@richardpl, that installs fine. However, when I type ffmpeg -filters, graphhint does not show up as a filter......it did show up in two places in logs of installation. Do I have to enable, the enabled filter in someway?

  1. Enabled filters:

graphhint

  1. CC libavfilter/vf_graphhint.o

./configure --enable-filter=graphhint

comment:27 Changed 3 years ago by richardpl

dont forget to install it or use ./ffmpeg

comment:28 Changed 3 years ago by jsniff

@richardpl, I guess I forgot ./configure --enable-filter=graphhint when installing initially.

comment:29 Changed 3 years ago by jsniff

@richarpl, so I just did that, then make, then make install, and graphhint is still not installed. Do I have to do something differently?

comment:30 Changed 3 years ago by richardpl

Perhaps it is installed in another directory, and you use still use old ffmpeg.
so start it with ./ffmpeg ....

comment:31 Changed 3 years ago by llogan

You should consider getting live help at the #ffmpeg IRC channel to figure out how to apply the patch, compiling, etc. That way you don't spam the ffmpeg-trac mailing list with dozens of back-and-forth comments.

comment:32 Changed 3 years ago by jsniff

@richardpl, ok, your code runs fine, but output doesn't display boxes. For your example, I added color before and after the below, but it didn't have any effect. So, what should I do for color?

0,0 drawbox=x=5:y=2:w=3:h=5
1,1 drawbox=x=6:y=3:w=4:h=5

comment:33 Changed 3 years ago by richardpl

just add ':color=invert' after h=5 make sure there is no spaces, because they are not ignored for now and they do breaks parsing.

comment:34 Changed 3 years ago by jsniff

@richardpl, when i do the below, there is no output.

0,0 drawbox=x=5:y=2:w=3:h=5:color=invert
1,1 drawbox=x=6:y=3:w=4:h=5:color=invert

what i think you mean is the below, but the below has no output as well......

0,0 drawbox=x=5:y=2:w=3:h=5:color=gray
1,1 drawbox=x=6:y=3:w=4:h=5:color=gray

comment:35 Changed 3 years ago by richardpl

How you test it? What is ffmpeg output?
It works fine here.

comment:36 Changed 3 years ago by jsniff

@richardpl, actually this works fine now. How did you fill the box though? What if you want a solid box? I will stress test it now for long videos.

comment:37 Changed 3 years ago by richardpl

add ':t=max'

comment:38 Changed 3 years ago by jsniff

@richardpl ya this works, i will stress-test for a few hours and let you know my thoughts. thanks!

comment:39 Changed 3 years ago by jsniff

@richardpl, does your framework allow for writing multiple boxes on one frame? It seems not to be working for me right now. When I do something like the below, the gray box shows up until frame 100, then the red box shows up until frame 200, then the blue box from frame 200 to 300. But the red box and blue box should have shown up before that.....

10,100 drawbox=x=13:y=14:w=15:h=16:color=gray:t=max
1,200 drawbox=x=60:y=34:w=35:h=36:color=red:t=max
1,300 drawbox=x=80:y=24:w=35:h=36:color=blue:t=max


comment:40 Changed 3 years ago by jsniff

@richardpl, I've tried a few variants. It's still doesn't allow for multiple boxes on an image. If you have any thoughts, please let me know.

comment:41 Changed 3 years ago by richardpl

For other boxes with overlapping frames you will need another file with lines and new graphhint instance.

I don't see how to do all them in same file.

So gray boxes would be in 1st file, red boxes in 2nd file and blue boxes in 3rd file, and any other boxes in next file.

-vf graphhint=gray.txt,graphhint=red.txt,graphhint=blue.txt ...

I also wrote luascript filter which would tehnically allow this in single file but script size would be even longer and parsing would be slower than graphhint approach.

comment:42 Changed 3 years ago by jsniff

@richardpl,

That works well. One other question/problem. Often times, my filter file is very long and has duplicate boxes of same color on same frame. So essentially, with your approach, you're asking me to break up the large file into several (possibly hundred or thousands) of text files. Is there another way to get around this? Possibly with luascript filter?

comment:43 Changed 3 years ago by richardpl

Nope, you still can do it in one file, but its more complicated, lets take your example above:

10,100 drawbox=x=13:y=14:w=15:h=16:color=gray:t=max
1,200 drawbox=x=60:y=34:w=35:h=36:color=red:t=max
1,300 drawbox=x=80:y=24:w=35:h=36:color=blue:t=max

It translates to this:

1,9 drawbox=x=60:y=34:w=35:h=36:color=red:t=max,drawbox=x=80:y=24:w=35:h=36:color=blue:t=max
10,100 drawbox=x=13:y=14:w=15:h=16:color=gray:t=max,drawbox=x=80:y=24:w=35:h=36:color=blue:t=max,drawbox=x=60:y=34:w=35:h=36:color=red:t=max
101,200 drawbox=x=60:y=34:w=35:h=36:color=red:t=max,drawbox=x=80:y=24:w=35:h=36:color=blue:t=max
201,300 drawbox=x=80:y=24:w=35:h=36:color=blue:t=max

comment:44 Changed 3 years ago by jsniff

@richardpl,

That works well. I just need to do some manipulating of original file then. I will stress test a bit more and let you know.

comment:45 Changed 3 years ago by jsniff

@richardpl,

I've done some stress-testing. This works well so far. Thanks! I'll keep you posted about it.

Note: See TracTickets for help on using tickets.