FFmpeg.AutoGen icon indicating copy to clipboard operation
FFmpeg.AutoGen copied to clipboard

ffmpeg static class fails to initialize on mobile.

Open emmauss opened this issue 2 years ago • 21 comments

Note: for support questions, please use stackoverflow or special repository on [github.com](in special repository github.com). This repository's issues are reserved for feature requests and bug reports.

  • **I'm submitting a ... **

    • [x] bug report
    • [ ] feature request
    • [ ] support request or question => Please do not submit support request or questions here, see note at the top of this template.
  • Do you want to request a feature or report a bug? Report a bug

  • What is the current behavior? ffmpeg static class fails to initialize on non desktop platforms, eg. Android. The line where it throws a PlatfromNotSupportedException is, https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/534a3eb0ff295bc9bc8382b311df407180ab5051/FFmpeg.AutoGen/FunctionResolverFactory.cs#L15

  • *If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem:

  • What is the expected behavior?

  • What is the motivation / use case for changing the behavior?

  • Please tell us about your environment:

  • version: 6.0. dotnet 7 Android
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)

emmauss avatar Apr 14 '23 14:04 emmauss

I wonder what PlatformID you are getting to make it fail. You can try to workaround by setting DynamicallyLoadedBindings.FunctionResolver = new LinuxFunctionResolver(); before calling DynamicallyLoadedBindings.Initialize(). Please, let me know upon result.

Ruslan-B avatar Apr 14 '23 14:04 Ruslan-B

GetPlatformId is called here, https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/15d15bdb5230fb1457883ad2b918cb94e6e1be59/FFmpeg.AutoGen/FFmpeg.cs#L17 , in the static constructor. I don't think it can be bypassed.

emmauss avatar Apr 14 '23 14:04 emmauss

StackTrace

at FFmpeg.AutoGen.FunctionResolverFactory.GetPlatformId()
at FFmpeg.AutoGen.ffmpeg..cctor()

emmauss avatar Apr 14 '23 14:04 emmauss

image Although my projects are all Net7, the autogen nuget package is net standard 2.0.

emmauss avatar Apr 14 '23 14:04 emmauss

Right, I see. I'll do hotfix.

Ruslan-B avatar Apr 14 '23 15:04 Ruslan-B

I wonder what PlatformID you are getting to make it fail. You can try to workaround by setting DynamicallyLoadedBindings.FunctionResolver = new LinuxFunctionResolver(); before calling DynamicallyLoadedBindings.Initialize(). Please, let me know upon result.

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android, https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/534a3eb0ff295bc9bc8382b311df407180ab5051/FFmpeg.AutoGen.Bindings.DynamicallyLoaded/Native/LinuxFunctionResolver.cs#L14

emmauss avatar Apr 15 '23 10:04 emmauss

Well, I guess you are the first one how trying this on android. You can create a copy of LinuxFunctionResolver with this thing private const string Libdl = "libdl.so"; - i.e. without version suffix.

Ruslan-B avatar Apr 15 '23 12:04 Ruslan-B

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android,

Question here from which set of bindings did you switched?

Ruslan-B avatar Apr 15 '23 15:04 Ruslan-B

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android,

Question here from which set of bindings did you switched?

I was using the legacy Autogen. I'm modifying an existing library to work on android, and it was made a while ago.

emmauss avatar Apr 15 '23 15:04 emmauss

I switched to using DynamicallyLoadedBindings, and the previous error no longer occurs. Instead it fails on dlopen, as libdl doesn't exist on android,

Question here from which set of bindings did you switched?

I was using the legacy Autogen. I'm modifying an existing library to work on android, and it was made a while ago.

focus my friend and give us details, as I have no understanding how and what runs dotNET on android now. we can do zoom session if you like too.

Ruslan-B avatar Apr 15 '23 16:04 Ruslan-B

Sorry for the misunderstanding. Let me start from the beginning. The project I'm porting is https://github.com/unosquare/ffmediaelement . It's currently outdated and uses ffmpeg 4.4 and FFMpeg.Autogen 4 nuget package. As the package, and the other Autogen packages were created using netstandard 2.0, and not multitargeting netstandard and net 5+, the exception I reported occurs because of this image

I switched to using https://www.nuget.org/packages/FFmpeg.AutoGen.Bindings.DynamicallyLoaded, updating ffmpeg to 6.0, and setting the resolver manually. This avoids the previous crash, but the Linux resolver doesn't work on android because libdl isn't provided with the android system. This is an issue from android and not dotnet, but the sdk provides ways to dynamically load libraries packaged in your app at runtime. So I made a custom resolver that uses dotnet's NativeLibrary and that works quite well.

