ffmpeg-android-java icon indicating copy to clipboard operation
ffmpeg-android-java copied to clipboard

How to generate .so files for 64 bit support

Open yadavkohi opened this issue 5 years ago • 41 comments

Hi, I am uploading my build with the ffmpeg dependency in it. Google play store show warning to add support for 64-bit till 1-Aug-2019 otherwise user won't able to install apk.

Please suggest how to create .so file step by step to support 64-bit.

Thanks in advance

yadavkohi avatar May 14 '19 14:05 yadavkohi

I have found that http://writingminds.github.io/ffmpeg-android-java/ URL shows that the supported architecture are armv7, armv7-neon, armv8, x86, x86_64 while extracting the code from .aar file it has only these architectures armeabi, x86, armeabi-v7a.

Does anybody help with providing all the architecture.

yadavkohi avatar May 15 '19 05:05 yadavkohi

same issues! Anyone resolved?

HungTDO avatar May 22 '19 07:05 HungTDO

I have generated .so file for 64 bit cpu architecture but facing 2 issues :

  1. The CpuArch.java file contails 2 architecture alphanumeric value i.e. x86("0dd4dbad305ff197a1ea9e6158bd2081d229e70e"), ARMv7("871888959ba2f063e18f56272d0d98ae01938ceb") I want these value for other architecture as well (I dont know from where i got it)

  2. The .so file is generated in their corresponding folder but the FFMpeg code is having some ffmpeg file inside assets folder. from where i got those for other architecture.

Please help i am stuck in only these issues.

kohiyadav avatar May 22 '19 12:05 kohiyadav

I have generated .so file for 64 bit cpu architecture but facing 2 issues :

  1. The CpuArch.java file contails 2 architecture alphanumeric value i.e. x86("0dd4dbad305ff197a1ea9e6158bd2081d229e70e"), ARMv7("871888959ba2f063e18f56272d0d98ae01938ceb") I want these value for other architecture as well (I dont know from where i got it)
  2. The .so file is generated in their corresponding folder but the FFMpeg code is having some ffmpeg file inside assets folder. from where i got those for other architecture.

Please help i am stuck in only these issues.

Wait for your solution,haha

taurushz avatar May 28 '19 07:05 taurushz

I have removed all the JNI code and local folder and find that the code only uses assets ffmpeg binary to execute command the JNI wrapper is not in use.

kohiyadav avatar May 29 '19 06:05 kohiyadav

After lots of investigation i found that only the assets ffmpeg static binaries is used. if you removed all the code of JNI, local folder still the code executed properly.

Now I am looking for static binaries. Once done i will share all architecture static binaries.

kohiyadav avatar May 31 '19 05:05 kohiyadav

I am facing same warning from google, does anyone have solution for it?

WilsonChristian94 avatar Jun 25 '19 07:06 WilsonChristian94

I am facing the same issue anyone with solution.

zolamadolo avatar Jul 11 '19 18:07 zolamadolo

@kohiyadav have you found the fix for this? We are running out of time I guess

ashirmehmood1996 avatar Jul 16 '19 10:07 ashirmehmood1996

I have created ffmpeg 64 bit binaries. You can find it on https://github.com/yadavkohi/FFmpeg-64Bit

yadavkohi avatar Jul 16 '19 10:07 yadavkohi

Thanks for quick respond. As the read me file says: ("This repository contains ffmpeg-64 bit static binaries. It support following libraries: libmp3lame libx264 libfreetype libfontconfig").

My project is using libphotoprocessing.so. will these binaries work our for that ?

ashirmehmood1996 avatar Jul 16 '19 10:07 ashirmehmood1996

I think it will work.

yadavkohi avatar Jul 16 '19 10:07 yadavkohi

ok. Thanks let me try.

ashirmehmood1996 avatar Jul 16 '19 10:07 ashirmehmood1996

@yadavkohi Please share your shall script on https://github.com/yadavkohi/FFmpeg-64Bit , how you build it ?

