tanersener / mobile-ffmpeg

FFmpeg for Android, iOS and tvOS. Not maintained anymore. Superseded by FFmpegKit.
https://tanersener.github.io/mobile-ffmpeg
GNU General Public License v3.0
3.85k stars 787 forks source link

.executeAsync and .cancel doesn't work from under Unity on Android. #625

Closed DaniilGalahov closed 3 years ago

DaniilGalahov commented 3 years ago

I'm trying to use mobile-ffmpeg with Unity for recording video from device camera. I need to start video recording by command from parent Unity app, and then stop it by other command. To do this I'm using this code:

    public class AndroidWrapper
    {
        AndroidJavaClass config = null;
        AndroidJavaClass ffmpeg = null;

        public void CallFFMPEGAsync(string arguments)
        {
            AndroidJNI.AttachCurrentThread();

            config = new AndroidJavaClass("com.arthenica.mobileffmpeg.Config");
            using (config)
            {
                AndroidJavaObject sigXCpu = new AndroidJavaClass("com.arthenica.mobileffmpeg.Signal").GetStatic<AndroidJavaObject>("SIGXCPU");
                config.CallStatic("ignoreSignal", new object[] { sigXCpu });

                ffmpeg = new AndroidJavaClass("com.arthenica.mobileffmpeg.FFmpeg");

                using (ffmpeg)
                {
                    int result = ffmpeg.CallStatic<int>("executeAsync", new object[] { arguments });
                    Debug.Log("FFMPEG call result: " + result);
                }
            }

            AndroidJNI.DetachCurrentThread();
        }

        public void StopFFMPEG()
        {
            AndroidJNI.AttachCurrentThread();

            using (config)
            {
                AndroidJavaObject sigXCpu = new AndroidJavaClass("com.arthenica.mobileffmpeg.Signal").GetStatic<AndroidJavaObject>("SIGXCPU");
                config.CallStatic("ignoreSignal", new object[] { sigXCpu });

                if (ffmpeg != null)
                {
                    using (ffmpeg)
                    {
                        int result = ffmpeg.CallStatic<int>("cancel", new object[] {});
                        Debug.Log("FFMPEG call result: " + result);
                    }
                }
            }

            AndroidJNI.DetachCurrentThread();
        }
    }

Arguments contains almost the same as in your example on the main page:

-f android_camera -i 0:0 -r 30 <record file path>

But it just doesn't work. App crashing if I try to call CallFFMPEGAsync() or even StopFFMPEG(), without any error reports in logcat.

My environment is:

Please, tell me how to solve this.

tanersener commented 3 years ago

I'm not very familiar with Unity. So, I don't know what is wrong there.

But, I see that you use AndroidJNI.AttachCurrentThread(); methods. Are you sure you need these calls? I had tested some parts of Using MobileFFmpeg in Unity guide and didn't have to use them.

DaniilGalahov commented 3 years ago

AndroidJNI.AttachCurrentThread(); is required, because I using calls from other thread (for prevent Unity freezing while ffmpeg performs long operations).

int result = ffmpeg.CallStatic<int>("execute", new object[] { arguments }); works fine. Only executeAsync and cancel not working from Unity.

Also, after last tests I found this error in logcat: E Unity : AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='cancel' signature='()I' in class Lcom.arthenica.mobileffmpeg.FFmpeg;

tanersener commented 3 years ago

AndroidJNI.AttachCurrentThread(); is required, because I using calls from other thread (for prevent Unity freezing while ffmpeg performs long operations).

Okay. But, if you want to prevent freezing you should be running ffmpeg commands in another thread. AndroidJNI.AttachCurrentThread() doesn't create another thread for you. You are still in the same one. I'm not convinced that this is necessary. Your reason might be valid but your solution, using AndroidJNI.AttachCurrentThread(), is not relevant to your reason.

DaniilGalahov commented 3 years ago

AndroidJNI.AttachCurrentThread() doesn't create another thread for you. You are still in the same one. I'm not convinced that this is necessary.

It's necessary, in my architecture. But, anyway, even if I remove it and call my methods CallFFMPEGAsync() or StopFFMPEG() from main thread (for test purposes), mobile-ffmpeg isn't worked and I've got in logcat this error messages:

E Unity   : AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='executeAsync' signature='(Ljava/lang/String;)I' in class Lcom.arthenica.mobileffmpeg.FFmpeg;
E Unity   : java.lang.NoSuchMethodError: no static method with name='executeAsync' signature='(Ljava/lang/String;)I' in class Lcom.arthenica.mobileffmpeg.FFmpeg;

and

E Unity   : AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='cancel' signature='()I' in class Lcom.arthenica.mobileffmpeg.FFmpeg;
E Unity   : java.lang.NoSuchMethodError: no static method with name='cancel' signature='()I' in class Lcom.arthenica.mobileffmpeg.FFmpeg;

I.e., looks like executeAsync and cancel are not accessible.

github-actions[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.