ffmpeginteropx / FFmpegInteropX

FFmpeg decoding library for Windows 10 UWP and WinUI 3 Apps
Apache License 2.0
212 stars 53 forks source link

Support Windows Subsystem for Linux (WSL) #267

Open JunielKatarn opened 2 years ago

JunielKatarn commented 2 years ago

Starting with Windows 10, Microsoft provides a Linux runtime mechanism which can easily replace MSYS2 for developer workflows.

I have started a branch to add support for WSL which aims to keep compatibility with MSYS2 for those who want to keep working with that tool. https://github.com/ffmpeginteropx/FFmpegInteropX/tree/wsl-2022

The advantage of WSL is that it's much easier to add UNIX-specific dependencies without a manual download or Path editing (i.e. Perl). It is also very performant when correctly configured (instances on version 1 are a simple subsystem that translates system calls to be executed by Windows. Version 2 instances are more powerful but take a performance hit in terms of I/O).

brabebhin commented 2 years ago

Sounds good.

lukasf commented 2 years ago

Hi @JunielKatarn that sounds pretty interesting! We already looked into WSL some time back. But back then we quickly ran into problems with the ffmpeg build scripts. I think @brabebhin needed quite some hacking of the ffmpeg build scripts to produce output. Mostly this was due to file and path name handling. If things are working now with untouched ffmpeg build scripts, I'd be happy to replace MSYS2 with WSL (or support both).

Can you give some hints on the usage? Did you install pacman into WSL for dependencies, or is it possible to use apt? Did you use a native Perl or the Windows version we have?

JunielKatarn commented 2 years ago

Hi @JunielKatarn that sounds pretty interesting! We already looked into WSL some time back. But back then we quickly ran into problems with the ffmpeg build scripts. I think @brabebhin needed quite some hacking of the ffmpeg build scripts to produce output. Mostly this was due to file and path name handling. If things are working now with untouched ffmpeg build scripts, I'd be happy to replace MSYS2 with WSL (or support both).

I got a functional WSL-based build a couple years ago. It required some patching on FFmpeg configure scripts, but it was minimal.

I started an experimental branch here: https://github.com/ffmpeginteropx/FFmpegInteropX/tree/wsl-2022 (To compare with the current master): https://github.com/ffmpeginteropx/FFmpegInteropX/compare/master..wsl-2022

Currently, I'm blocked by some of the new dependencies (i.e. libdav1d). I may share exact errors encountered later.

lukasf commented 2 years ago

Oh, too bad that patching configure scripts is still required. We can only make this a new official build path if it works without patching stuff. If required changes are minimal, then at least there might be a chance to get this back into the ffmpeg repo.

brabebhin commented 2 years ago

I wonder if this may allow us to create a libass build

JunielKatarn commented 2 years ago

The changes ARE minimal, but I got a lot of backlash from the FFmpeg owners when I tried to submit the change due to some old-school bureaucratic conventions.

When I finally fixed those, they just ignored the change.

I will try to submit such change again in the following weeks, but I'd argue applying a simple patch locally should still do the trick for us. (Not a fan of on-spot patching, but also don't think using it should be a blocker).

@brabebhin I am not familiar with libass but if it can be built via MinGW, it can be built via WSL.

brabebhin commented 2 years ago

This bad guy

https://github.com/libass/libass

lukasf commented 2 years ago

I don't think that WSL will help here. Then problem is the autoconfig build system that just does not support MSVC toolchain at all. There is a PR open to add meson build to libass:

https://github.com/libass/libass/pull/330

It is open since 3 years, but there is a lot of work going on recently. If it gets merged, then it should finally be possible to build libass using MSVC. I am using meson already for building dav1d, so I have some experience with that already.

JunielKatarn commented 2 years ago

Hi @JunielKatarn that sounds pretty interesting! We already looked into WSL some time back. But back then we quickly ran into problems with the ffmpeg build scripts. I think @brabebhin needed quite some hacking of the ffmpeg build scripts to produce output. Mostly this was due to file and path name handling. If things are working now with untouched ffmpeg build scripts, I'd be happy to replace MSYS2 with WSL (or support both).

Can you give some hints on the usage? Did you install pacman into WSL for dependencies, or is it possible to use apt? Did you use a native Perl or the Windows version we have?

I have posted a patch to the ffmpeg-devel list, awaiting for its approval. Even if they take their time, it's a one-liner (plus an if condition) in the configure script.