nikunjparadva avatar Jul 20 '19 09:07 nikunjparadva

@ashirmehmood1996 ... How to use these files in gradle file system to support x64 bit ?

RajaReddyP avatar Jul 22 '19 07:07 RajaReddyP

@RajaReddyP I have simple pasted the 64-bit binaries in assets folder as @yadavkohi suggested. the app is behaving normal for now but it is difficult to tell that the app is using the 32-bit binaries or 64-bit. When I place 64-bit binaries only .The app crashes.

ashirmehmood1996 avatar Jul 22 '19 07:07 ashirmehmood1996

@RajaReddyP I have simple pasted the 64-bit binaries in assets folder as @yadavkohi suggested. the app is behaving normal for now but it is difficult to tell that the app is using the 32-bit binaries or 64-bit. When I place 64-bit binaries only .The app crashes.

and one more thing. my device is lg nexus 5x which is 64-bit arm architecture

ashirmehmood1996 avatar Jul 22 '19 07:07 ashirmehmood1996

@ashirmehmood1996 @yadavkohi Now can i place these files in assets folder and then remove this line " implementation 'com.writingminds:FFmpegAndroid:0.3.2'" from build.gradle then it will support 64 bit as google expecting ?

RajaReddyP avatar Jul 22 '19 07:07 RajaReddyP

// Your app's build.gradle apply plugin: 'com.android.app' android { compileSdkVersion xx defaultConfig { appId "com.example.yourappname" minSdkVersion xx targetSdkVersion xx versionCode x versionName "x.x" ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64' // ...

this is taken from the following link https://developer.android.com/distribute/best-practices/develop/64-bit

ashirmehmood1996 avatar Jul 22 '19 07:07 ashirmehmood1996

Hey Guys,

I am afraid of the way you are trying to add 64-bit support as it is not the proper way and can lead to rejection of the APK as it is not proper 64-bit support.

We are trying to get back with a proper 64-bit solution for this.

hiteshsondhi88 avatar Jul 22 '19 07:07 hiteshsondhi88

@hiteshsondhi88 about 9 days are left. Are you working on this?

ashirmehmood1996 avatar Jul 22 '19 07:07 ashirmehmood1996

@hiteshsondhi88 Actually we are closer to deadlines to submit updated application with x64 bit support.. that is the reason we are trying to resolve this issue.. Can you please send solution for this issue ASAP.

RajaReddyP avatar Jul 22 '19 07:07 RajaReddyP

@hiteshsondhi88 Its all depends on you, You are the Last Hope for us. Please make a latest 64 bit Binary.

nikunjparadva avatar Jul 22 '19 07:07 nikunjparadva

Please. I have added the library as suggested above and it is running fine but I am not sure if I will not be rejected on Playstore.

zolamadolo avatar Jul 22 '19 07:07 zolamadolo

Please. I have added the library as suggested above and it is running fine but I am not sure if I will not be rejected on Playstore.

same situation here

ashirmehmood1996 avatar Jul 22 '19 07:07 ashirmehmood1996

I don't think it will create any problem while using the 64-bit binaries that i have shared. Need to made some changes in .java file to adopt those architectures.

CPUArch.java changes: enum CpuArch { x86("0dd4dbad305ff197a1ea9e6158bd2081d229e70e"), ARMv7("871888959ba2f063e18f56272d0d98ae01938ceb"), ARMv8("8cc6b01618b14a07d86ed1d2e19befc957eefae6"), x86_64("3f486973998ca951b735cb0c0dd58e05424c81d4"), NONE(null);

private String sha1;

CpuArch(String sha1) {
    this.sha1 = sha1;
}

String getSha1(){
    return sha1;
}

static CpuArch fromString(String sha1) {
    if (!TextUtils.isEmpty(sha1)) {
        for (CpuArch cpuArch : CpuArch.values()) {
            if (sha1.equalsIgnoreCase(cpuArch.sha1)) {
                return cpuArch;
            }
        }
    }
    return NONE;
}

}

