securesmartcam / app / src / main / java / org / witness / obscuracam / video / FFMPEGWrapper.java @ 41590feb
History | View | Annotate | Download (7.56 KB)
1 |
package org.witness.obscuracam.video; |
---|---|
2 |
|
3 |
import android.content.Context; |
4 |
import android.util.Log; |
5 |
|
6 |
import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler; |
7 |
import com.github.hiteshsondhi88.libffmpeg.FFmpeg; |
8 |
import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler; |
9 |
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegCommandAlreadyRunningException; |
10 |
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException; |
11 |
|
12 |
import java.io.File; |
13 |
import java.io.FileNotFoundException; |
14 |
import java.io.FileWriter; |
15 |
import java.io.IOException; |
16 |
import java.io.PrintWriter; |
17 |
import java.text.DecimalFormat; |
18 |
import java.util.ArrayList; |
19 |
|
20 |
public class FFMPEGWrapper { |
21 |
|
22 |
Context context;
|
23 |
FFmpeg ffmpeg; |
24 |
|
25 |
public FFMPEGWrapper(Context _context) throws FileNotFoundException, IOException { |
26 |
context = _context; |
27 |
|
28 |
ffmpeg = FFmpeg.getInstance(context); |
29 |
|
30 |
try {
|
31 |
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
|
32 |
|
33 |
@Override
|
34 |
public void onStart() {} |
35 |
|
36 |
@Override
|
37 |
public void onFailure() { |
38 |
Log.e(getClass().getName(),"Failed to install binary");
|
39 |
} |
40 |
|
41 |
@Override
|
42 |
public void onSuccess() { |
43 |
Log.i(getClass().getName(),"SUCCESS: installed binary");
|
44 |
} |
45 |
|
46 |
@Override
|
47 |
public void onFinish() {} |
48 |
}); |
49 |
} catch (FFmpegNotSupportedException e) {
|
50 |
// Handle if FFmpeg is not supported by device
|
51 |
|
52 |
Log.e(getClass().getName(),"Failed to install binary",e);
|
53 |
} |
54 |
} |
55 |
|
56 |
|
57 |
|
58 |
public void processVideo( |
59 |
ArrayList<RegionTrail> regionTrails, File inputFile, File outputFile, int frameRate, float startTime, float duration, |
60 |
boolean compressVideo, int obscureVideoAmount, int obscureAudioAmount, ExecuteBinaryResponseHandler listener) throws Exception { |
61 |
|
62 |
DecimalFormat df = new DecimalFormat("####0.00"); |
63 |
|
64 |
ArrayList<String> alCmds = new ArrayList<>(); |
65 |
|
66 |
alCmds.add("-y");
|
67 |
alCmds.add("-i");
|
68 |
alCmds.add(inputFile.getCanonicalPath()); |
69 |
|
70 |
if (duration > 0) |
71 |
{ |
72 |
alCmds.add("-ss");
|
73 |
alCmds.add(df.format(startTime)); |
74 |
|
75 |
alCmds.add("-t");
|
76 |
alCmds.add(df.format(duration)); |
77 |
} |
78 |
|
79 |
if (frameRate > 0) |
80 |
{ |
81 |
alCmds.add("-r");
|
82 |
alCmds.add(frameRate+"");
|
83 |
} |
84 |
|
85 |
if (compressVideo) {
|
86 |
alCmds.add("-b:v");
|
87 |
alCmds.add("500K");
|
88 |
|
89 |
} |
90 |
|
91 |
if (obscureAudioAmount > 0) { |
92 |
alCmds.add("-filter_complex");
|
93 |
alCmds.add("vibrato=f=" + obscureAudioAmount);
|
94 |
|
95 |
alCmds.add("-b:a");
|
96 |
alCmds.add("4K");
|
97 |
|
98 |
alCmds.add("-ab");
|
99 |
alCmds.add("4K");
|
100 |
|
101 |
alCmds.add("-ar");
|
102 |
alCmds.add("11025");
|
103 |
|
104 |
alCmds.add("-ac");
|
105 |
alCmds.add("1");
|
106 |
} |
107 |
|
108 |
StringBuffer filters = new StringBuffer(); |
109 |
|
110 |
if (obscureVideoAmount > 0) { |
111 |
int pixelScale = obscureVideoAmount;
|
112 |
|
113 |
//scale down and up to fully pixelize
|
114 |
filters.append("scale=iw/" + pixelScale + ":ih/" + pixelScale + ",scale=" + pixelScale + "*iw:" + pixelScale + "*ih:flags=neighbor,"); |
115 |
} |
116 |
|
117 |
|
118 |
if (regionTrails.size() == 0) { |
119 |
//do what?
|
120 |
} |
121 |
else {
|
122 |
for (RegionTrail trail : regionTrails) {
|
123 |
|
124 |
if (trail.isDoTweening() && trail.getRegionCount() > 1) { |
125 |
int timeInc = 100; |
126 |
|
127 |
for (int i = 0; i < ((int)duration); i = i + timeInc) { |
128 |
ObscureRegion or = trail.getCurrentRegion(i, trail.isDoTweening()); |
129 |
if (or != null) { |
130 |
|
131 |
int x = (int) or.getBounds().left; |
132 |
int y = (int) or.getBounds().top; |
133 |
int height = (int) or.getBounds().height(); |
134 |
int width = (int) or.getBounds().width(); |
135 |
String color = "black"; |
136 |
float timeStart = ((float) or.timeStamp) / 1000f; |
137 |
float timeStop = (((float) or.timeStamp) + 100) / 1000f; |
138 |
|
139 |
float timeEnd = duration / 1000f; |
140 |
timeStop = Math.max(timeStop, timeEnd);
|
141 |
|
142 |
filters.append("drawbox=x=" + x + ":y=" + y |
143 |
+ ":w=" + width + ":h=" + height |
144 |
+ ":color=" + color
|
145 |
+ ":t=max"
|
146 |
+ ":enable='between(t,"
|
147 |
+ df.format(timeStart) + "," + df.format(timeStop) + ")',"); |
148 |
} |
149 |
} |
150 |
|
151 |
} else {
|
152 |
|
153 |
for (Integer orKey : trail.getRegionKeys()) { |
154 |
ObscureRegion or = trail.getRegion(orKey); |
155 |
|
156 |
int x = (int) or.getBounds().left; |
157 |
int y = (int) or.getBounds().top; |
158 |
int height = (int) or.getBounds().height(); |
159 |
int width = (int) or.getBounds().width(); |
160 |
String color = "black"; |
161 |
|
162 |
filters.append("drawbox=x=" + x + ":y=" + y |
163 |
+ ":w=" + width + ":h=" + height |
164 |
+ ":color=" + color
|
165 |
+ ":t=max");
|
166 |
|
167 |
} |
168 |
|
169 |
|
170 |
} |
171 |
} |
172 |
} |
173 |
|
174 |
|
175 |
if (filters.toString().length() > 0) { |
176 |
Log.d(getClass().getName(), "filters: " + filters.toString());
|
177 |
|
178 |
alCmds.add("-vf");
|
179 |
|
180 |
String filterCmd = filters.toString();
|
181 |
|
182 |
alCmds.add(filterCmd.substring(0, filterCmd.length() - 1)); |
183 |
} |
184 |
|
185 |
alCmds.add(outputFile.getCanonicalPath()); |
186 |
|
187 |
String[] cmd = alCmds.toArray(new String[alCmds.size()]); |
188 |
|
189 |
try {
|
190 |
|
191 |
|
192 |
// to execute "ffmpeg -version" command you just need to pass "-version"
|
193 |
ffmpeg.execute(cmd,listener); |
194 |
} catch (FFmpegCommandAlreadyRunningException e) {
|
195 |
// Handle if FFmpeg is already running
|
196 |
Log.e(getClass().getName(),"already running");
|
197 |
} |
198 |
} |
199 |
|
200 |
private void writeRedactData(File redactSettingsFile, ArrayList<RegionTrail> regionTrails, float widthMod, float heightMod, int mDuration) throws IOException { |
201 |
// Write out the finger data
|
202 |
|
203 |
FileWriter redactSettingsFileWriter = new FileWriter(redactSettingsFile); |
204 |
PrintWriter redactSettingsPrintWriter = new PrintWriter(redactSettingsFileWriter); |
205 |
ObscureRegion or = null, lastOr = null; |
206 |
String orData = ""; |
207 |
|
208 |
for (RegionTrail trail : regionTrails)
|
209 |
{ |
210 |
|
211 |
if (trail.isDoTweening())
|
212 |
{ |
213 |
int timeInc = 100; |
214 |
|
215 |
for (int i = 0; i < mDuration; i = i+timeInc) |
216 |
{ |
217 |
or = trail.getCurrentRegion(i, trail.isDoTweening()); |
218 |
if (or != null) |
219 |
{ |
220 |
orData = or.getStringData(widthMod, heightMod,i,timeInc, trail.getObscureMode()); |
221 |
redactSettingsPrintWriter.println(orData); |
222 |
} |
223 |
} |
224 |
|
225 |
} |
226 |
else
|
227 |
{ |
228 |
|
229 |
for (Integer orKey : trail.getRegionKeys()) |
230 |
{ |
231 |
or = trail.getRegion(orKey); |
232 |
|
233 |
if (lastOr != null) |
234 |
{ |
235 |
|
236 |
orData = lastOr.getStringData(widthMod, heightMod,or.timeStamp,or.timeStamp-lastOr.timeStamp, trail.getObscureMode()); |
237 |
} |
238 |
|
239 |
redactSettingsPrintWriter.println(orData); |
240 |
|
241 |
lastOr = or; |
242 |
} |
243 |
|
244 |
if (or != null) |
245 |
{ |
246 |
orData = lastOr.getStringData(widthMod, heightMod,or.timeStamp,or.timeStamp-lastOr.timeStamp, trail.getObscureMode()); |
247 |
redactSettingsPrintWriter.println(orData); |
248 |
} |
249 |
} |
250 |
} |
251 |
|
252 |
redactSettingsPrintWriter.flush(); |
253 |
|
254 |
redactSettingsPrintWriter.close(); |
255 |
|
256 |
|
257 |
} |
258 |
|
259 |
public FFmpeg getFFMPEG ()
|
260 |
{ |
261 |
return ffmpeg;
|
262 |
} |
263 |
|
264 |
} |
265 |
|
266 |
|