See http://ffmpeg.org/pipermail/ffmpeg-devel/2022-October/302510.html .

You can also see the change comparison here: https://github.com/FFmpeg/FFmpeg/compare/master...JunielKatarn:FFmpeg:wsl

JunielKatarn commented 2 years ago

I don't think that WSL will help here. Then problem is the autoconfig build system that just does not support MSVC toolchain at all. There is a PR open to add meson build to libass:

If libass can't be built with MSVC, how does it get linked into FFmpegInteropX? What toolchain compiles it?

Is it essential for all FFmpeg builds, or can it be kept out (adding a switch to our build scripts)?

brabebhin commented 2 years ago

Libass is something we want to add to render subtitles ourselves. We don't have it cause we don't have a msvc build.

JunielKatarn commented 2 years ago

In that case, we should consider forking libass, and producing a separate NuGet package ourselves, in my opinion.

brabebhin commented 2 years ago

Yeah but how do we built it?

brabebhin commented 2 years ago

Now that I think of it, do we really need the build to be done by MSVC? I'd expect a linker to be able to link against a lib / dll / exe regardless of what produced that bin file.

lukasf commented 2 years ago

Libass is not required for FFmpeg and we currently do not include it in out builds. We can render subtitles without it. It is just that we do not support subtitle animations, which are pretty rare anyways.

Including libass would be helpful though, if we'd want to do custom subtitle rendering (e.g. for use with MediaPlayer in frame server mode).

Different C/C++ compilers are only theoretically compatible. In practice, various problems can occur if you try to link a library from compiler A with a lib from a different compiler B. That is why it is strongly recommended to only ever use a single compiler toolchain throughout a project. Life would be much easier for us if we could just link GCC compiled libs, but that's just now how it is.

The only way to include libass is waiting (hoping) for meson build system to be added, then we can build with MSVC and link the output.

JunielKatarn commented 2 years ago

Understood!

Though now I see libass is not related to building under WSL, I know Visual Studio ships with a Clang compiler toolset that should be compatible (linkable) with MSVC. Maybe this is a possible workaround?

The alternative is to try and build libass with mingw/GCC, hoping that its exported functions are ABI-safe. Again, this is off-topic at this point.

As a reminder, I have re-submitted the patch that enables WSL to the ffmpeg-devel list. Even if they won't take it, we could easily apply this tiny patch into our build system and thus dropping dependencies on CYGWIN.

JunielKatarn commented 2 years ago

Now that I think of it, do we really need the build to be done by MSVC? I'd expect a linker to be able to link against a lib / dll / exe regardless of what produced that bin file.

I don't know anything about libass's code base, but if it is plain standard C, that should work. If it's C++ and it exports symbols, it will be a problem when using different compilers/linkers.

lukasf commented 2 years ago

I am by no means a compiler expert. I only read multiple times that it is not recommended to mix different compiler outputs. It could be wrong. But what I know is that for creating a UWP app/dll, you can only link libs that are built for UWP target. Besides not using certain APIs, this requires passing the the /GL parameter to MSVC compiler. I don't know what MSVC does differently then, but you cannot link MSVC libs built without /GL into an UWP project. Since GCC/Clang do not know anything about UWP or /GL, I would be surprised if we could link such a lib.

If anyone likes to try this and can show that it works (functionality is there, plus check AppCertToolkit), I'd be happy to include this.

JunielKatarn commented 2 years ago

I'll take a look after getting WSL to work. If we build libass as a DLL, I don't think the /GL switch for the main UWP app should affect it at all. Those would likely be two separate images (one EXE, one DLL) with their own optimization/runtime semantics.

brabebhin commented 2 years ago

libass needs to be built with appcontainer support to work for UWP. I saw some mentions of that in their docs, but didn't dig much deeper. Technically it should work (VLC uses libass, not sure if on UWP though), but you never know.

JunielKatarn commented 2 years ago

We could explore a different approach for those dependencies (NOT ffmpeg itself):

VCPKG has ported tons of UNIX-only libraries in a way that can produce any variants we need (platform, config, linkage).

Apparently, the even have libass. https://github.com/microsoft/vcpkg/pull/5026

Note, the simplified buildability comes at the cost of configurability. Tweaking a particular lib to suit our needs may require heavy patching, which is why I suggest we keep building FFmpeg as a submodule.

I'll explore this approach send a PR if it works.