-
Notifications
You must be signed in to change notification settings - Fork 826
Expand file tree
/
Copy pathFFmpeg.java
More file actions
152 lines (129 loc) · 5.41 KB
/
FFmpeg.java
File metadata and controls
152 lines (129 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.github.hiteshsondhi88.libffmpeg;
import android.content.Context;
import android.text.TextUtils;
import java.lang.reflect.Array;
import java.util.Map;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegCommandAlreadyRunningException;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;
@SuppressWarnings("unused")
public class FFmpeg implements FFmpegInterface {
private final FFmpegContextProvider 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(FFmpegContextProvider contextProvider) {
this.context = contextProvider;
Log.setDEBUG(Util.isDebug(this.context.provide()));
}
public static FFmpeg getInstance(FFmpegContextProvider contextProvider) {
if (instance == null) {
instance = new FFmpeg(contextProvider);
}
return instance;
}
@Deprecated
public static FFmpeg getInstance(final Context context) {
if (instance == null) {
instance = new FFmpeg(new FFmpegContextProvider() {
@Override
public Context provide() {
return 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 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.provide(), environvenmentVars) };
String[] command = concatenate(ffmpegBinary, cmd);
ffmpegExecuteAsyncTask = new FFmpegExecuteAsyncTask(command , timeout, ffmpegExecuteResponseHandler);
ffmpegExecuteAsyncTask.execute();
} else {
throw new IllegalArgumentException("shell command cannot be empty");
}
}
private static <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.provide()), "-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.provide().getString(R.string.shipped_ffmpeg_version);
}
@Override
public boolean isFFmpegCommandRunning() {
if (ffmpegExecuteAsyncTask == null)
return false;
else
return !ffmpegExecuteAsyncTask.isProcessCompleted();
}
@Override
public boolean killRunningProcesses() {
boolean status = Util.killAsync(ffmpegLoadLibraryAsyncTask) || Util.killAsync(ffmpegExecuteAsyncTask);
ffmpegExecuteAsyncTask = null;
return status;
}
@Override
public void setTimeout(long timeout) {
if (timeout >= MINIMUM_TIMEOUT) {
this.timeout = timeout;
}
}
@Override
public FFmpegObserver whenFFmpegIsReady(Runnable onReady, int timeout) {
return Util.observeOnce(new Util.ObservePredicate() {
@Override
public Boolean isReadyToProceed() {
return !isFFmpegCommandRunning();
}
}, onReady, timeout);
}
}