dukebw / lintel

A Python module to decode video frames directly, using the FFmpeg C API.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

segmentation fault when trying to read webm file

esc opened this issue · comments

I compiled lintel against ffmpeg 4.0.0 from conda-forge. I get segfaults when trying to decode a webm file:

(base) vhaenel@gpucluster02:~/lintel$ lintel_test --filename ../benchmarks/smth-smth-1.webm --width 0 --height 0
python: lintel/py_ext/lintelmodule.c:134: setup_vid_stream_context: Assertion `(video_stream->duration > 0) && (video_stream->nb_frames > 0)' failed.
Aborted (core dumped)

I have attached the file. To test it, please rename it to smth-smth-1.webm.

smth-smth-1

Same problem occurs when ffmpeg was compiled from source, following the instructions from README.

Hmm, this one may take some digging into FFmpeg's examples to see if they handle the webm container specially.

Your video has only one stream, but for some reason that video stream has a negative value for duration, and nb_frames = 0.

Out of curiousity, is your FFmpeg compiled with --enable-libvpx? You can see this from ffmpeg -version.

Just to add some more data points from my side: I can reproduce the error, and due to the odd-numbered width of this video (427) I can't convert the video to H.264. However, I am able to convert to PNG, so my FFmpeg's VP9 codec is working, at least.

One workaround that does work for me is to resize the video while converting to H.264/MP4 container:

ffmpeg -i smth-smth-1.webm -s 426x240 smth-smth-1.mp4

Lintel can handle the video after that. It does seem that Lintel just doesn't handle webm correctly, as even if I transcode to a new webm file, I still hit the same video_stream->nb_frames == 0 issue.

Hi All,

I was wondering if you can give this branch a try: https://github.com/dukebw/lintel/tree/webm-fix.

The problem with webm was that the container doesn't store information about either the duration or the number of frames per stream (see https://stackoverflow.com/a/32538549). So now we get duration from the AVFormatContext (instead of the AVStream), and approximate nb_frames from the average FPS.

If that branch fixes your issues, then I will merge it in. I also fixed a bug in receive_frame() (I was using the avcodec_send_packet() / avcodec_receive_frame() API slightly wrong), which affected the VP9 encoded video you uploaded.

I get a different error then:

(base) vhaenel@gpucluster02:~/lintel$ lintel_test --filename ../benchmarks/smth-smth-1.webm --width 0 --height 0
Ran out of frames. Looping.
time: 0.312794548999932
Traceback (most recent call last):
  File "/home/vhaenel/miniconda3/bin/lintel_test", line 11, in <module>
    load_entry_point('Lintel==0.0', 'console_scripts', 'lintel_test')()
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/click-6.7-py3.6.egg/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/click-6.7-py3.6.egg/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/click-6.7-py3.6.egg/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/click-6.7-py3.6.egg/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/Lintel-0.0-py3.6-linux-x86_64.egg/lintel/test/loadvid_test.py", line 172, in loadvid_test
    should_seek)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/Lintel-0.0-py3.6-linux-x86_64.egg/lintel/test/loadvid_test.py", line 112, in _loadvid_test_frame_nums
    plt.imshow(decoded_frames[i, ...])
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/pyplot.py", line 3189, in imshow
    ax = gca()
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/pyplot.py", line 984, in gca
    return gcf().gca(**kwargs)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/pyplot.py", line 601, in gcf
    return figure()
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/pyplot.py", line 548, in figure
    **kwargs)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/backend_bases.py", line 161, in new_figure_manager
    return cls.new_figure_manager_given_figure(num, fig)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/backend_bases.py", line 167, in new_figure_manager_given_figure
    canvas = cls.FigureCanvas(figure)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/backends/backend_qt5agg.py", line 24, in __init__
    super(FigureCanvasQTAgg, self).__init__(figure=figure)
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/backends/backend_qt5.py", line 234, in __init__
    _create_qApp()
  File "/home/vhaenel/miniconda3/lib/python3.6/site-packages/matplotlib/backends/backend_qt5.py", line 125, in _create_qApp
    raise RuntimeError('Invalid DISPLAY variable')
RuntimeError: Invalid DISPLAY variable

I tried:

matplotlib/matplotlib#3466

Using the patch:

(base) vhaenel@gpucluster02:~/lintel$ git diff
diff --git a/lintel/test/loadvid_test.py b/lintel/test/loadvid_test.py
index f7627fd..953456e 100644
--- a/lintel/test/loadvid_test.py
+++ b/lintel/test/loadvid_test.py
@@ -24,6 +24,7 @@ import matplotlib.pyplot as plt
 
 import lintel
 
+plt.switch_backend('agg')
 
 def _loadvid_test_vanilla(filename, width, height):
     """Tests the usual loadvid call, with a default FPS cap.

and got:

(base) vhaenel@gpucluster02:~/lintel$ lintel_test --filename ../benchmarks/smth-smth-1.webm --width 0 --height 0
Ran out of frames. Looping.
time: 0.039263828999992256
Ran out of frames. Looping.
time: 0.03922413199984476
Ran out of frames. Looping.
time: 0.03895704800015665
Ran out of frames. Looping.
time: 0.038944147999927736
Ran out of frames. Looping.
time: 0.03820108600007188
Ran out of frames. Looping.
time: 0.03833767900005114
Ran out of frames. Looping.
time: 0.03876225799990607
Ran out of frames. Looping.
time: 0.038565767000136475
Ran out of frames. Looping.
time: 0.03761931600001844
Ran out of frames. Looping.
time: 0.038617368000132046

Not sure what that means though.. Did it load it successfully?

Regarding the option you asked about:

(base) vhaenel@gpucluster02:~$ ffmpeg -version
ffmpeg: Relink `/home/vhaenel/miniconda3/bin/../lib/././libpng16.so.16' with `/lib/x86_64-linux-gnu/libpthread.so.0' for IFUNC symbol `longjmp'
ffmpeg version 3.4.2 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 4.8.2 (GCC) 20140120 (Red Hat 4.8.2-15)
configuration: --prefix=/home/vhaenel/miniconda3 --disable-doc --enable-shared --enable-static --extra-cflags='-Wall -g -m64 -pipe -O3 -march=x86-64 -fPIC -I/home/vhaenel/miniconda3/include' --extra-cxxflags='=-Wall -g -m64 -pipe -O3 -march=x86-64 -fPIC' --extra-libs='-L/home/vhaenel/miniconda3/lib -lz' --enable-pic --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --enable-libfreetype --enable-gnutls --enable-libx264
libavutil      55. 78.100 / 55. 78.100
libavcodec     57.107.100 / 57.107.100
libavformat    57. 83.100 / 57. 83.100
libavdevice    57. 10.100 / 57. 10.100
libavfilter     6.107.100 /  6.107.100
libavresample   3.  7.  0 /  3.  7.  0
libswscale      4.  8.100 /  4.  8.100
libswresample   2.  9.100 /  2.  9.100
libpostproc    54.  7.100 / 54.  7.100

Apparently not, eh?

Hmm, it seems to be working. I believe the thing about the display variables is because you have SSH'ed into a machine without X, and lintel_test is trying to pop up a plot. It should work with ssh -XC.

I shall merge this change into the master branch then, thank you!

Closing as fixed by #15