diff --git a/.classpath b/.classpath
index 3a0c88f..d57ec02 100644
--- a/.classpath
+++ b/.classpath
@@ -1,9 +1,9 @@
-
+
-
+
diff --git a/README.md b/README.md
index 4f677e1..7ad2b0c 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,9 @@ Android applications. It depends on the
[android-ffmpeg](https://github.com/guardianproject/android-ffmpeg) project to
provide the ffmpeg binary.
+For ease of developer use, we've included the FFMPEG and Sox binaries in the project,
+however, we strongly recommend you compile them yourselves using the steps below.
+
It is licensed under the GPLv3.
## Building
@@ -19,4 +22,11 @@ Then execute:
cd external/android-ffmpeg
./configure_make_everything.sh
+Once compiled, you will find the binaries at:
+
+external/android-ffmpeg/ffmpeg/ffmpeg
+external/android-ffmpeg/data/data/info.guardianproject.ffmpeg/app_opt/bin/sox
+
+You should replace the files in res/raw with these.
+
Then build the project in Eclipse.
diff --git a/external/android-ffmpeg b/external/android-ffmpeg
index 53fc9d4..61ea21c 160000
--- a/external/android-ffmpeg
+++ b/external/android-ffmpeg
@@ -1 +1 @@
-Subproject commit 53fc9d4e2972792236d9e4c4c5793322947a884e
+Subproject commit 61ea21c932d7498b8d330a421425e50e65c805aa
diff --git a/project.properties b/project.properties
index 484dab0..91d2b02 100644
--- a/project.properties
+++ b/project.properties
@@ -11,5 +11,5 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-17
+target=android-19
android.library=true
diff --git a/res/raw/ffmpeg b/res/raw/ffmpeg
new file mode 100755
index 0000000..d24cdce
Binary files /dev/null and b/res/raw/ffmpeg differ
diff --git a/res/raw/ffmpeg.mp3 b/res/raw/ffmpeg.mp3
deleted file mode 120000
index 01c28da..0000000
--- a/res/raw/ffmpeg.mp3
+++ /dev/null
@@ -1 +0,0 @@
-../../external/android-ffmpeg/ffmpeg/ffmpeg
\ No newline at end of file
diff --git a/res/raw/sox b/res/raw/sox
new file mode 100755
index 0000000..60d1849
Binary files /dev/null and b/res/raw/sox differ
diff --git a/res/raw/sox.mp3 b/res/raw/sox.mp3
deleted file mode 120000
index af7f4da..0000000
--- a/res/raw/sox.mp3
+++ /dev/null
@@ -1 +0,0 @@
-../../external/android-ffmpeg/data/data/info.guardianproject.ffmpeg/app_opt/bin/sox
\ No newline at end of file
diff --git a/src/net/sourceforge/sox/CrossfadeCat.java b/src/net/sourceforge/sox/CrossfadeCat.java
index 7de2225..78cfdd1 100644
--- a/src/net/sourceforge/sox/CrossfadeCat.java
+++ b/src/net/sourceforge/sox/CrossfadeCat.java
@@ -4,11 +4,9 @@
import java.io.IOException;
import java.util.ArrayList;
-import android.util.Log;
-
/**
* Concatenates two files together with a crossfade of user
- * defined length.
+ * defined mClipLength.
*
* It is a Java port of the scripts/crossfade_cat.sh script
* in the sox source tree.
@@ -34,32 +32,37 @@ public CrossfadeCat(SoxController controller, String firstFile, String secondFil
mSecondFile = secondFile;
mFadeLength = fadeLength;
mFinalMix = outFile;
+
+ //double mClipLength = mController.getLength(mFirstFile);
}
- public boolean start() throws IOException {
- // find length of first file
- double length = mController.getLength(mFirstFile);
-
- double trimLength = length - mFadeLength;
+ public boolean start() throws Exception {
+ // find mClipLength of first file
+
// Obtain trimLength seconds of fade out position from the first File
+ double firstFileLength = mController.getLength(mFirstFile);
+ double trimLength = firstFileLength - mFadeLength;
+
String trimmedOne = mController.trimAudio(mFirstFile, trimLength, mFadeLength);
+
if( trimmedOne == null )
- return abort();
-
- // We assume a fade out is needed (i.e., firstFile doesn't already fade out)
+ throw new IOException("audio trim did not complete: " + mFirstFile);
+
+ // We assume a fade out is needed (i.e., firstFile doesn't already fade out)
String fadedOne = mController.fadeAudio(trimmedOne, "t", 0, mFadeLength, mFadeLength);
if( fadedOne == null )
- return abort();
+ throw new IOException("audio fade did not complete: " + trimmedOne);
+
// Get crossfade section from the second file
String trimmedTwo = mController.trimAudio(mSecondFile, 0, mFadeLength);
if( trimmedTwo == null )
- return abort();
+ throw new IOException("audio trim did not complete: " + mSecondFile);
String fadedTwo = mController.fadeAudio(trimmedTwo, "t", mFadeLength, -1, -1);
if( fadedTwo == null )
- return abort();
+ throw new IOException("audio fade did not complete: " + trimmedTwo);
// Mix crossfaded files together at full volume
ArrayList files = new ArrayList();
@@ -69,30 +72,29 @@ public boolean start() throws IOException {
String crossfaded = new File(mFirstFile).getCanonicalPath() + "-x-" + new File(mSecondFile).getName() +".wav";
crossfaded = mController.combineMix(files, crossfaded);
if( crossfaded == null )
- return abort();
+ throw new IOException("crossfade did not complete");
// Trim off crossfade sections from originals
String trimmedThree = mController.trimAudio(mFirstFile, 0, trimLength);
if( trimmedThree == null )
- return abort();
+ throw new IOException("crossfade trim beginning did not complete");
String trimmedFour = mController.trimAudio(mSecondFile, mFadeLength, -1);
if( trimmedFour == null )
- return abort();
-
+ throw new IOException("crossfade trim end did not complete");
+
// Combine into final mix
files.clear();
files.add(trimmedThree);
files.add(crossfaded);
files.add(trimmedFour);
mFinalMix = mController.combine(files, mFinalMix);
+
+ if (mFinalMix == null)
+ throw new IOException("final mix did not complete");
+
return true;
}
-
- private boolean abort() {
- return false;
- }
-
}
diff --git a/src/net/sourceforge/sox/SoxController.java b/src/net/sourceforge/sox/SoxController.java
index d8269d8..4ad6873 100644
--- a/src/net/sourceforge/sox/SoxController.java
+++ b/src/net/sourceforge/sox/SoxController.java
@@ -3,18 +3,16 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
import java.util.Locale;
-import org.ffmpeg.android.BinaryInstaller;
+import org.ffmpeg.android.R;
import org.ffmpeg.android.ShellUtils.ShellCallback;
import android.content.Context;
@@ -25,23 +23,68 @@ public class SoxController {
String[] libraryAssets = {"sox"};
private String soxBin;
private File fileBinDir;
- private Context context;
private ShellCallback callback;
- public SoxController(Context _context, ShellCallback _callback) throws FileNotFoundException, IOException {
- context = _context;
- fileBinDir = context.getDir("bin",0);
+ public SoxController(Context context, File fileAppRoot, ShellCallback _callback) throws FileNotFoundException, IOException {
callback = _callback;
- if (!new File(fileBinDir, libraryAssets[0]).exists())
- {
- BinaryInstaller bi = new BinaryInstaller(context,fileBinDir);
- bi.installFromRaw();
- }
-
- soxBin = new File(fileBinDir,"sox").getCanonicalPath();
+ installBinaries(context, false);
+ fileBinDir = new File(soxBin).getParentFile();
+
+ }
+
+ public void installBinaries(Context context, boolean overwrite)
+ {
+ soxBin = installBinary(context, R.raw.sox, "sox", overwrite);
+ }
+
+ public String getBinaryPath ()
+ {
+ return soxBin;
+ }
+
+ private static String installBinary(Context ctx, int resId, String filename, boolean upgrade) {
+ try {
+ File f = new File(ctx.getDir("bin", 0), filename);
+ if (f.exists()) {
+ f.delete();
+ }
+ copyRawFile(ctx, resId, f, "0755");
+ return f.getCanonicalPath();
+ } catch (Exception e) {
+ Log.e(TAG, "installBinary failed: " + e.getLocalizedMessage());
+ return null;
+ }
}
+
+ /**
+ * Copies a raw resource file, given its ID to the given location
+ * @param ctx context
+ * @param resid resource id
+ * @param file destination file
+ * @param mode file permissions (E.g.: "755")
+ * @throws IOException on error
+ * @throws InterruptedException when interrupted
+ */
+ private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
+ {
+ final String abspath = file.getAbsolutePath();
+ // Write the iptables binary
+ final FileOutputStream out = new FileOutputStream(file);
+ final InputStream is = ctx.getResources().openRawResource(resid);
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = is.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ out.close();
+ is.close();
+ // Change the permissions
+ Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
+ }
+
+
private class LengthParser implements ShellCallback {
@@ -50,7 +93,6 @@ private class LengthParser implements ShellCallback {
@Override
public void shellOut(String shellLine) {
- Log.d("sox", shellLine);
if( !shellLine.startsWith("Length") )
return;
String[] split = shellLine.split(":");
@@ -89,12 +131,10 @@ public double getLength(String path) {
try {
execSox(cmd, sc);
- } catch (IOException e) {
- Log.e("sox","error getting length ",e);
- } catch (InterruptedException e) {
- Log.e("sox","error getting length",e);
- }
-
+ } catch (Exception e) {
+ return -1;
+ }
+
return sc.length;
}
@@ -105,7 +145,7 @@ public double getLength(String path) {
* @param length (optional)
* @return path to trimmed audio
*/
- public String trimAudio(String path, double start, double length) throws IOException {
+ public String trimAudio(String path, double start, double length) throws Exception {
ArrayList cmd = new ArrayList();
File file = new File(path);
@@ -122,18 +162,9 @@ public String trimAudio(String path, double start, double length) throws IOExcep
if( length != -1 )
cmd.add(length+"");
- try {
- int rc = execSox(cmd, callback);
- if( rc != 0 ) {
- Log.e(TAG, "trimAudio receieved non-zero return code!");
- outFile = null;
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ int rc = execSox(cmd, callback);
+ if( rc != 0 ) {
+ outFile = null;
}
if (file.exists())
@@ -158,8 +189,8 @@ public String fadeAudio(String path, String type, double fadeInLength, double st
final List curves = Arrays.asList( new String[]{ "q", "h", "t", "l", "p"} );
if(!curves.contains(type)) {
- Log.e(TAG, "fadeAudio: passed invalid type: " + type);
- return null;
+ throw new RuntimeException("fadeAudio: passed invalid type: " + type);
+
}
File file = new File(path);
@@ -180,7 +211,8 @@ public String fadeAudio(String path, String type, double fadeInLength, double st
try {
int rc = execSox(cmd, callback);
if(rc != 0) {
- Log.e(TAG, "fadeAudio receieved non-zero return code!");
+ //Log.e(TAG, "fadeAudio receieved non-zero return code!");
+
outFile = null;
}
} catch (IOException e) {
@@ -215,7 +247,7 @@ public String combineMix(List files, String outFile) {
try {
int rc = execSox(cmd, callback);
if(rc != 0) {
- Log.e(TAG, "combineMix receieved non-zero return code!");
+ // Log.e(TAG, "combineMix receieved non-zero return code!");
outFile = null;
}
} catch (IOException e) {
@@ -235,7 +267,7 @@ public String combineMix(List files, String outFile) {
* @param outFile
* @return outFile or null on failure
*/
- public String combine(List files, String outFile) {
+ public String combine(List files, String outFile) throws Exception {
ArrayList cmd = new ArrayList();
cmd.add(soxBin);
@@ -244,19 +276,12 @@ public String combine(List files, String outFile) {
}
cmd.add(outFile);
- try {
int rc = execSox(cmd, callback);
if(rc != 0) {
- Log.e(TAG, "combine receieved non-zero return code!");
- outFile = null;
+ throw new Exception ("exit code: " + rc);
+
}
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+
return outFile;
}
@@ -277,6 +302,7 @@ public int execSox(List cmd, ShellCallback sc) throws IOException,
InterruptedException {
String soxBin = new File(fileBinDir, "sox").getCanonicalPath();
+
Runtime.getRuntime().exec("chmod 700 " + soxBin);
return execProcess(cmd, sc);
}
@@ -284,6 +310,12 @@ public int execSox(List cmd, ShellCallback sc) throws IOException,
private int execProcess(List cmds, ShellCallback sc)
throws IOException, InterruptedException {
+ //ensure that the arguments are in the correct Locale format
+ for (String cmd :cmds)
+ {
+ cmd = String.format(Locale.US, "%s", cmd);
+ }
+
ProcessBuilder pb = new ProcessBuilder(cmds);
pb.directory(fileBinDir);
@@ -294,8 +326,8 @@ private int execProcess(List cmds, ShellCallback sc)
cmdlog.append(' ');
}
- Log.v(TAG, cmdlog.toString());
-
+ sc.shellOut(cmdlog.toString());
+
// pb.redirectErrorStream(true);
Process process = pb.start();
@@ -341,7 +373,7 @@ public void run() {
sc.shellOut(line);
} catch (IOException ioe) {
- Log.e(TAG, "error reading shell slog", ioe);
+ ioe.printStackTrace();
}
}
}
diff --git a/src/org/ffmpeg/android/BinaryInstaller.java b/src/org/ffmpeg/android/BinaryInstaller.java
deleted file mode 100644
index d2d514c..0000000
--- a/src/org/ffmpeg/android/BinaryInstaller.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package org.ffmpeg.android;
-/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
-/* See LICENSE for licensing information */
-
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-
-import android.content.Context;
-import android.util.Log;
-
-public class BinaryInstaller {
-
-
- File installFolder;
- Context context;
-
- private static int isARMv6 = -1;
- private static String CHMOD_EXEC = "700";
-
- private final static int FILE_WRITE_BUFFER_SIZE = 32256;
-
- public BinaryInstaller (Context context, File installFolder)
- {
- this.installFolder = installFolder;
-
- this.context = context;
- }
-
- //
- /*
- * Extract the Tor binary from the APK file using ZIP
- */
- public boolean installFromRaw () throws IOException, FileNotFoundException
- {
-
- InputStream is;
- File outFile;
-
- is = context.getResources().openRawResource(R.raw.ffmpeg);
- outFile = new File(installFolder, "ffmpeg");
- streamToFile(is, outFile, false, false, "700");
-
- is = context.getResources().openRawResource(R.raw.sox);
- outFile = new File(installFolder, "sox");
- streamToFile(is, outFile, false, false, "700");
-
- return true;
- }
-
-
- private static void copyAssetFile(Context ctx, String asset, File file) throws IOException, InterruptedException
- {
-
- DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
- InputStream is = new GZIPInputStream(ctx.getAssets().open(asset));
-
- byte buf[] = new byte[8172];
- int len;
- while ((len = is.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- out.close();
- is.close();
- }
- /*
- * Write the inputstream contents to the file
- */
- private static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip, String mode) throws IOException
-
- {
- byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
-
- int bytecount;
-
-
- OutputStream stmOut = new FileOutputStream(outFile, append);
-
- if (zip)
- {
- ZipInputStream zis = new ZipInputStream(stm);
- ZipEntry ze = zis.getNextEntry();
- stm = zis;
-
- }
-
- while ((bytecount = stm.read(buffer)) > 0)
- {
-
- stmOut.write(buffer, 0, bytecount);
-
- }
-
- stmOut.close();
- stm.close();
-
- Runtime.getRuntime().exec("chmod "+mode+" "+outFile.getCanonicalPath());
-
-
- return true;
-
- }
-
- //copy the file from inputstream to File output - alternative impl
- public void copyFile (InputStream is, File outputFile)
- {
-
- try {
- outputFile.createNewFile();
- DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile));
- DataInputStream in = new DataInputStream(is);
-
- int b = -1;
- byte[] data = new byte[1024];
-
- while ((b = in.read(data)) != -1) {
- out.write(data);
- }
-
- if (b == -1); //rejoice
-
- //
- out.flush();
- out.close();
- in.close();
- // chmod?
-
-
-
- } catch (IOException ex) {
- Log.e("ffmpeg", "error copying binary", ex);
- }
-
- }
-
-
-
- /**
- * Check if this is an ARMv6 device
- * @return true if this is ARMv6
- */
- private static boolean isARMv6() {
- if (isARMv6 == -1) {
- BufferedReader r = null;
- try {
- isARMv6 = 0;
- r = new BufferedReader(new FileReader("/proc/cpuinfo"));
- for (String line = r.readLine(); line != null; line = r.readLine()) {
- if (line.startsWith("Processor") && line.contains("ARMv6")) {
- isARMv6 = 1;
- break;
- } else if (line.startsWith("CPU architecture") && (line.contains("6TE") || line.contains("5TE"))) {
- isARMv6 = 1;
- break;
- }
- }
- } catch (Exception ex) {
- } finally {
- if (r != null) try {r.close();} catch (Exception ex) {}
- }
- }
- return (isARMv6 == 1);
- }
-
- /**
- * Copies a raw resource file, given its ID to the given location
- * @param ctx context
- * @param resid resource id
- * @param file destination file
- * @param mode file permissions (E.g.: "755")
- * @throws IOException on error
- * @throws InterruptedException when interrupted
- */
- private static void copyRawFile(Context ctx, int resid, File file, String mode, boolean isZipd) throws IOException, InterruptedException
- {
- final String abspath = file.getCanonicalPath();
- // Write the iptables binary
- final FileOutputStream out = new FileOutputStream(file);
- InputStream is = ctx.getResources().openRawResource(resid);
-
- if (isZipd)
- {
- ZipInputStream zis = new ZipInputStream(is);
- ZipEntry ze = zis.getNextEntry();
- is = zis;
- }
-
- byte buf[] = new byte[1024];
- int len;
- while ((len = is.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- out.close();
- is.close();
- // Change the permissions
- Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
- }
-
-
-}
diff --git a/src/org/ffmpeg/android/MediaDesc.java b/src/org/ffmpeg/android/Clip.java
similarity index 59%
rename from src/org/ffmpeg/android/MediaDesc.java
rename to src/org/ffmpeg/android/Clip.java
index cef9503..413ec5d 100644
--- a/src/org/ffmpeg/android/MediaDesc.java
+++ b/src/org/ffmpeg/android/Clip.java
@@ -1,6 +1,6 @@
package org.ffmpeg.android;
-public class MediaDesc implements Cloneable
+public class Clip implements Cloneable
{
public int width = -1;
@@ -23,7 +23,7 @@ public class MediaDesc implements Cloneable
public String mimeType;
public String startTime; //00:00:00 or seconds format
- public String duration; //00:00:00 or seconds format
+ public double duration = -1; //00:00:00 or seconds format
public String videoFilter;
public String audioFilter;
@@ -32,20 +32,39 @@ public class MediaDesc implements Cloneable
public String aspect;
public int passCount = 1; //default
- public MediaDesc clone () throws CloneNotSupportedException
+ public Clip ()
{
- return (MediaDesc)super.clone();
+
+ }
+
+ public Clip (String path)
+ {
+ this.path = path;
+ }
+
+ public Clip clone () throws CloneNotSupportedException
+ {
+ return (Clip)super.clone();
}
public boolean isImage() {
- return mimeType.startsWith("image");
+ if (mimeType != null)
+ return mimeType.startsWith("image");
+ else
+ return false;
}
public boolean isVideo() {
- return mimeType.startsWith("video");
+ if (mimeType != null)
+ return mimeType.startsWith("video");
+ else
+ return false;
}
public boolean isAudio() {
- return mimeType.startsWith("audio");
+ if (mimeType != null)
+ return mimeType.startsWith("audio");
+ else
+ return false;
}
}
diff --git a/src/org/ffmpeg/android/FfmpegController.java b/src/org/ffmpeg/android/FfmpegController.java
index c37c152..0731be6 100644
--- a/src/org/ffmpeg/android/FfmpegController.java
+++ b/src/org/ffmpeg/android/FfmpegController.java
@@ -10,8 +10,6 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -20,61 +18,108 @@
import org.ffmpeg.android.ShellUtils.ShellCallback;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.media.MediaMetadataRetriever;
import android.util.Log;
public class FfmpegController {
- File fileBinDir;
- Context mContext;
- private String ffmpegBin;
+
+ private String mFfmpegBin;
private final static String TAG = "FFMPEG";
private File mFileTemp;
- private String mCmdCat;
+ private String mCmdCat = "sh cat";
- public FfmpegController(Context context, File fileTemp) throws FileNotFoundException, IOException {
- mContext = context;
+ public FfmpegController(Context context, File fileTemp) throws FileNotFoundException, IOException {
mFileTemp = fileTemp;
- checkBinary ();
-
+ installBinaries(context, false);
}
- private void checkBinary () throws FileNotFoundException, IOException
+ public void installBinaries(Context context, boolean overwrite)
{
- fileBinDir = mContext.getDir("bin",0);
-
- long assetLength = mContext.getResources().openRawResourceFd(R.raw.ffmpeg).getLength();
- File fileBin = new File(fileBinDir,"ffmpeg");
-
- if (!fileBin.exists() || fileBin.length() != assetLength)
- {
- BinaryInstaller bi = new BinaryInstaller(mContext,fileBinDir);
- bi.installFromRaw();
+ mFfmpegBin = installBinary(context, R.raw.ffmpeg, "ffmpeg", overwrite);
+ }
+
+ public String getBinaryPath ()
+ {
+ return mFfmpegBin;
+ }
+
+ private static String installBinary(Context ctx, int resId, String filename, boolean upgrade) {
+ try {
+ File f = new File(ctx.getDir("bin", 0), filename);
+ if (f.exists()) {
+ f.delete();
+ }
+ copyRawFile(ctx, resId, f, "0755");
+ return f.getCanonicalPath();
+ } catch (Exception e) {
+ Log.e(TAG, "installBinary failed: " + e.getLocalizedMessage());
+ return null;
}
-
- ffmpegBin = fileBin.getCanonicalPath();
-
- mCmdCat = "sh cat";
-
}
+ /**
+ * Copies a raw resource file, given its ID to the given location
+ * @param ctx context
+ * @param resid resource id
+ * @param file destination file
+ * @param mode file permissions (E.g.: "755")
+ * @throws IOException on error
+ * @throws InterruptedException when interrupted
+ */
+ private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
+ {
+ final String abspath = file.getAbsolutePath();
+ // Write the iptables binary
+ final FileOutputStream out = new FileOutputStream(file);
+ final InputStream is = ctx.getResources().openRawResource(resid);
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = is.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ out.close();
+ is.close();
+ // Change the permissions
+ Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
+ }
+
+
+
private void execFFMPEG (List cmd, ShellCallback sc, File fileExec) throws IOException, InterruptedException {
- String ffmpegBin = new File(fileBinDir,"ffmpeg").getCanonicalPath();
- Runtime.getRuntime().exec("chmod 777 " +ffmpegBin);
-
+ enablePermissions();
+
execProcess (cmd, sc, fileExec);
}
+ private void enablePermissions () throws IOException
+ {
+ Runtime.getRuntime().exec("chmod 700 " + mFfmpegBin);
+
+ }
+
private void execFFMPEG (List cmd, ShellCallback sc) throws IOException, InterruptedException {
- execFFMPEG (cmd, sc, fileBinDir);
+ execFFMPEG (cmd, sc, new File(mFfmpegBin).getParentFile());
}
private int execProcess(List cmds, ShellCallback sc, File fileExec) throws IOException, InterruptedException {
+ //ensure that the arguments are in the correct Locale format
+ for (String cmd :cmds)
+ {
+ cmd = String.format(Locale.US, "%s", cmd);
+ }
+
ProcessBuilder pb = new ProcessBuilder(cmds);
pb.directory(fileExec);
@@ -86,25 +131,22 @@ private int execProcess(List cmds, ShellCallback sc, File fileExec) thro
cmdlog.append(' ');
}
- Log.d(TAG,cmdlog.toString());
+ sc.shellOut(cmdlog.toString());
- pb.redirectErrorStream(true);
- // pb.redirectErrorStream(true);
- Process process = pb.start();
+ //pb.redirectErrorStream(true);
+
+ Process process = pb.start();
-
- // any error message?
- /*
- StreamGobbler errorGobbler = new
- StreamGobbler(process.getErrorStream(), "ERROR", sc);
- */
-
+
+ // any error message?
+ StreamGobbler errorGobbler = new StreamGobbler(
+ process.getErrorStream(), "ERROR", sc);
+
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(process.getInputStream(), "OUTPUT", sc);
- // kick them off
- // errorGobbler.start();
+ errorGobbler.start();
outputGobbler.start();
int exitVal = process.waitFor();
@@ -112,19 +154,18 @@ private int execProcess(List cmds, ShellCallback sc, File fileExec) thro
sc.processComplete(exitVal);
return exitVal;
-
-
}
private int execProcess(String cmd, ShellCallback sc, File fileExec) throws IOException, InterruptedException {
+ //ensure that the argument is in the correct Locale format
+ cmd = String.format(Locale.US, "%s", cmd);
+
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.directory(fileExec);
- Log.d(TAG,cmd);
-
// pb.redirectErrorStream(true);
Process process = pb.start();
@@ -153,56 +194,56 @@ private int execProcess(String cmd, ShellCallback sc, File fileExec) throws IOEx
}
- public class FFMPEGArg
+ public class Argument
{
String key;
String value;
- public static final String ARG_VIDEOCODEC = "-vcodec";
- public static final String ARG_AUDIOCODEC = "-acodec";
+ public static final String VIDEOCODEC = "-vcodec";
+ public static final String AUDIOCODEC = "-acodec";
- public static final String ARG_VIDEOBITSTREAMFILTER = "-vbsf";
- public static final String ARG_AUDIOBITSTREAMFILTER = "-absf";
+ public static final String VIDEOBITSTREAMFILTER = "-vbsf";
+ public static final String AUDIOBITSTREAMFILTER = "-absf";
- public static final String ARG_VERBOSITY = "-v";
- public static final String ARG_FILE_INPUT = "-i";
- public static final String ARG_SIZE = "-s";
- public static final String ARG_FRAMERATE = "-r";
- public static final String ARG_FORMAT = "-f";
- public static final String ARG_BITRATE_VIDEO = "-b:v";
+ public static final String VERBOSITY = "-v";
+ public static final String FILE_INPUT = "-i";
+ public static final String SIZE = "-s";
+ public static final String FRAMERATE = "-r";
+ public static final String FORMAT = "-f";
+ public static final String BITRATE_VIDEO = "-b:v";
- public static final String ARG_BITRATE_AUDIO = "-b:a";
- public static final String ARG_CHANNELS_AUDIO = "-ac";
- public static final String ARG_FREQ_AUDIO = "-ar";
+ public static final String BITRATE_AUDIO = "-b:a";
+ public static final String CHANNELS_AUDIO = "-ac";
+ public static final String FREQ_AUDIO = "-ar";
- public static final String ARG_STARTTIME = "-ss";
- public static final String ARG_DURATION = "-t";
+ public static final String STARTTIME = "-ss";
+ public static final String DURATION = "-t";
}
- public void processVideo(MediaDesc in, MediaDesc out, boolean enableExperimental, ShellCallback sc) throws Exception {
+ public void processVideo(Clip in, Clip out, boolean enableExperimental, ShellCallback sc) throws Exception {
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
if (in.format != null)
{
- cmd.add(FFMPEGArg.ARG_FORMAT);
+ cmd.add(Argument.FORMAT);
cmd.add(in.format);
}
if (in.videoCodec != null)
{
- cmd.add(FFMPEGArg.ARG_VIDEOCODEC);
+ cmd.add(Argument.VIDEOCODEC);
cmd.add(in.videoCodec);
}
if (in.audioCodec != null)
{
- cmd.add(FFMPEGArg.ARG_AUDIOCODEC);
+ cmd.add(Argument.AUDIOCODEC);
cmd.add(in.audioCodec);
}
@@ -211,31 +252,31 @@ public void processVideo(MediaDesc in, MediaDesc out, boolean enableExperimental
if (out.videoBitrate > 0)
{
- cmd.add(FFMPEGArg.ARG_BITRATE_VIDEO);
+ cmd.add(Argument.BITRATE_VIDEO);
cmd.add(out.videoBitrate + "k");
}
if (out.width > 0)
{
- cmd.add(FFMPEGArg.ARG_SIZE);
+ cmd.add(Argument.SIZE);
cmd.add(out.width + "x" + out.height);
}
if (out.videoFps != null)
{
- cmd.add(FFMPEGArg.ARG_FRAMERATE);
+ cmd.add(Argument.FRAMERATE);
cmd.add(out.videoFps);
}
if (out.videoCodec != null)
{
- cmd.add(FFMPEGArg.ARG_VIDEOCODEC);
+ cmd.add(Argument.VIDEOCODEC);
cmd.add(out.videoCodec);
}
if (out.videoBitStreamFilter != null)
{
- cmd.add(FFMPEGArg.ARG_VIDEOBITSTREAMFILTER);
+ cmd.add(Argument.VIDEOBITSTREAMFILTER);
cmd.add(out.videoBitStreamFilter);
}
@@ -248,24 +289,24 @@ public void processVideo(MediaDesc in, MediaDesc out, boolean enableExperimental
if (out.audioCodec != null)
{
- cmd.add(FFMPEGArg.ARG_AUDIOCODEC);
+ cmd.add(Argument.AUDIOCODEC);
cmd.add(out.audioCodec);
}
if (out.audioBitStreamFilter != null)
{
- cmd.add(FFMPEGArg.ARG_AUDIOBITSTREAMFILTER);
+ cmd.add(Argument.AUDIOBITSTREAMFILTER);
cmd.add(out.audioBitStreamFilter);
}
if (out.audioChannels > 0)
{
- cmd.add(FFMPEGArg.ARG_CHANNELS_AUDIO);
+ cmd.add(Argument.CHANNELS_AUDIO);
cmd.add(out.audioChannels+"");
}
if (out.audioBitrate > 0)
{
- cmd.add(FFMPEGArg.ARG_BITRATE_AUDIO);
+ cmd.add(Argument.BITRATE_AUDIO);
cmd.add(out.audioBitrate + "k");
}
@@ -274,6 +315,12 @@ public void processVideo(MediaDesc in, MediaDesc out, boolean enableExperimental
cmd.add("-f");
cmd.add(out.format);
}
+
+ if (out.duration > 0)
+ {
+ cmd.add(Argument.DURATION);
+ cmd.add(out.duration);
+ }
if (enableExperimental)
{
@@ -288,7 +335,7 @@ public void processVideo(MediaDesc in, MediaDesc out, boolean enableExperimental
}
- public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images, MediaDesc audio, MediaDesc out, int durationPerSlide, ShellCallback sc) throws Exception
+ public Clip createSlideshowFromImagesAndAudio (ArrayList images, Clip audio, Clip out, int durationPerSlide, ShellCallback sc) throws Exception
{
final String imageBasePath = new File(mFileTemp,"image-").getCanonicalPath();
@@ -301,10 +348,10 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
String newImagePath = null;
int imageCounter = 0;
- MediaDesc imageCover = images.get(0); //add the first image twice
+ Clip imageCover = images.get(0); //add the first image twice
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
@@ -321,10 +368,10 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
execFFMPEG(cmd, sc);
- for (MediaDesc image : images)
+ for (Clip image : images)
{
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
@@ -347,7 +394,7 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
//then combine them
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-loop");
@@ -374,7 +421,7 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
//now combine and encode
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
@@ -391,10 +438,10 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
cmd.add("-map");
cmd.add("1:0");
- cmd.add(FFMPEGArg.ARG_AUDIOCODEC);
+ cmd.add(Argument.AUDIOCODEC);
cmd.add("aac");
- cmd.add(FFMPEGArg.ARG_BITRATE_AUDIO);
+ cmd.add(Argument.BITRATE_AUDIO);
cmd.add("128k");
}
@@ -402,7 +449,7 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
cmd.add("-strict");
cmd.add("-2");//experimental
- cmd.add(FFMPEGArg.ARG_VIDEOCODEC);
+ cmd.add(Argument.VIDEOCODEC);
if (out.videoCodec != null)
@@ -412,7 +459,7 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
if (out.videoBitrate != -1)
{
- cmd.add(FFMPEGArg.ARG_BITRATE_VIDEO);
+ cmd.add(Argument.BITRATE_VIDEO);
cmd.add(out.videoBitrate + "k");
}
@@ -444,11 +491,11 @@ public MediaDesc createSlideshowFromImagesAndAudio (ArrayList images,
out.avi – create this output file. Change it as you like, for example using another container like MP4.
*/
- public MediaDesc combineAudioAndVideo (MediaDesc videoIn, MediaDesc audioIn, MediaDesc out, ShellCallback sc) throws Exception
+ public Clip combineAudioAndVideo (Clip videoIn, Clip audioIn, Clip out, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
@@ -461,7 +508,7 @@ public MediaDesc combineAudioAndVideo (MediaDesc videoIn, MediaDesc audioIn, Med
cmd.add("-strict");
cmd.add("-2");//experimental
- cmd.add(FFMPEGArg.ARG_AUDIOCODEC);
+ cmd.add(Argument.AUDIOCODEC);
if (out.audioCodec != null)
cmd.add(out.audioCodec);
else
@@ -470,7 +517,7 @@ public MediaDesc combineAudioAndVideo (MediaDesc videoIn, MediaDesc audioIn, Med
}
- cmd.add(FFMPEGArg.ARG_VIDEOCODEC);
+ cmd.add(Argument.VIDEOCODEC);
if (out.videoCodec != null)
cmd.add(out.videoCodec);
else
@@ -480,19 +527,19 @@ public MediaDesc combineAudioAndVideo (MediaDesc videoIn, MediaDesc audioIn, Med
if (out.videoBitrate != -1)
{
- cmd.add(FFMPEGArg.ARG_BITRATE_VIDEO);
+ cmd.add(Argument.BITRATE_VIDEO);
cmd.add(out.videoBitrate + "k");
}
if (out.videoFps != null)
{
- cmd.add(FFMPEGArg.ARG_FRAMERATE);
+ cmd.add(Argument.FRAMERATE);
cmd.add(out.videoFps);
}
if (out.audioBitrate != -1)
{
- cmd.add(FFMPEGArg.ARG_BITRATE_AUDIO);
+ cmd.add(Argument.BITRATE_AUDIO);
cmd.add(out.audioBitrate + "k");
}
cmd.add("-y");
@@ -502,7 +549,7 @@ public MediaDesc combineAudioAndVideo (MediaDesc videoIn, MediaDesc audioIn, Med
if (out.width > 0)
{
- cmd.add(FFMPEGArg.ARG_SIZE);
+ cmd.add(Argument.SIZE);
cmd.add(out.width + "x" + out.height);
}
@@ -523,9 +570,9 @@ public MediaDesc combineAudioAndVideo (MediaDesc videoIn, MediaDesc audioIn, Med
}
- public MediaDesc convertImageToMP4 (MediaDesc mediaIn, int duration, String outPath, ShellCallback sc) throws Exception
+ public Clip convertImageToMP4 (Clip mediaIn, int duration, String outPath, ShellCallback sc) throws Exception
{
- MediaDesc result = new MediaDesc ();
+ Clip result = new Clip ();
ArrayList cmd = new ArrayList();
// ffmpeg -loop 1 -i IMG_1338.jpg -t 10 -r 29.97 -s 640x480 -qscale 5 test.mp4
@@ -533,7 +580,7 @@ public MediaDesc convertImageToMP4 (MediaDesc mediaIn, int duration, String outP
cmd = new ArrayList();
//convert images to MP4
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-loop");
@@ -542,7 +589,7 @@ public MediaDesc convertImageToMP4 (MediaDesc mediaIn, int duration, String outP
cmd.add("-i");
cmd.add(new File(mediaIn.path).getCanonicalPath());
- cmd.add(FFMPEGArg.ARG_FRAMERATE);
+ cmd.add(Argument.FRAMERATE);
cmd.add(mediaIn.videoFps);
cmd.add("-t");
@@ -553,7 +600,7 @@ public MediaDesc convertImageToMP4 (MediaDesc mediaIn, int duration, String outP
if (mediaIn.width != -1)
{
- cmd.add(FFMPEGArg.ARG_SIZE);
+ cmd.add(Argument.SIZE);
cmd.add(mediaIn.width + "x" + mediaIn.height);
// cmd.add("-vf");
// cmd.add("\"scale=-1:" + mediaIn.width + "\"");
@@ -561,7 +608,7 @@ public MediaDesc convertImageToMP4 (MediaDesc mediaIn, int duration, String outP
if (mediaIn.videoBitrate != -1)
{
- cmd.add(FFMPEGArg.ARG_BITRATE_VIDEO);
+ cmd.add(Argument.BITRATE_VIDEO);
cmd.add(mediaIn.videoBitrate + "");
}
@@ -585,30 +632,50 @@ public MediaDesc convertImageToMP4 (MediaDesc mediaIn, int duration, String outP
//ffmpeg -i input1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
//ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
- public MediaDesc convertToMP4Stream (MediaDesc mediaIn, String startTime, String duration, String outPath, ShellCallback sc) throws Exception
+ public Clip convertToMP4Stream (Clip mediaIn, String startTime, double duration, String outPath, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- MediaDesc mediaOut = new MediaDesc();
+ Clip mediaOut = new Clip();
mediaOut.path = outPath;
String mediaPath = new File(mediaIn.path).getCanonicalPath();
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
if (startTime != null)
{
- cmd.add(FFMPEGArg.ARG_STARTTIME);
+ cmd.add(Argument.STARTTIME);
cmd.add(startTime);
}
- if (duration != null)
+ if (duration != -1)
{
- cmd.add(FFMPEGArg.ARG_DURATION);
- cmd.add(duration);
+ cmd.add(Argument.DURATION);
+
+ double dValue = mediaIn.duration;
+ int hours = (int)(dValue/3600f);
+ dValue -= (hours*3600);
+
+ cmd.add("0");
+ cmd.add(String.format(Locale.US,"%s",hours));
+ cmd.add(":");
+
+ int min = (int)(dValue/60f);
+ dValue -= (min*60);
+
+ cmd.add("0");
+ cmd.add(String.format(Locale.US,"%s",min));
+ cmd.add(":");
+
+ cmd.add(String.format(Locale.US,"%f",dValue));
+
+ //cmd.add("00:00:" + String.format(Locale.US,"%f",mediaIn.duration));
+
+
}
cmd.add("-i");
@@ -622,7 +689,7 @@ public MediaDesc convertToMP4Stream (MediaDesc mediaIn, String startTime, String
cmd.add("-an");
- //cmd.add(FFMPEGArg.ARG_VIDEOBITSTREAMFILTER);
+ //cmd.add(Argument.VIDEOBITSTREAMFILTER);
cmd.add("-bsf:v");
cmd.add("h264_mp4toannexb");
@@ -637,11 +704,11 @@ public MediaDesc convertToMP4Stream (MediaDesc mediaIn, String startTime, String
}
- public MediaDesc convertToWaveAudio (MediaDesc mediaIn, String outPath, int sampleRate, int channels, ShellCallback sc) throws Exception
+ public Clip convertToWaveAudio (Clip mediaIn, String outPath, int sampleRate, int channels, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
if (mediaIn.startTime != null)
@@ -650,10 +717,10 @@ public MediaDesc convertToWaveAudio (MediaDesc mediaIn, String outPath, int samp
cmd.add(mediaIn.startTime);
}
- if (mediaIn.duration != null)
+ if (mediaIn.duration != -1)
{
cmd.add("-t");
- cmd.add(mediaIn.duration);
+ cmd.add(String.format(Locale.US,"%f",mediaIn.duration));
}
cmd.add("-i");
@@ -668,7 +735,7 @@ public MediaDesc convertToWaveAudio (MediaDesc mediaIn, String outPath, int samp
cmd.add("-vn");
- MediaDesc mediaOut = new MediaDesc();
+ Clip mediaOut = new Clip();
File fileOut = new File(outPath);
mediaOut.path = fileOut.getCanonicalPath();
@@ -680,11 +747,11 @@ public MediaDesc convertToWaveAudio (MediaDesc mediaIn, String outPath, int samp
return mediaOut;
}
- public MediaDesc convertTo3GPAudio (MediaDesc mediaIn, MediaDesc mediaOut, ShellCallback sc) throws Exception
+ public Clip convertTo3GPAudio (Clip mediaIn, Clip mediaOut, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add(new File(mediaIn.path).getCanonicalPath());
@@ -695,10 +762,11 @@ public MediaDesc convertTo3GPAudio (MediaDesc mediaIn, MediaDesc mediaOut, Shell
cmd.add(mediaIn.startTime);
}
- if (mediaIn.duration != null)
+ if (mediaIn.duration != -1)
{
cmd.add("-t");
- cmd.add(mediaIn.duration);
+ cmd.add(String.format(Locale.US,"%f",mediaIn.duration));
+
}
cmd.add("-vn");
@@ -727,11 +795,11 @@ public MediaDesc convertTo3GPAudio (MediaDesc mediaIn, MediaDesc mediaOut, Shell
return mediaOut;
}
- public MediaDesc convert (MediaDesc mediaIn, String outPath, ShellCallback sc) throws Exception
+ public Clip convert (Clip mediaIn, String outPath, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add(new File(mediaIn.path).getCanonicalPath());
@@ -742,14 +810,15 @@ public MediaDesc convert (MediaDesc mediaIn, String outPath, ShellCallback sc) t
cmd.add(mediaIn.startTime);
}
- if (mediaIn.duration != null)
+ if (mediaIn.duration != -1)
{
cmd.add("-t");
- cmd.add(mediaIn.duration);
+ cmd.add(String.format(Locale.US,"%f",mediaIn.duration));
+
}
- MediaDesc mediaOut = new MediaDesc();
+ Clip mediaOut = new Clip();
File fileOut = new File(outPath);
@@ -763,11 +832,11 @@ public MediaDesc convert (MediaDesc mediaIn, String outPath, ShellCallback sc) t
return mediaOut;
}
- public MediaDesc convertToMPEG (MediaDesc mediaIn, String outPath, ShellCallback sc) throws Exception
+ public Clip convertToMPEG (Clip mediaIn, String outPath, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add(new File(mediaIn.path).getCanonicalPath());
@@ -778,10 +847,11 @@ public MediaDesc convertToMPEG (MediaDesc mediaIn, String outPath, ShellCallback
cmd.add(mediaIn.startTime);
}
- if (mediaIn.duration != null)
+ if (mediaIn.duration != -1)
{
cmd.add("-t");
- cmd.add(mediaIn.duration);
+ cmd.add(String.format(Locale.US,"%f",mediaIn.duration));
+
}
@@ -792,7 +862,7 @@ public MediaDesc convertToMPEG (MediaDesc mediaIn, String outPath, ShellCallback
cmd.add("-f");
cmd.add("mpeg");
- MediaDesc mediaOut = mediaIn.clone();
+ Clip mediaOut = mediaIn.clone();
File fileOut = new File(outPath);
@@ -805,14 +875,14 @@ public MediaDesc convertToMPEG (MediaDesc mediaIn, String outPath, ShellCallback
return mediaOut;
}
- public void concatAndTrimFilesMPEG (ArrayList videos,MediaDesc out, boolean preConvert, ShellCallback sc) throws Exception
+ public void concatAndTrimFilesMPEG (ArrayList videos,Clip out, boolean preConvert, ShellCallback sc) throws Exception
{
int idx = 0;
if (preConvert)
{
- for (MediaDesc mdesc : videos)
+ for (Clip mdesc : videos)
{
if (mdesc.path == null)
continue;
@@ -820,7 +890,7 @@ public void concatAndTrimFilesMPEG (ArrayList videos,MediaDesc out, b
//extract MPG video
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add(mdesc.path);
@@ -831,10 +901,11 @@ public void concatAndTrimFilesMPEG (ArrayList videos,MediaDesc out, b
cmd.add(mdesc.startTime);
}
- if (mdesc.duration != null)
+ if (mdesc.duration != -1)
{
cmd.add("-t");
- cmd.add(mdesc.duration);
+ cmd.add(String.format(Locale.US,"%f",mdesc.duration));
+
}
/*
@@ -868,7 +939,7 @@ public void concatAndTrimFilesMPEG (ArrayList videos,MediaDesc out, b
idx = 0;
- for (MediaDesc vdesc : videos)
+ for (Clip vdesc : videos)
{
if (vdesc.path == null)
continue;
@@ -884,13 +955,11 @@ public void concatAndTrimFilesMPEG (ArrayList videos,MediaDesc out, b
cmdRun.append("> ");
cmdRun.append(mCatPath);
- Log.d(TAG,"cat cmd: " + cmdRun.toString());
-
String[] cmds = {"sh","-c",cmdRun.toString()};
Runtime.getRuntime().exec(cmds).waitFor();
- MediaDesc mInCat = new MediaDesc();
+ Clip mInCat = new Clip();
mInCat.path = mCatPath;
processVideo(mInCat, out, false, sc);
@@ -898,13 +967,13 @@ public void concatAndTrimFilesMPEG (ArrayList videos,MediaDesc out, b
out.path = mCatPath;
}
- public void extractAudio (MediaDesc mdesc, String audioFormat, File audioOutPath, ShellCallback sc) throws IOException, InterruptedException
+ public void extractAudio (Clip mdesc, String audioFormat, File audioOutPath, ShellCallback sc) throws IOException, InterruptedException
{
//no just extract the audio
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add(new File(mdesc.path).getCanonicalPath());
@@ -917,10 +986,11 @@ public void extractAudio (MediaDesc mdesc, String audioFormat, File audioOutPath
cmd.add(mdesc.startTime);
}
- if (mdesc.duration != null)
+ if (mdesc.duration != -1)
{
cmd.add("-t");
- cmd.add(mdesc.duration);
+ cmd.add(String.format(Locale.US,"%f",mdesc.duration));
+
}
cmd.add("-f");
@@ -933,7 +1003,7 @@ public void extractAudio (MediaDesc mdesc, String audioFormat, File audioOutPath
}
- class FileMover {
+ private class FileMover {
InputStream inputStream;
File destination;
@@ -962,16 +1032,14 @@ public int killVideoProcessor (boolean asRoot, boolean waitFor) throws IOExcepti
{
int killDelayMs = 300;
- String ffmpegBin = new File(mContext.getDir("bin",0),"ffmpeg").getCanonicalPath();
-
int result = -1;
int procId = -1;
- while ((procId = ShellUtils.findProcessId(ffmpegBin)) != -1)
+ while ((procId = ShellUtils.findProcessId(mFfmpegBin)) != -1)
{
- Log.d(TAG, "Found PID=" + procId + " - killing now...");
+ // Log.d(TAG, "Found PID=" + procId + " - killing now...");
String[] cmd = { ShellUtils.SHELL_CMD_KILL + ' ' + procId + "" };
@@ -982,8 +1050,6 @@ public int killVideoProcessor (boolean asRoot, boolean waitFor) throws IOExcepti
@Override
public void shellOut(String msg) {
- Log.d(TAG,"Killing ffmpeg:" + msg);
-
}
@Override
@@ -1001,29 +1067,30 @@ public void processComplete(int exitValue) {
}
- public MediaDesc trim (MediaDesc mediaIn, boolean withSound, String outPath, ShellCallback sc) throws Exception
+ public Clip trim (Clip mediaIn, boolean withSound, String outPath, ShellCallback sc) throws Exception
{
ArrayList cmd = new ArrayList();
- MediaDesc mediaOut = new MediaDesc();
+ Clip mediaOut = new Clip();
String mediaPath = mediaIn.path;
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
if (mediaIn.startTime != null)
{
- cmd.add(FFMPEGArg.ARG_STARTTIME);
+ cmd.add(Argument.STARTTIME);
cmd.add(mediaIn.startTime);
}
- if (mediaIn.duration != null)
+ if (mediaIn.duration != -1)
{
- cmd.add(FFMPEGArg.ARG_DURATION);
- cmd.add(mediaIn.duration);
+ cmd.add("-t");
+ cmd.add(String.format(Locale.US,"%f",mediaIn.duration));
+
}
cmd.add("-i");
@@ -1044,7 +1111,7 @@ public MediaDesc trim (MediaDesc mediaIn, boolean withSound, String outPath, She
return mediaOut;
}
- public void concatAndTrimFilesMP4Stream (ArrayList videos,MediaDesc out, boolean preconvertClipsToMP4, boolean useCatCmd, ShellCallback sc) throws Exception
+ public void concatAndTrimFilesMP4Stream (ArrayList videos,Clip out, boolean preconvertClipsToMP4, boolean useCatCmd, ShellCallback sc) throws Exception
{
@@ -1055,10 +1122,10 @@ public void concatAndTrimFilesMP4Stream (ArrayList videos,MediaDesc o
int tmpIdx = 0;
- for (MediaDesc vdesc : videos)
+ for (Clip vdesc : videos)
{
- MediaDesc mdOut = null;
+ Clip mdOut = null;
if (preconvertClipsToMP4)
{
@@ -1074,7 +1141,7 @@ public void concatAndTrimFilesMP4Stream (ArrayList videos,MediaDesc o
if (fileOut.exists())
fileOut.delete();
- mdOut = convertToMP4Stream(mdOut,null,null,fileOut.getCanonicalPath(), sc);
+ mdOut = convertToMP4Stream(mdOut,null,-1,fileOut.getCanonicalPath(), sc);
}
else
{
@@ -1114,15 +1181,13 @@ public void concatAndTrimFilesMP4Stream (ArrayList videos,MediaDesc o
cmdBuff.append(fileExportOut.getCanonicalPath() + ".ts");
- Log.d(TAG,"concat: " + cmdBuff.toString());
-
Runtime.getRuntime().exec(cmdBuff.toString());
ArrayList cmd = new ArrayList();
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
@@ -1145,7 +1210,7 @@ public void concatAndTrimFilesMP4Stream (ArrayList videos,MediaDesc o
//ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
ArrayList cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add("concat:" + sbCat.toString());
@@ -1169,13 +1234,13 @@ public void concatAndTrimFilesMP4Stream (ArrayList videos,MediaDesc o
}
- public MediaDesc getInfo (MediaDesc in) throws IOException, InterruptedException
+ public Clip getInfo (Clip in) throws IOException, InterruptedException
{
ArrayList cmd = new ArrayList();
cmd = new ArrayList();
- cmd.add(ffmpegBin);
+ cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
@@ -1184,12 +1249,9 @@ public MediaDesc getInfo (MediaDesc in) throws IOException, InterruptedException
InfoParser ip = new InfoParser(in);
execFFMPEG(cmd,ip, null);
- while (in.duration == null)
- {
- try{Thread.sleep(100);}
- catch (Exception e){}
-
- }
+ try{Thread.sleep(200);}
+ catch (Exception e){}
+
return in;
@@ -1197,10 +1259,10 @@ public MediaDesc getInfo (MediaDesc in) throws IOException, InterruptedException
private class InfoParser implements ShellCallback {
- private MediaDesc mMedia;
+ private Clip mMedia;
private int retValue;
- public InfoParser (MediaDesc media)
+ public InfoParser (Clip media)
{
mMedia = media;
}
@@ -1210,7 +1272,6 @@ public void shellOut(String shellLine) {
if (shellLine.contains("Duration:"))
{
- Log.d(TAG,"Parsing Length: " + shellLine);
// Duration: 00:01:01.75, start: 0.000000, bitrate: 8184 kb/s
String[] timecode = shellLine.split(",")[0].split(":");
@@ -1220,12 +1281,32 @@ public void shellOut(String shellLine) {
duration = Double.parseDouble(timecode[1].trim())*60*60; //hours
duration += Double.parseDouble(timecode[2].trim())*60; //minutes
- duration += Double.parseDouble(timecode[3].trim()); //minutes
+ duration += Double.parseDouble(timecode[3].trim()); //seconds
- mMedia.duration = String.format(Locale.US,"%.2f",duration);
+ mMedia.duration = duration;
}
+
+ // Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 16939 kb/s, 30.02 fps, 30 tbr, 90k tbn, 180k tbc
+ else if (shellLine.contains(": Video:"))
+ {
+ String[] line = shellLine.split(":");
+ String[] videoInfo = line[3].split(",");
+
+ mMedia.videoCodec = videoInfo[0];
+ }
+
+ //Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, s16, 121 kb/s
+ else if (shellLine.contains(": Audio:"))
+ {
+ String[] line = shellLine.split(":");
+ String[] audioInfo = line[3].split(",");
+
+ mMedia.audioCodec = audioInfo[0];
+
+ }
+
//
//Stream #0.0(und): Video: h264 (Baseline), yuv420p, 1280x720, 8052 kb/s, 29.97 fps, 90k tbr, 90k tbn, 180k tbc
@@ -1240,7 +1321,7 @@ public void processComplete(int exitValue) {
}
}
- class StreamGobbler extends Thread
+ private class StreamGobbler extends Thread
{
InputStream is;
String type;
@@ -1266,10 +1347,26 @@ public void run()
} catch (IOException ioe)
{
- Log.e(TAG,"error reading shell slog",ioe);
+ // Log.e(TAG,"error reading shell slog",ioe);
+ ioe.printStackTrace();
}
}
}
+
+ public static Bitmap getVideoFrame(String videoPath,long frameTime) throws Exception {
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+
+ try {
+ retriever.setDataSource(videoPath);
+ return retriever.getFrameAtTime(frameTime, MediaMetadataRetriever.OPTION_CLOSEST);
+
+ } finally {
+ try {
+ retriever.release();
+ } catch (RuntimeException ex) {
+ }
+ }
+ }
}
/*
diff --git a/src/org/ffmpeg/android/MediaUtils.java b/src/org/ffmpeg/android/MediaUtils.java
deleted file mode 100644
index c0bf004..0000000
--- a/src/org/ffmpeg/android/MediaUtils.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.ffmpeg.android;
-
-import android.graphics.Bitmap;
-import android.media.MediaMetadataRetriever;
-import android.util.Log;
-
-public class MediaUtils {
-
- public static Bitmap getVideoFrame(String videoPath,long frameTime) {
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-
- try {
- retriever.setDataSource(videoPath);
- return retriever.getFrameAtTime(frameTime, MediaMetadataRetriever.OPTION_CLOSEST);
- } catch (IllegalArgumentException ex) {
- Log.w("FFMPEG.MediaUtils", "illegal argument exception");
-
- } catch (RuntimeException ex) {
- Log.w("FFMPEG.MediaUtils", "error getting video frame");
- } finally {
- try {
- retriever.release();
- } catch (RuntimeException ex) {
- }
- }
- return null;
- }
-
-}
diff --git a/src/org/ffmpeg/android/filters/DrawBoxVideoFilter.java b/src/org/ffmpeg/android/filters/DrawBoxVideoFilter.java
index 77d5b62..5d74a0a 100644
--- a/src/org/ffmpeg/android/filters/DrawBoxVideoFilter.java
+++ b/src/org/ffmpeg/android/filters/DrawBoxVideoFilter.java
@@ -18,16 +18,14 @@ public class DrawBoxVideoFilter extends OverlayVideoFilter {
public int width;
public int height;
public String color;
- private Context context;
- public DrawBoxVideoFilter (int x, int y, int width, int height, int alpha, String color, Context context)
+ public DrawBoxVideoFilter (int x, int y, int width, int height, int alpha, String color, File tmpDir) throws Exception
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
- this.context = context;
if( alpha < 0 || alpha > 255 ) {
throw new IllegalArgumentException("Alpha must be an integer betweeen 0 and 255");
@@ -43,19 +41,13 @@ public DrawBoxVideoFilter (int x, int y, int width, int height, int alpha, Strin
Canvas canvas = new Canvas(temp_box);
canvas.drawBitmap(bitmap, 0, 0, paint);
- try {
- File outputFile;
- outputFile = File.createTempFile("box_"+width+height+color, ".png", new File("/sdcard")/*context.getCacheDir()*/);
- FileOutputStream os = new FileOutputStream(outputFile);
- temp_box.compress(Bitmap.CompressFormat.PNG, 100, os);
- overlayFile = outputFile;
- xParam = Integer.toString(x);
- yParam = Integer.toString(y);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
+ File outputFile;
+ outputFile = File.createTempFile("box_"+width+height+color, ".png", tmpDir);
+ FileOutputStream os = new FileOutputStream(outputFile);
+ temp_box.compress(Bitmap.CompressFormat.PNG, 100, os);
+ overlayFile = outputFile;
+ xParam = Integer.toString(x);
+ yParam = Integer.toString(y);
}
}
diff --git a/src/org/ffmpeg/android/test/ConcatTest.java b/src/org/ffmpeg/android/test/ConcatTest.java
index 66e33ed..6b69962 100644
--- a/src/org/ffmpeg/android/test/ConcatTest.java
+++ b/src/org/ffmpeg/android/test/ConcatTest.java
@@ -1,5 +1,66 @@
package org.ffmpeg.android.test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Locale;
+
+import net.sourceforge.sox.SoxController;
+
+import org.ffmpeg.android.Clip;
+import org.ffmpeg.android.FfmpegController;
+import org.ffmpeg.android.ShellUtils;
+
public class ConcatTest {
+ public static void test (String videoRoot, String fileTmpPath, String fileOut, double fadeLen) throws Exception
+ {
+ File fileTmp = new File(fileTmpPath);
+ File fileAppRoot = new File("");
+ File fileVideoRoot = new File(videoRoot);
+
+ FfmpegController fc = new FfmpegController(null, fileTmp);
+ SoxController sxCon = new SoxController(null, fileAppRoot, null);
+
+ ArrayList listVideos = new ArrayList();
+
+ String[] fileList = fileVideoRoot.list();
+ for (String fileVideo : fileList)
+ {
+ if (fileVideo.endsWith("mp4"))
+ {
+ Clip clip = new Clip();
+ clip.path = new File(fileVideoRoot,fileVideo).getCanonicalPath();
+
+ fc.getInfo(clip);
+
+ clip.duration = clip.duration-fadeLen;
+ listVideos.add(clip);
+
+
+ }
+ }
+
+ Clip clipOut = new Clip ();
+ clipOut.path = new File(fileOut).getCanonicalPath();
+
+ fc.concatAndTrimFilesMP4Stream(listVideos, clipOut, false, false, new ShellUtils.ShellCallback() {
+
+ @Override
+ public void shellOut(String shellLine) {
+
+ System.out.println("fc>" + shellLine);
+ }
+
+ @Override
+ public void processComplete(int exitValue) {
+
+ if (exitValue < 0)
+ System.err.println("concat non-zero exit: " + exitValue);
+ }
+ });
+
+
+
+ }
}
diff --git a/src/org/ffmpeg/android/test/CrossfadeTest.java b/src/org/ffmpeg/android/test/CrossfadeTest.java
new file mode 100644
index 0000000..5b11505
--- /dev/null
+++ b/src/org/ffmpeg/android/test/CrossfadeTest.java
@@ -0,0 +1,204 @@
+package org.ffmpeg.android.test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Locale;
+
+import net.sourceforge.sox.CrossfadeCat;
+import net.sourceforge.sox.SoxController;
+
+import org.ffmpeg.android.Clip;
+import org.ffmpeg.android.FfmpegController;
+import org.ffmpeg.android.ShellUtils;
+
+public class CrossfadeTest {
+
+
+ public static void test (String videoRoot, String fileTmpPath, String clipOutPath, double fadeLen) throws Exception
+ {
+ File fileTmp = new File(fileTmpPath);
+ File fileAppRoot = new File("");
+ File fileVideoRoot = new File(videoRoot);
+
+ String fadeType = "l";
+ int sampleRate = 22050;
+ int channels = 1;
+
+ FfmpegController ffmpegc = new FfmpegController (null, fileTmp);
+
+ Clip clipOut = new Clip();
+ clipOut.path = clipOutPath;
+ clipOut.audioCodec="aac";
+ clipOut.audioBitrate=56;
+
+
+ ArrayList listVideos = new ArrayList();
+
+ String[] fileList = fileVideoRoot.list();
+ for (String fileVideo : fileList)
+ {
+ if (fileVideo.endsWith("mp4"))
+ {
+ Clip clip = new Clip();
+ clip.path = new File(fileVideoRoot,fileVideo).getCanonicalPath();
+ //clip.startTime = "00:00:03";
+ //clip.duration = "00:00:02";
+
+ ffmpegc.getInfo(clip);
+
+ //System.out.println("clip " + fileVideo + " duration=" + clip.duration);
+
+ listVideos.add(clip);
+
+ }
+ }
+
+ //now add 1 second cross fade to each audio file and cat them together
+ SoxController sxCon = new SoxController(null, fileAppRoot, new ShellUtils.ShellCallback() {
+
+ @Override
+ public void shellOut(String shellLine) {
+
+ // System.out.println("sxCon> " + shellLine);
+
+ }
+
+ @Override
+ public void processComplete(int exitValue) {
+
+
+ if (exitValue != 0)
+ {
+ System.err.println("sxCon> EXIT=" + exitValue);
+
+ RuntimeException re = new RuntimeException("non-zero exit: " + exitValue);
+ re.printStackTrace();
+ throw re;
+ }
+
+ }
+ });
+
+ ArrayList alAudio = new ArrayList();
+
+ //convert each input file to a WAV so we can use Sox to process
+ int wavIdx = 0;
+
+ for (Clip mediaIn : listVideos)
+ {
+ if (new File(mediaIn.path).exists())
+ {
+
+ if (mediaIn.audioCodec == null)
+ {
+ //there is no audio track so let's generate silence
+
+
+ }
+ else
+ {
+ Clip audioOut = ffmpegc.convertToWaveAudio(mediaIn, new File(fileTmp, wavIdx+".wav").getCanonicalPath(),sampleRate,channels, new ShellUtils.ShellCallback() {
+
+ @Override
+ public void shellOut(String shellLine) {
+
+ // System.out.println("convertToWav> " + shellLine);
+
+ }
+
+ @Override
+ public void processComplete(int exitValue) {
+
+ if (exitValue != 0)
+ {
+
+ System.err.println("convertToWav> EXIT=" + exitValue);
+
+ RuntimeException re = new RuntimeException("non-zero exit: " + exitValue);
+ re.printStackTrace();
+ throw re;
+ }
+ }
+ });
+
+ alAudio.add(audioOut);
+
+ /*
+ float duration = (float) sxCon.getLength(new File(audioOut.path).getCanonicalPath());
+
+ if (mediaIn.duration == null)
+ {
+ mediaIn.duration = String.format(Locale.US, "%f", duration);
+ }*/
+ ffmpegc.getInfo(mediaIn);
+
+
+ wavIdx++;
+ }
+ }
+ else
+ {
+ throw new FileNotFoundException(mediaIn.path);
+ }
+ }
+
+ if (alAudio.size() > 0)
+ {
+ String fileOut = alAudio.get(0).path;
+
+ System.out.println("mix length=" + sxCon.getLength(fileOut));
+
+ for (int i = 1; i < alAudio.size(); i++)
+ {
+
+ File fileAdd = new File(alAudio.get(i).path);
+
+ CrossfadeCat xCat = new CrossfadeCat(sxCon, fileOut, fileAdd.getCanonicalPath(), fadeLen, fileOut);
+ xCat.start();
+
+ fileAdd.deleteOnExit();
+
+ System.out.println("mix length=" + sxCon.getLength(fileOut));
+
+ }
+
+
+ //1 second fade in and fade out, t = triangle or linear
+ //String fadeLenStr = sxCon.formatTimePeriod(fadeLen);
+
+
+
+ String fadeFileOut = sxCon.fadeAudio(fileOut, fadeType, fadeLen, sxCon.getLength(fileOut)-fadeLen, fadeLen);
+
+ //now export the final file to our requested output format mOut.mimeType = AppConstants.MimeTypes.MP4_AUDIO;
+
+ Clip mdFinalIn = new Clip();
+ mdFinalIn.path = fadeFileOut;
+
+
+ System.out.println ("final duration: " + sxCon.getLength(fadeFileOut));
+
+ Clip exportOut = ffmpegc.convertTo3GPAudio(mdFinalIn, clipOut, new ShellUtils.ShellCallback() {
+
+ @Override
+ public void shellOut(String shellLine) {
+
+ //System.out.println("convertTo3gp> " + shellLine);
+ }
+
+ @Override
+ public void processComplete(int exitValue) {
+
+ if (exitValue < 0)
+ {
+ RuntimeException re = new RuntimeException("non-zero exit: " + exitValue);
+ re.printStackTrace();
+ throw re;
+ }
+ }
+ });
+ }
+ }
+
+}
diff --git a/src/org/ffmpeg/android/test/FilterTest.java b/src/org/ffmpeg/android/test/FilterTest.java
index dee1072..93b7711 100644
--- a/src/org/ffmpeg/android/test/FilterTest.java
+++ b/src/org/ffmpeg/android/test/FilterTest.java
@@ -1,6 +1,7 @@
package org.ffmpeg.android.test;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import org.ffmpeg.android.filters.CropVideoFilter;
@@ -16,24 +17,27 @@
public class FilterTest {
- public void test (Context context)
+ public static void test (String title, String textColor, File fileFont, String boxColor, String opacity) throws Exception
{
ArrayList listFilters = new ArrayList();
+ File fileDir = new File("tmp");
+ fileDir.mkdir();
+
int height = 480;
int width = 720;
int lowerThird = height / 3;
- DrawBoxVideoFilter vf = new DrawBoxVideoFilter(0,height-lowerThird,width,lowerThird,100,"blue",context);
+ DrawBoxVideoFilter vf = new DrawBoxVideoFilter(0,height-lowerThird,width,lowerThird,100,"blue",fileDir);
DrawTextVideoFilter vfTitle =
- new DrawTextVideoFilter("Rikshaw Rock and Roll",
+ new DrawTextVideoFilter(title,
DrawTextVideoFilter.X_CENTERED,DrawTextVideoFilter.Y_CENTERED,
- "green",
+ textColor,
38,
- new File("/system/fonts/DroidSerif-Regular.ttf"),
+ fileFont,
true,
- "yellow",
- "0.5");
+ boxColor,
+ opacity);
float fps = 29.97f;
int fadeTime = (int)(fps*3);
@@ -56,5 +60,8 @@ public void test (Context context)
listFilters.add(vfFadeIn);
listFilters.add(vfFadeOut);
+
+
+ fileDir.deleteOnExit();
}
}
diff --git a/src/org/ffmpeg/android/test/MixTest.java b/src/org/ffmpeg/android/test/MixTest.java
new file mode 100644
index 0000000..4472471
--- /dev/null
+++ b/src/org/ffmpeg/android/test/MixTest.java
@@ -0,0 +1,41 @@
+package org.ffmpeg.android.test;
+
+import java.io.File;
+
+import org.ffmpeg.android.Clip;
+import org.ffmpeg.android.FfmpegController;
+import org.ffmpeg.android.ShellUtils;
+
+public class MixTest {
+
+ public static void test (String fileTmpPath, String videoClipPath, String audioClipPath, Clip clipOut) throws Exception
+ {
+ File fileTmp = new File(fileTmpPath);
+ File fileAppRoot = new File("");
+
+ FfmpegController fc = new FfmpegController(null, fileTmp);
+
+ Clip clipVideo = new Clip(videoClipPath);
+ //fc.getInfo(clipVideo);
+
+ Clip clipAudio = new Clip(audioClipPath);
+ //fc.getInfo(clipAudio);
+
+ fc.combineAudioAndVideo(clipVideo, clipAudio, clipOut, new ShellUtils.ShellCallback() {
+
+ @Override
+ public void shellOut(String shellLine) {
+ // System.out.println("MIX> " + shellLine);
+ }
+
+ @Override
+ public void processComplete(int exitValue) {
+
+ if (exitValue != 0)
+ System.err.println("concat non-zero exit: " + exitValue);
+ }
+ });
+
+ }
+
+}
diff --git a/src/org/ffmpeg/android/test/Tests.java b/src/org/ffmpeg/android/test/Tests.java
new file mode 100644
index 0000000..a714fcf
--- /dev/null
+++ b/src/org/ffmpeg/android/test/Tests.java
@@ -0,0 +1,81 @@
+package org.ffmpeg.android.test;
+
+import java.io.File;
+
+import org.ffmpeg.android.Clip;
+
+public class Tests {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) throws Exception {
+
+
+
+ String[] testpaths = {
+ // "/home/n8fr8/Desktop/smcampmovie",
+ // "/home/n8fr8/Desktop/smcampmovie2",
+ "/home/n8fr8/Desktop/sm3"
+
+ };
+
+ int idx = -1;
+
+ double fadeLen = 1;
+
+ for (String testpath : testpaths)
+ {
+ idx++;
+
+ System.out.println ("************************************");
+ System.out.println ("CONCAT TEST: " + testpath);
+
+ File fileVideoOutput = new File("/tmp/test" + idx + ".mp4");
+ fileVideoOutput.delete();
+
+ ConcatTest.test(testpath, "/tmp", fileVideoOutput.getCanonicalPath(), fadeLen);
+
+ if (!fileVideoOutput.exists())
+ {
+ System.out.println("FAIL!! > output file did not get created: " + fileVideoOutput.getCanonicalPath());
+ continue;
+ }
+ else
+ System.out.println("SUCCESS!! > " + fileVideoOutput.getCanonicalPath());
+
+ System.out.println ("************************************");
+ System.out.println ("CROSSFADE TEST: " + testpath);
+
+ File fileAudioOutput = new File("/tmp/test" + idx + ".3gp");
+ fileAudioOutput.delete();
+ CrossfadeTest.test(testpath, "/tmp", fileAudioOutput.getCanonicalPath(),fadeLen);
+ if (!fileAudioOutput.exists())
+ {
+ System.out.println("FAIL!! > output file did not get created: " + fileAudioOutput.getCanonicalPath());
+ continue;
+ }
+ else
+ System.out.println("SUCCESS!! > " + fileAudioOutput.getCanonicalPath());
+
+ System.out.println ("************************************");
+ System.out.println ("MIX TEST: " + testpath);
+
+ File fileMix = new File("/tmp/test" + idx + "mix.mp4");
+ fileMix.delete();
+ Clip clipMixOut = new Clip(fileMix.getCanonicalPath());
+ MixTest.test("/tmp", fileVideoOutput.getCanonicalPath(), fileAudioOutput.getCanonicalPath(), clipMixOut);
+ if (!fileMix.exists())
+ System.out.println("FAIL!! > output file did not get created: " + fileMix.getCanonicalPath());
+ else
+ System.out.println("SUCCESS!! > " + fileMix.getCanonicalPath());
+
+
+ }
+
+ System.out.println("**********************");
+ System.out.println("*******FIN**********");
+
+ }
+
+}