Question

I am trying to build ffmpeg for android. I want to achieve two things with it. 1. Rotate video 2. Join two or more videos.

There are two approaches for having ffmpeg in my application. 1. Having ffmpeg executable, copying it to /data/package/ and executing ffmpeg commands. 2. Build ffmpeg library .so file with ndk and write jni code etc.

Which approach is best according to my needs? And can I have some code snippets that follows those approaches?

Was it helpful?

Solution

You can achieve it by two ways, I would do it with the first one:

Place your ffmpeg file into you raw folder.

You need to use the ffmpeg executable file using commands, but you'll need to place the file into a file-system folder and change the permissions of the file, so use this code:

public static void installBinaryFromRaw(Context context, int resId, File file) {
    final InputStream rawStream = context.getResources().openRawResource(resId);
    final OutputStream binStream = getFileOutputStream(file);

    if (rawStream != null && binStream != null) {
        pipeStreams(rawStream, binStream);

        try {
            rawStream.close();
            binStream.close();
        } catch (IOException e) {
            Log.e(TAG, "Failed to close streams!", e);
        }       

        doChmod(file, 777);
    }       
}
public static OutputStream getFileOutputStream(File file) {
    try {
        return new FileOutputStream(file);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "File not found attempting to stream file.", e);
    }
    return null;
}

public static void pipeStreams(InputStream is, OutputStream os) {
    byte[] buffer = new byte[IO_BUFFER_SIZE];
    int count;
    try {
        while ((count = is.read(buffer)) > 0) {
            os.write(buffer, 0, count);
        }
    } catch (IOException e) {
        Log.e(TAG, "Error writing stream.", e);
    }
}
public static void doChmod(File file, int chmodValue) {
    final StringBuilder sb = new StringBuilder();
    sb.append("chmod");
    sb.append(' ');
    sb.append(chmodValue);
    sb.append(' ');
    sb.append(file.getAbsolutePath());

    try {
        Runtime.getRuntime().exec(sb.toString());
    } catch (IOException e) {
        Log.e(TAG, "Error performing chmod", e);
    }
}

Call this method:

private void installFfmpeg() {
    File ffmpegFile = new File(getCacheDir(), "ffmpeg");
    String mFfmpegInstallPath = ffmpegFile.toString();
    Log.d(TAG, "ffmpeg install path: " + mFfmpegInstallPath);
    if (!ffmpegFile.exists()) {
        try {
            ffmpegFile.createNewFile();
        } catch (IOException e) {
            Log.e(TAG, "Failed to create new file!", e);
        }
        Utils.installBinaryFromRaw(this, R.raw.ffmpeg, ffmpegFile);
    }else{
        Log.d(TAG, "It was installed");
    }

    ffmpegFile.setExecutable(true);
}

Then, you will have your ffmpeg file ready to use by commands. (This way works for me but there are some people that says that it doesn't work, I don't know why, hope it isn't your case). Then, we use the ffmpeg with this code:

String command = "data/data/YOUR_PACKAGE/cache/ffmpeg" + THE_REST_OF_YOUR_COMMAND;
        try {
            Process process = Runtime.getRuntime().exec(command);
            process.waitFor();
            Log.d(TAG, "Process finished");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

As I said, you have to use the ffmpeg file by commands, so you should search on Internet and choose the command you want to use, then, add it into the command string. If the command fails, you won't be alerted by any log, so you should try your command with a terminal emulator and be sure that it works. If it doesn´t work, you won't see any result.

Hope it's useful!!

OTHER TIPS

The advantage of library approach is that you have better control over the progress of your conversion, and can tune it in the middle. One the other hand, operating the executable is a bit easier. Finally, you can simply install the ffmpeg4android app and work with their API.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top