internal class AndroidFunctionResolver : FunctionResolverBase
    {
        protected override nint GetFunctionPointer(nint nativeLibraryHandle, string functionName)
        {
            var func = NativeLibrary.GetExport(nativeLibraryHandle, functionName);

            return func;
        }
        protected override string GetNativeLibraryName(string libraryName, int version) => $"lib{libraryName}.so";

        protected override nint LoadNativeLibrary(string libraryName)
        {
            var lib = NativeLibrary.Load(libraryName);

            return lib;
        }
    }

The original project was ported to a cross platform toolkit, so it doesn't rely on wpf. the port isn't public at this moment so I can't share much.

emmauss avatar Apr 15 '23 19:04 emmauss

Well great if you manage to solve the issue, I guess we can close this topic - however would be nice if you share what is behind NativeLibrary call, if some one will try android once again.

Ruslan-B avatar Apr 19 '23 05:04 Ruslan-B

Well great if you manage to solve the issue, I guess we can close this topic - however would be nice if you share what is behind NativeLibrary call, if some one will try android once again.

NativeLibrary is dotnets loader. https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.nativelibrary?source=recommendations&view=net-7.0

emmauss avatar Apr 19 '23 06:04 emmauss

I'll try to address this in upcoming update. Wrt to 7.0 we have another issue #254 - I'll look into it when earlier issues will be solved.

Ruslan-B avatar Nov 15 '23 08:11 Ruslan-B

Sorry for the misunderstanding. Let me start from the beginning. The project I'm porting is https://github.com/unosquare/ffmediaelement . It's currently outdated and uses ffmpeg 4.4 and FFMpeg.Autogen 4 nuget package. As the package, and the other Autogen packages were created using netstandard 2.0, and not multitargeting netstandard and net 5+, the exception I reported occurs because of this image

I switched to using https://www.nuget.org/packages/FFmpeg.AutoGen.Bindings.DynamicallyLoaded, updating ffmpeg to 6.0, and setting the resolver manually. This avoids the previous crash, but the Linux resolver doesn't work on android because libdl isn't provided with the android system. This is an issue from android and not dotnet, but the sdk provides ways to dynamically load libraries packaged in your app at runtime. So I made a custom resolver that uses dotnet's NativeLibrary and that works quite well.

internal class AndroidFunctionResolver : FunctionResolverBase
    {
        protected override nint GetFunctionPointer(nint nativeLibraryHandle, string functionName)
        {
            var func = NativeLibrary.GetExport(nativeLibraryHandle, functionName);

            return func;
        }
        protected override string GetNativeLibraryName(string libraryName, int version) => $"lib{libraryName}.so";

        protected override nint LoadNativeLibrary(string libraryName)
        {
            var lib = NativeLibrary.Load(libraryName);

            return lib;
        }
    }

The original project was ported to a cross platform toolkit, so it doesn't rely on wpf. the port isn't public at this moment so I can't share much.

how to setup the rootpath?

zero16832 avatar Mar 18 '24 07:03 zero16832

Trying to use it on Android here. I followed the approach to create the AndroidFunctionResolver and set it on DynamicallyLoadedBindings.FunctionResolver but I still getting the platform not supported exception on https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/28e5e18cd1041b5243e1d88e35225ee5e0a64d7a/FFmpeg.AutoGen/FFmpeg.cs#L17

juanmalm avatar Mar 18 '24 11:03 juanmalm

Trying to use it on Android here. I followed the approach to create the AndroidFunctionResolver and set it on DynamicallyLoadedBindings.FunctionResolver but I still getting the platform not supported exception on

https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/28e5e18cd1041b5243e1d88e35225ee5e0a64d7a/FFmpeg.AutoGen/FFmpeg.cs#L17

dose you use it in unity?

zero16832 avatar Mar 18 '24 11:03 zero16832

Trying to use it on Android here. I followed the approach to create the AndroidFunctionResolver and set it on DynamicallyLoadedBindings.FunctionResolver but I still getting the platform not supported exception on https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/28e5e18cd1041b5243e1d88e35225ee5e0a64d7a/FFmpeg.AutoGen/FFmpeg.cs#L17

dose you use it in unity?

Nope. Using it on MAUI. I just realized I must move from FFmpeg.AutoGen package to FFmpeg.AutoGen.Abstractions and FFmpeg.AutoGen.Bindings.DynamicallyLoaded.

juanmalm avatar Mar 18 '24 12:03 juanmalm

I'll make possible to do a platform loader override within few days. However, I see you have a workaround.

Ruslan-B avatar Mar 26 '24 07:03 Ruslan-B