CpuArchHelper.java file changes

class CpuArchHelper {

static CpuArch getCpuArch() {
    Log.d("Build.CPU_ABI : " + Build.CPU_ABI);
    // check if device is x86 or x86_64
    if (Build.CPU_ABI.equals(getx86CpuAbi())) {
        return CpuArch.x86;
    } else if(Build.CPU_ABI.equals(getx86_64CpuAbi())){
        return CpuArch.x86_64;
    }else {
        // check if device is armeabi
        if (Build.CPU_ABI.equals(getArmeabiv7CpuAbi())) {
            // check if device is arm64 which is supported by ARMV7
                return CpuArch.ARMv7;
        } else if (Build.CPU_ABI.equals(getArm64CpuAbi())) {
            return CpuArch.ARMv8;
        }
    }
    return CpuArch.NONE;
}

static String getx86CpuAbi() {
    return "x86";
}

static String getx86_64CpuAbi() {
    return "x86_64";
}

static String getArm64CpuAbi() {
    return "arm64-v8a";
}

static String getArmeabiv7CpuAbi() {
    return "armeabi-v7a";
}

}

FFmpeg.java file changes @SuppressWarnings("unused") public class FFmpeg implements FFmpegInterface {

private final Context context;
private FFmpegExecuteAsyncTask ffmpegExecuteAsyncTask;
private FFmpegLoadLibraryAsyncTask ffmpegLoadLibraryAsyncTask;

private static final long MINIMUM_TIMEOUT = 10 * 1000;
private long timeout = Long.MAX_VALUE;

private static FFmpeg instance = null;

private FFmpeg(Context context) {
    this.context = context.getApplicationContext();
    Log.setDEBUG(Util.isDebug(this.context));
}

public static FFmpeg getInstance(Context context) {
    if (instance == null) {
        instance = new FFmpeg(context);
    }
    return instance;
}

@Override
public void loadBinary(FFmpegLoadBinaryResponseHandler ffmpegLoadBinaryResponseHandler) throws FFmpegNotSupportedException {
    String cpuArchNameFromAssets = null;
    switch (CpuArchHelper.getCpuArch()) {
        case x86:
            Log.i("Loading FFmpeg for x86 CPU");
            cpuArchNameFromAssets = "x86";
            break;
        case ARMv7:
            Log.i("Loading FFmpeg for armv7 CPU");
            cpuArchNameFromAssets = "armeabi-v7a";
            break;
        case ARMv8:
            Log.i("Loading FFmpeg for arm64-v8a CPU");
            cpuArchNameFromAssets = "arm64-v8a";
            break;

        case x86_64:
            Log.i("Loading FFmpeg for x86_64 CPU");
            cpuArchNameFromAssets = "x86_64";
            break;
        case NONE:
            throw new FFmpegNotSupportedException("Device not supported");
    }

    if (!TextUtils.isEmpty(cpuArchNameFromAssets)) {
        ffmpegLoadLibraryAsyncTask = new FFmpegLoadLibraryAsyncTask(context, cpuArchNameFromAssets, ffmpegLoadBinaryResponseHandler);
        ffmpegLoadLibraryAsyncTask.execute();
    } else {
        throw new FFmpegNotSupportedException("Device not supported");
    }
}

@Override
public void execute(Map<String, String> environvenmentVars, String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException {
    /*if (ffmpegExecuteAsyncTask != null && !ffmpegExecuteAsyncTask.isProcessCompleted()) {
        throw new FFmpegCommandAlreadyRunningException("FFmpeg command is already running, you are only allowed to run single command at a time");
    }*/
    if (cmd.length != 0) {
        String[] ffmpegBinary = new String[] { FileUtils.getFFmpeg(context, environvenmentVars) };
        String[] command = concatenate(ffmpegBinary, cmd);
        ffmpegExecuteAsyncTask = new FFmpegExecuteAsyncTask(command , timeout, ffmpegExecuteResponseHandler);
        ffmpegExecuteAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    } else {
        throw new IllegalArgumentException("shell command cannot be empty");
    }
}

public <T> T[] concatenate (T[] a, T[] b) {
    int aLen = a.length;
    int bLen = b.length;

    @SuppressWarnings("unchecked")
    T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
    System.arraycopy(a, 0, c, 0, aLen);
    System.arraycopy(b, 0, c, aLen, bLen);

    return c;
}

@Override
public void execute(String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException {
    execute(null, cmd, ffmpegExecuteResponseHandler);
}

@Override
public String getDeviceFFmpegVersion() throws FFmpegCommandAlreadyRunningException {
    ShellCommand shellCommand = new ShellCommand();
    CommandResult commandResult = shellCommand.runWaitFor(new String[] { FileUtils.getFFmpeg(context), "-version" });
    if (commandResult.success) {
        return commandResult.output.split(" ")[2];
    }
    // if unable to find version then return "" to avoid NPE
    return "";
}

@Override
public String getLibraryFFmpegVersion() {
    return context.getString(R.string.shipped_ffmpeg_version);
}

@Override
public boolean isFFmpegCommandRunning() {
    return ffmpegExecuteAsyncTask != null && !ffmpegExecuteAsyncTask.isProcessCompleted();
}

@Override
public boolean killRunningProcesses() {
    return Util.killAsync(ffmpegLoadLibraryAsyncTask) || Util.killAsync(ffmpegExecuteAsyncTask);
}

@Override
public void setTimeout(long timeout) {
    if (timeout >= MINIMUM_TIMEOUT) {
        this.timeout = timeout;
    }
}

}

yadavkohi avatar Jul 22 '19 08:07 yadavkohi

I don't think it will create any problem while using the 64-bit binaries that i have shared. Need to made some changes in .java file to adopt those architectures.

CPUArch.java changes: enum CpuArch { x86("0dd4dbad305ff197a1ea9e6158bd2081d229e70e"), ARMv7("871888959ba2f063e18f56272d0d98ae01938ceb"), ARMv8("8cc6b01618b14a07d86ed1d2e19befc957eefae6"), x86_64("3f486973998ca951b735cb0c0dd58e05424c81d4"), NONE(null);

private String sha1;

CpuArch(String sha1) {
    this.sha1 = sha1;
}

String getSha1(){
    return sha1;
}

static CpuArch fromString(String sha1) {
    if (!TextUtils.isEmpty(sha1)) {
        for (CpuArch cpuArch : CpuArch.values()) {
            if (sha1.equalsIgnoreCase(cpuArch.sha1)) {
                return cpuArch;
            }
        }
    }
    return NONE;
}

}

CpuArchHelper.java file changes

class CpuArchHelper {

static CpuArch getCpuArch() {
    Log.d("Build.CPU_ABI : " + Build.CPU_ABI);
    // check if device is x86 or x86_64
    if (Build.CPU_ABI.equals(getx86CpuAbi())) {
        return CpuArch.x86;
    } else if(Build.CPU_ABI.equals(getx86_64CpuAbi())){
        return CpuArch.x86_64;
    }else {
        // check if device is armeabi
        if (Build.CPU_ABI.equals(getArmeabiv7CpuAbi())) {
            // check if device is arm64 which is supported by ARMV7
                return CpuArch.ARMv7;
        } else if (Build.CPU_ABI.equals(getArm64CpuAbi())) {
            return CpuArch.ARMv8;
        }
    }
    return CpuArch.NONE;
}

static String getx86CpuAbi() {
    return "x86";
}

static String getx86_64CpuAbi() {
    return "x86_64";
}

static String getArm64CpuAbi() {
    return "arm64-v8a";
}

static String getArmeabiv7CpuAbi() {
    return "armeabi-v7a";
}

}

FFmpeg.java file changes @SuppressWarnings("unused") public class FFmpeg implements FFmpegInterface {

private final Context context;
private FFmpegExecuteAsyncTask ffmpegExecuteAsyncTask;
private FFmpegLoadLibraryAsyncTask ffmpegLoadLibraryAsyncTask;

private static final long MINIMUM_TIMEOUT = 10 * 1000;
private long timeout = Long.MAX_VALUE;

private static FFmpeg instance = null;

private FFmpeg(Context context) {
    this.context = context.getApplicationContext();
    Log.setDEBUG(Util.isDebug(this.context));
}

public static FFmpeg getInstance(Context context) {
    if (instance == null) {
        instance = new FFmpeg(context);
    }
    return instance;
}

@Override
public void loadBinary(FFmpegLoadBinaryResponseHandler ffmpegLoadBinaryResponseHandler) throws FFmpegNotSupportedException {
    String cpuArchNameFromAssets = null;
    switch (CpuArchHelper.getCpuArch()) {
        case x86:
            Log.i("Loading FFmpeg for x86 CPU");
            cpuArchNameFromAssets = "x86";
            break;
        case ARMv7:
            Log.i("Loading FFmpeg for armv7 CPU");
            cpuArchNameFromAssets = "armeabi-v7a";
            break;
        case ARMv8:
            Log.i("Loading FFmpeg for arm64-v8a CPU");
            cpuArchNameFromAssets = "arm64-v8a";
            break;

        case x86_64:
            Log.i("Loading FFmpeg for x86_64 CPU");
            cpuArchNameFromAssets = "x86_64";
            break;
        case NONE:
            throw new FFmpegNotSupportedException("Device not supported");
    }

    if (!TextUtils.isEmpty(cpuArchNameFromAssets)) {
        ffmpegLoadLibraryAsyncTask = new FFmpegLoadLibraryAsyncTask(context, cpuArchNameFromAssets, ffmpegLoadBinaryResponseHandler);
        ffmpegLoadLibraryAsyncTask.execute();
    } else {
        throw new FFmpegNotSupportedException("Device not supported");
    }
}

@Override
public void execute(Map<String, String> environvenmentVars, String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException {
    /*if (ffmpegExecuteAsyncTask != null && !ffmpegExecuteAsyncTask.isProcessCompleted()) {
        throw new FFmpegCommandAlreadyRunningException("FFmpeg command is already running, you are only allowed to run single command at a time");
    }*/
    if (cmd.length != 0) {
        String[] ffmpegBinary = new String[] { FileUtils.getFFmpeg(context, environvenmentVars) };
        String[] command = concatenate(ffmpegBinary, cmd);
        ffmpegExecuteAsyncTask = new FFmpegExecuteAsyncTask(command , timeout, ffmpegExecuteResponseHandler);
        ffmpegExecuteAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    } else {
        throw new IllegalArgumentException("shell command cannot be empty");
    }
}

public <T> T[] concatenate (T[] a, T[] b) {
    int aLen = a.length;
    int bLen = b.length;

    @SuppressWarnings("unchecked")
    T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
    System.arraycopy(a, 0, c, 0, aLen);
    System.arraycopy(b, 0, c, aLen, bLen);

    return c;
}

@Override
public void execute(String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException {
    execute(null, cmd, ffmpegExecuteResponseHandler);
}

@Override
public String getDeviceFFmpegVersion() throws FFmpegCommandAlreadyRunningException {
    ShellCommand shellCommand = new ShellCommand();
    CommandResult commandResult = shellCommand.runWaitFor(new String[] { FileUtils.getFFmpeg(context), "-version" });
    if (commandResult.success) {
        return commandResult.output.split(" ")[2];
    }
    // if unable to find version then return "" to avoid NPE
    return "";
}

@Override
public String getLibraryFFmpegVersion() {
    return context.getString(R.string.shipped_ffmpeg_version);
}

@Override
public boolean isFFmpegCommandRunning() {
    return ffmpegExecuteAsyncTask != null && !ffmpegExecuteAsyncTask.isProcessCompleted();
}

@Override
public boolean killRunningProcesses() {
    return Util.killAsync(ffmpegLoadLibraryAsyncTask) || Util.killAsync(ffmpegExecuteAsyncTask);
}

@Override
public void setTimeout(long timeout) {
    if (timeout >= MINIMUM_TIMEOUT) {
        this.timeout = timeout;
    }
}

}

you didn't mention this earlier. please add all required steps in read me of your binaries repository.

ashirmehmood1996 avatar Jul 22 '19 08:07 ashirmehmood1996

I have added the required file changes in my repository

yadavkohi avatar Jul 22 '19 09:07 yadavkohi

I don't think it will create any problem while using the 64-bit binaries that i have shared. Need to made some changes in .java file to adopt those architectures.

CPUArch.java changes: enum CpuArch { x86("0dd4dbad305ff197a1ea9e6158bd2081d229e70e"), ARMv7("871888959ba2f063e18f56272d0d98ae01938ceb"), ARMv8("8cc6b01618b14a07d86ed1d2e19befc957eefae6"), x86_64("3f486973998ca951b735cb0c0dd58e05424c81d4"), NONE(null);

private String sha1;

CpuArch(String sha1) {
    this.sha1 = sha1;
}

String getSha1(){
    return sha1;
}

static CpuArch fromString(String sha1) {
    if (!TextUtils.isEmpty(sha1)) {
        for (CpuArch cpuArch : CpuArch.values()) {
            if (sha1.equalsIgnoreCase(cpuArch.sha1)) {
                return cpuArch;
            }
        }
    }
    return NONE;
}

}

CpuArchHelper.java file changes

class CpuArchHelper {

static CpuArch getCpuArch() {
    Log.d("Build.CPU_ABI : " + Build.CPU_ABI);
    // check if device is x86 or x86_64
    if (Build.CPU_ABI.equals(getx86CpuAbi())) {
        return CpuArch.x86;
    } else if(Build.CPU_ABI.equals(getx86_64CpuAbi())){
        return CpuArch.x86_64;
    }else {
        // check if device is armeabi
        if (Build.CPU_ABI.equals(getArmeabiv7CpuAbi())) {
            // check if device is arm64 which is supported by ARMV7
                return CpuArch.ARMv7;
        } else if (Build.CPU_ABI.equals(getArm64CpuAbi())) {
            return CpuArch.ARMv8;
        }
    }
    return CpuArch.NONE;
}

static String getx86CpuAbi() {
    return "x86";
}

static String getx86_64CpuAbi() {
    return "x86_64";
}

static String getArm64CpuAbi() {
    return "arm64-v8a";
}

static String getArmeabiv7CpuAbi() {
    return "armeabi-v7a";
}

}

FFmpeg.java file changes @SuppressWarnings("unused") public class FFmpeg implements FFmpegInterface {

private final Context context;
private FFmpegExecuteAsyncTask ffmpegExecuteAsyncTask;
private FFmpegLoadLibraryAsyncTask ffmpegLoadLibraryAsyncTask;

private static final long MINIMUM_TIMEOUT = 10 * 1000;
private long timeout = Long.MAX_VALUE;

private static FFmpeg instance = null;

private FFmpeg(Context context) {
    this.context = context.getApplicationContext();
    Log.setDEBUG(Util.isDebug(this.context));
}

public static FFmpeg getInstance(Context context) {
    if (instance == null) {
        instance = new FFmpeg(context);
    }
    return instance;
}

@Override
public void loadBinary(FFmpegLoadBinaryResponseHandler ffmpegLoadBinaryResponseHandler) throws FFmpegNotSupportedException {
    String cpuArchNameFromAssets = null;
    switch (CpuArchHelper.getCpuArch()) {
        case x86:
            Log.i("Loading FFmpeg for x86 CPU");
            cpuArchNameFromAssets = "x86";
            break;
        case ARMv7:
            Log.i("Loading FFmpeg for armv7 CPU");
            cpuArchNameFromAssets = "armeabi-v7a";
            break;
        case ARMv8:
            Log.i("Loading FFmpeg for arm64-v8a CPU");
            cpuArchNameFromAssets = "arm64-v8a";
            break;

        case x86_64:
            Log.i("Loading FFmpeg for x86_64 CPU");
            cpuArchNameFromAssets = "x86_64";
            break;
        case NONE:
            throw new FFmpegNotSupportedException("Device not supported");
    }

    if (!TextUtils.isEmpty(cpuArchNameFromAssets)) {
        ffmpegLoadLibraryAsyncTask = new FFmpegLoadLibraryAsyncTask(context, cpuArchNameFromAssets, ffmpegLoadBinaryResponseHandler);
        ffmpegLoadLibraryAsyncTask.execute();
    } else {
        throw new FFmpegNotSupportedException("Device not supported");
    }
}

@Override
public void execute(Map<String, String> environvenmentVars, String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException {
    /*if (ffmpegExecuteAsyncTask != null && !ffmpegExecuteAsyncTask.isProcessCompleted()) {
        throw new FFmpegCommandAlreadyRunningException("FFmpeg command is already running, you are only allowed to run single command at a time");
    }*/
    if (cmd.length != 0) {
        String[] ffmpegBinary = new String[] { FileUtils.getFFmpeg(context, environvenmentVars) };
        String[] command = concatenate(ffmpegBinary, cmd);
        ffmpegExecuteAsyncTask = new FFmpegExecuteAsyncTask(command , timeout, ffmpegExecuteResponseHandler);
        ffmpegExecuteAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    } else {
        throw new IllegalArgumentException("shell command cannot be empty");
    }
}

public <T> T[] concatenate (T[] a, T[] b) {
    int aLen = a.length;
    int bLen = b.length;

    @SuppressWarnings("unchecked")
    T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
    System.arraycopy(a, 0, c, 0, aLen);
    System.arraycopy(b, 0, c, aLen, bLen);

    return c;
}

@Override
public void execute(String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException {
    execute(null, cmd, ffmpegExecuteResponseHandler);
}

@Override
public String getDeviceFFmpegVersion() throws FFmpegCommandAlreadyRunningException {
    ShellCommand shellCommand = new ShellCommand();
    CommandResult commandResult = shellCommand.runWaitFor(new String[] { FileUtils.getFFmpeg(context), "-version" });
    if (commandResult.success) {
        return commandResult.output.split(" ")[2];
    }
    // if unable to find version then return "" to avoid NPE
    return "";
}

@Override
public String getLibraryFFmpegVersion() {
    return context.getString(R.string.shipped_ffmpeg_version);
}

@Override
public boolean isFFmpegCommandRunning() {
    return ffmpegExecuteAsyncTask != null && !ffmpegExecuteAsyncTask.isProcessCompleted();
}

@Override
public boolean killRunningProcesses() {
    return Util.killAsync(ffmpegLoadLibraryAsyncTask) || Util.killAsync(ffmpegExecuteAsyncTask);
}

@Override
public void setTimeout(long timeout) {
    if (timeout >= MINIMUM_TIMEOUT) {
        this.timeout = timeout;
    }
}

}

@yadavkohi Thanks a lot. Final after making the java code changes I am able to utilize the binaries. To test it I removed 32 bit binaries and ran application on 64-bit binaries only and its working like a charm. Thanks again.

ashirmehmood1996 avatar Jul 22 '19 09:07 ashirmehmood1996

@ashirmehmood1996 Can you please tell me how to update these files ?

RajaReddyP avatar Jul 22 '19 09:07 RajaReddyP