1

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?

Rohit
  • 2,538
  • 6
  • 28
  • 41

2 Answers2

2

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!!

Gonzalo Solera
  • 1,182
  • 12
  • 26
  • Hi Gonzalo, this works perfectly :). One question, the file you gave me was ffmpeg 0.1.11, how can I build it again using latest ffmpeg? – Rohit Feb 25 '14 at 19:37
  • Hi rohit. I'm glad it works! You should compile it again and it's so difficult if you don't use linux... see this link: http://www.roman10.net/how-to-build-ffmpeg-with-ndk-r9/ – Gonzalo Solera Feb 25 '14 at 19:58
  • I used the same link to build ffmpeg also on linux. But still I cant build it. And btw link is for creating libffmpeg.so file and not for ffmpeg executable. – Rohit Feb 26 '14 at 13:21
  • oh sorry, I sent you an incorrect link. I can´t help you on creating a new ffmpeg because the one I use is compiled by a friend, not by me and I don't know how to compile it exactly... sorry... – Gonzalo Solera Feb 26 '14 at 15:43
  • it's bad approach to use FFmpeg BINARY, you're only allowed to use SHARED LIBRARIES (.so files) in commercial closed-source app (with LGPL License, without x264) – user25 May 17 '18 at 19:17
1

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.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Hi Alex, I tried this app before but its commercial version is paid. And yes, this app is fulfilling my needs. But I cant afford its license. Thanks. – Rohit Feb 25 '14 at 16:08
  • Yes, I understand your limitations. Actually, I don't think their licensing model is sustainable. But I think it was important to list it as one of options. – Alex Cohn Feb 25 '14 at 17:54
  • Yes, I completely agree with you. It was the only option in front of me before I saw the answer Gonzalo posted. I can achieve what I want using his answer. – Rohit Feb 25 '14 at 19:35