Osu: Resolve video playback issue on linux by bundling libavformat and so on with the package

Created on 22 Feb 2020  Â·  12Comments  Â·  Source: ppy/osu

Tested on Ubuntu 20.04 and Ubuntu 19.10 with lazer version ≥ 20191113

Simply copy libavcodec.so.58 , libavformat.so.58 , libavutil.so.56 and libswscale.so.5 into "AppDir/usr/lib/-linux-gnu/" then rename them to the correct filename.

On ubuntu 20.04 x86_64(64 bit), execute the following commands to copy:

cp /usr/lib/x86_64-linux-gnu/libavformat.so.58 ./libavformat.so &&cp /usr/lib/x86_64-linux-gnu/libavcodec.so.58 ./libavcodec.so &&cp /usr/lib/x86_64-linux-gnu/libavutil.so.56 ./libavutil.so &&cp /usr/lib/x86_64-linux-gnu/libswscale.so.5 ./libswscale.so
linux

Most helpful comment

I created the symlink libavformat.so , libavutil.so , libavcodec.so and libswscale.so to their origin libs (libavformat.so.58 , libavutil.so.56 , libavcodec.so.58 and libswscale.so.5) then run lazer , the problem disappeared.

All 12 comments

The fact that you have to copy the libraries to the app's cwd seems to suggests your shared object symlinks are somewhat incorrect, as the dynamic linker should be picking them up. You should check with LD_DEBUG=libs to see which binaries are being used at runtime.

That said, it might be a point of consideration to bundle ffmpeg either in framework or as part of appimage deployment, although I don't know if it's viable for technical (ABI compatibility?) or even legal reasons (would probably have to find ffmpeg binaries licensed under LGPL, instead of the GPL ones, since that could interfere with the MIT license used here and in framework).

So how the Windows Installer doing it? Can we do the same way with the Windows Installer?

On Windows, ffmpeg libraries are bundled framework-side as a NuGet package (osu.Framework.NativeLibs). Last time there was an attempt to package linux binaries it was deemed unviable due to distribution fragmentation. Unsure if that is still the case, but I wouldn't be surprised.

AppImage repo wiki has a page titled Bundling FFmpeg but it's quite WTF-worthy for me (dry one-sentence information about static binaries being available - how does that help in actually bundling it? - followed by a link to another repo that bundles ffmpeg as an npm package for some reason?)

I tried a few versions available and found none that would reliably work cross-distro. We'd likely have to build our own.

Maybe we could use a script which detects whether the ffmpeg libs are correctly symlinked then fix them instead to avoid legal problems?

I tried to run lazer on another Ubuntu 20.04 system with ffmpeg installed and LD_DEBUG=libs , and it crashes when using Triangles as intro or trying to load a beatmap's background video.
crashreport.txt

Seem like we need to do dependency check anyways before running lazer to ensure the required libraries and their version and at least notify the user of the problems (missing dependecy/the version is too old...), like the .NET Framework error on Windows.

There should be no such requirements.

@MATRIX-feather In the case you're citing it seems that a version of libavformat was found:

     54654: find library=libavformat [0]; searching
     54654:  search cache=/etc/ld.so.cache
     54654:  search path=/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib:/usr/lib      (system search path)
     54654:   trying file=/lib/x86_64-linux-gnu/libavformat
     54654:   trying file=/usr/lib/x86_64-linux-gnu/libavformat
     54654:   trying file=/lib/libavformat
     54654:   trying file=/usr/lib/libavformat

The case seems consistent with what I had yesterday - most likely /usr/lib/libavformat is pointing to a ffmpeg version <4, which framework doesn't support. The decoder would first fail silently at the start but then die loudly upon first call to GetConversionMatrix(). (The logs would show a VideoDecoder faulted error.) This will fail silently instead of causing a crash in the next release as ppy/osu-framework#3295 has been merged.

Ubuntu seems to be bad about ffmpeg in some cases, as in you can do $ ffmpeg -v, which will show v4, but then actually use a built-in older ffmpeg that you could have to manually uninstall. I don't think we should be checking binaries ourselves, I don't even think there's a reliable way to do so. I recall running strings at ffmpeg binaries before and no human-printable version number fell out as far as I could tell.

@bdach I had a look of the runtime.log just now , and found this error message:

2020-02-22 18:05:10: VideoDecoder faulted: System.DllNotFoundException: Unable to load shared library 'avformat' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libavformat: cannot open shared object file: No such file or directory
2020-02-22 18:05:10: at System.Runtime.InteropServices.NativeLibrary.LoadByName(String libraryName, QCallAssembly callingAssembly, Boolean hasDllImportSearchPathFlag, UInt32 dllImportSearchPathFlag, Boolean throwOnError)
2020-02-22 18:05:10: at System.Runtime.InteropServices.NativeLibrary.LoadLibraryByName(String libraryName, Assembly assembly, Nullable1 searchPath, Boolean throwOnError) 2020-02-22 18:05:10: at System.Runtime.InteropServices.NativeLibrary.Load(String libraryName, Assembly assembly, Nullable1 searchPath)
2020-02-22 18:05:10: at osu.Framework.Graphics.Video.VideoDecoder.<>c.b__56_0(String name)
2020-02-22 18:05:10: at FFmpeg.AutoGen.ffmpeg.<>c.<.cctor>b__5_318()
2020-02-22 18:05:10: at FFmpeg.AutoGen.ffmpeg.avformat_alloc_context()
2020-02-22 18:05:10: at osu.Framework.Graphics.Video.VideoDecoder.prepareDecoding()
2020-02-22 18:05:10: at osu.Framework.Graphics.Video.VideoDecoder.StartDecoding()

It says "cannot open shared object file: No such file or directory", that probably means the file "libavformat.so" actually doesn't exists in both /lib and /usr/lib or it was rename to another name that couldn't be found.

So I execute ls /usr/lib/x86_64-linux-gnu/ | grep "avformat", it returns with 2 files : libavformat.so.58 and libavformat.so.58.29.100 , then I create a symlink libavformat.so to libavformat.so.58 and run lazer again, that error message changed to ... libavutil: cannot open shared object file: No such file or directory ... , probably this is the core issue that causes lazer crash.

I created the symlink libavformat.so , libavutil.so , libavcodec.so and libswscale.so to their origin libs (libavformat.so.58 , libavutil.so.56 , libavcodec.so.58 and libswscale.so.5) then run lazer , the problem disappeared.

FYI: the nuget RID system has the capability to bundle different binaries for different distro. But that would potentially increase complexity of Linux installer (if we do have one in the future).

I modified the content of AppRun, this may help to solve the problem of ffmpeg libs
AppRun.zip

Edit: however , a system-wide ffmpeg installation is still needed to make the script run correctly

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lauthaiming picture lauthaiming  Â·  3Comments

Axeanz picture Axeanz  Â·  3Comments

Lerkeer picture Lerkeer  Â·  3Comments

Gabixel picture Gabixel  Â·  3Comments

lenzfilipski picture lenzfilipski  Â·  3Comments