();
1375 |
1376 | cmd.add(mFfmpegBin);
1377 | cmd.add("-y");
1378 | cmd.add("-i");
1379 |
1380 | cmd.add(new File(in.path).getCanonicalPath());
1381 |
1382 | InfoParser ip = new InfoParser(in);
1383 | execFFMPEG(cmd,ip, null);
1384 |
1385 | try{Thread.sleep(200);}
1386 | catch (Exception e){}
1387 |
1388 |
1389 | return in;
1390 |
1391 | }
1392 |
1393 | private class InfoParser implements ShellCallback {
1394 |
1395 | private Clip mMedia;
1396 | private int retValue;
1397 |
1398 | public InfoParser (Clip media)
1399 | {
1400 | mMedia = media;
1401 | }
1402 |
1403 | @Override
1404 | public void shellOut(String shellLine) {
1405 | if (shellLine.contains("Duration:"))
1406 | {
1407 |
1408 | // Duration: 00:01:01.75, start: 0.000000, bitrate: 8184 kb/s
1409 |
1410 | String[] timecode = shellLine.split(",")[0].split(":");
1411 |
1412 |
1413 | double duration = 0;
1414 |
1415 | duration = Double.parseDouble(timecode[1].trim())*60*60; //hours
1416 | duration += Double.parseDouble(timecode[2].trim())*60; //minutes
1417 | duration += Double.parseDouble(timecode[3].trim()); //seconds
1418 |
1419 | mMedia.duration = duration;
1420 |
1421 |
1422 | }
1423 |
1424 | // Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 16939 kb/s, 30.02 fps, 30 tbr, 90k tbn, 180k tbc
1425 | else if (shellLine.contains(": Video:"))
1426 | {
1427 | String[] line = shellLine.split(":");
1428 | String[] videoInfo = line[3].split(",");
1429 |
1430 | mMedia.videoCodec = videoInfo[0];
1431 | }
1432 |
1433 | //Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, s16, 121 kb/s
1434 | else if (shellLine.contains(": Audio:"))
1435 | {
1436 | String[] line = shellLine.split(":");
1437 | String[] audioInfo = line[3].split(",");
1438 |
1439 | mMedia.audioCodec = audioInfo[0];
1440 |
1441 | }
1442 |
1443 |
1444 | //
1445 | //Stream #0.0(und): Video: h264 (Baseline), yuv420p, 1280x720, 8052 kb/s, 29.97 fps, 90k tbr, 90k tbn, 180k tbc
1446 | //Stream #0.1(und): Audio: mp2, 22050 Hz, 2 channels, s16, 127 kb/s
1447 |
1448 | }
1449 |
1450 | @Override
1451 | public void processComplete(int exitValue) {
1452 | retValue = exitValue;
1453 |
1454 | }
1455 | }
1456 |
1457 | private class StreamGobbler extends Thread
1458 | {
1459 | InputStream is;
1460 | String type;
1461 | ShellCallback sc;
1462 |
1463 | StreamGobbler(InputStream is, String type, ShellCallback sc)
1464 | {
1465 | this.is = is;
1466 | this.type = type;
1467 | this.sc = sc;
1468 | }
1469 |
1470 | public void run()
1471 | {
1472 | try
1473 | {
1474 | InputStreamReader isr = new InputStreamReader(is);
1475 | BufferedReader br = new BufferedReader(isr);
1476 | String line=null;
1477 | while ( (line = br.readLine()) != null)
1478 | if (sc != null)
1479 | sc.shellOut(line);
1480 |
1481 | } catch (IOException ioe)
1482 | {
1483 | // Log.e(TAG,"error reading shell slog",ioe);
1484 | ioe.printStackTrace();
1485 | }
1486 | }
1487 | }
1488 |
1489 | public static Bitmap getVideoFrame(String videoPath,long frameTime) throws Exception {
1490 | MediaMetadataRetriever retriever = new MediaMetadataRetriever();
1491 |
1492 | try {
1493 | retriever.setDataSource(videoPath);
1494 | return retriever.getFrameAtTime(frameTime, MediaMetadataRetriever.OPTION_CLOSEST);
1495 |
1496 | } finally {
1497 | try {
1498 | retriever.release();
1499 | } catch (RuntimeException ex) {
1500 | }
1501 | }
1502 | }
1503 | }
1504 |
1505 | /*
1506 | * Main options:
1507 | -L show license
1508 | -h show help
1509 | -? show help
1510 | -help show help
1511 | --help show help
1512 | -version show version
1513 | -formats show available formats
1514 | -codecs show available codecs
1515 | -bsfs show available bit stream filters
1516 | -protocols show available protocols
1517 | -filters show available filters
1518 | -pix_fmts show available pixel formats
1519 | -sample_fmts show available audio sample formats
1520 | -loglevel loglevel set libav* logging level
1521 | -v loglevel set libav* logging level
1522 | -debug flags set debug flags
1523 | -report generate a report
1524 | -f fmt force format
1525 | -i filename input file name
1526 | -y overwrite output files
1527 | -n do not overwrite output files
1528 | -c codec codec name
1529 | -codec codec codec name
1530 | -pre preset preset name
1531 | -t duration record or transcode "duration" seconds of audio/video
1532 | -fs limit_size set the limit file size in bytes
1533 | -ss time_off set the start time offset
1534 | -itsoffset time_off set the input ts offset
1535 | -itsscale scale set the input ts scale
1536 | -timestamp time set the recording timestamp ('now' to set the current time)
1537 | -metadata string=string add metadata
1538 | -dframes number set the number of data frames to record
1539 | -timelimit limit set max runtime in seconds
1540 | -target type specify target file type ("vcd", "svcd", "dvd", "dv", "dv50", "pal-vcd", "ntsc-svcd", ...)
1541 | -xerror exit on error
1542 | -frames number set the number of frames to record
1543 | -tag fourcc/tag force codec tag/fourcc
1544 | -filter filter_list set stream filterchain
1545 | -stats print progress report during encoding
1546 | -attach filename add an attachment to the output file
1547 | -dump_attachment filename extract an attachment into a file
1548 | -bsf bitstream_filters A comma-separated list of bitstream filters
1549 | -dcodec codec force data codec ('copy' to copy stream)
1550 |
1551 | Advanced options:
1552 | -map file.stream[:syncfile.syncstream] set input stream mapping
1553 | -map_channel file.stream.channel[:syncfile.syncstream] map an audio channel from one stream to another
1554 | -map_meta_data outfile[,metadata]:infile[,metadata] DEPRECATED set meta data information of outfile from infile
1555 | -map_metadata outfile[,metadata]:infile[,metadata] set metadata information of outfile from infile
1556 | -map_chapters input_file_index set chapters mapping
1557 | -benchmark add timings for benchmarking
1558 | -dump dump each input packet
1559 | -hex when dumping packets, also dump the payload
1560 | -re read input at native frame rate
1561 | -loop_input deprecated, use -loop
1562 | -loop_output deprecated, use -loop
1563 | -vsync video sync method
1564 | -async audio sync method
1565 | -adrift_threshold threshold audio drift threshold
1566 | -copyts copy timestamps
1567 | -copytb source copy input stream time base when stream copying
1568 | -shortest finish encoding within shortest input
1569 | -dts_delta_threshold threshold timestamp discontinuity delta threshold
1570 | -copyinkf copy initial non-keyframes
1571 | -q q use fixed quality scale (VBR)
1572 | -qscale q use fixed quality scale (VBR)
1573 | -streamid streamIndex:value set the value of an outfile streamid
1574 | -muxdelay seconds set the maximum demux-decode delay
1575 | -muxpreload seconds set the initial demux-decode delay
1576 | -fpre filename set options from indicated preset file
1577 |
1578 | Video options:
1579 | -vframes number set the number of video frames to record
1580 | -r rate set frame rate (Hz value, fraction or abbreviation)
1581 | -s size set frame size (WxH or abbreviation)
1582 | -aspect aspect set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)
1583 | -bits_per_raw_sample number set the number of bits per raw sample
1584 | -croptop size Removed, use the crop filter instead
1585 | -cropbottom size Removed, use the crop filter instead
1586 | -cropleft size Removed, use the crop filter instead
1587 | -cropright size Removed, use the crop filter instead
1588 | -padtop size Removed, use the pad filter instead
1589 | -padbottom size Removed, use the pad filter instead
1590 | -padleft size Removed, use the pad filter instead
1591 | -padright size Removed, use the pad filter instead
1592 | -padcolor color Removed, use the pad filter instead
1593 | -vn disable video
1594 | -vcodec codec force video codec ('copy' to copy stream)
1595 | -sameq use same quantizer as source (implies VBR)
1596 | -same_quant use same quantizer as source (implies VBR)
1597 | -pass n select the pass number (1 or 2)
1598 | -passlogfile prefix select two pass log file name prefix
1599 | -vf filter list video filters
1600 | -b bitrate video bitrate (please use -b:v)
1601 | -dn disable data
1602 |
1603 | Advanced Video options:
1604 | -pix_fmt format set pixel format
1605 | -intra use only intra frames
1606 | -vdt n discard threshold
1607 | -rc_override override rate control override for specific intervals
1608 | -deinterlace deinterlace pictures
1609 | -psnr calculate PSNR of compressed frames
1610 | -vstats dump video coding statistics to file
1611 | -vstats_file file dump video coding statistics to file
1612 | -intra_matrix matrix specify intra matrix coeffs
1613 | -inter_matrix matrix specify inter matrix coeffs
1614 | -top top=1/bottom=0/auto=-1 field first
1615 | -dc precision intra_dc_precision
1616 | -vtag fourcc/tag force video tag/fourcc
1617 | -qphist show QP histogram
1618 | -force_fps force the selected framerate, disable the best supported framerate selection
1619 | -force_key_frames timestamps force key frames at specified timestamps
1620 | -vbsf video bitstream_filters deprecated
1621 | -vpre preset set the video options to the indicated preset
1622 |
1623 | Audio options:
1624 | -aframes number set the number of audio frames to record
1625 | -aq quality set audio quality (codec-specific)
1626 | -ar rate set audio sampling rate (in Hz)
1627 | -ac channels set number of audio channels
1628 | -an disable audio
1629 | -acodec codec force audio codec ('copy' to copy stream)
1630 | -vol volume change audio volume (256=normal)
1631 | -rmvol volume rematrix volume (as factor)
1632 |
1633 | */
1634 |
1635 | /*
1636 | * //./ffmpeg -y -i test.mp4 -vframes 999999 -vf 'redact=blurbox.txt [out] [d], [d]nullsink' -acodec copy outputa.mp4
1637 |
1638 | //ffmpeg -v 10 -y -i /sdcard/org.witness.sscvideoproto/videocapture1042744151.mp4 -vcodec libx264
1639 | //-b 3000k -s 720x480 -r 30 -acodec copy -f mp4 -vf 'redact=/data/data/org.witness.sscvideoproto/redact_unsort.txt'
1640 | ///sdcard/org.witness.sscvideoproto/new.mp4
1641 |
1642 | //"-vf" , "redact=" + Environment.getExternalStorageDirectory().getPath() + "/" + PACKAGENAME + "/redact_unsort.txt",
1643 |
1644 |
1645 | // Need to make sure this will create a legitimate mp4 file
1646 | //"-acodec", "ac3", "-ac", "1", "-ar", "16000", "-ab", "32k",
1647 |
1648 |
1649 | String[] ffmpegCommand = {"/data/data/"+PACKAGENAME+"/ffmpeg", "-v", "10", "-y", "-i", recordingFile.getPath(),
1650 | "-vcodec", "libx264", "-b", "3000k", "-vpre", "baseline", "-s", "720x480", "-r", "30",
1651 | //"-vf", "drawbox=10:20:200:60:red@0.5",
1652 | "-vf" , "\"movie="+ overlayImage.getPath() +" [logo];[in][logo] overlay=0:0 [out]\"",
1653 | "-acodec", "copy",
1654 | "-f", "mp4", savePath.getPath()+"/output.mp4"};
1655 |
1656 |
1657 |
1658 |
1659 | //ffmpeg -i source-video.avi -s 480x320 -vcodec mpeg4 -acodec aac -ac 1 -ar 16000 -r 13 -ab 32000 -aspect 3:2 output-video.mp4/
1660 |
1661 |
1662 | */
1663 |
1664 |
1665 | /* concat doesn't seem to work
1666 | cmd.add("-i");
1667 |
1668 | StringBuffer concat = new StringBuffer();
1669 |
1670 | for (int i = 0; i < videos.size(); i++)
1671 | {
1672 | if (i > 0)
1673 | concat.append("|");
1674 |
1675 | concat.append(out.path + '.' + i + ".wav");
1676 |
1677 | }
1678 |
1679 | cmd.add("concat:\"" + concat.toString() + "\"");
1680 | */
1681 |
1682 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/ShellUtils.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
2 | /* See LICENSE for licensing information */
3 | package org.ffmpeg.android;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.io.InputStreamReader;
9 | import java.io.OutputStreamWriter;
10 | import java.util.StringTokenizer;
11 |
12 |
13 | import android.util.Log;
14 |
15 | public class ShellUtils {
16 |
17 | //various console cmds
18 | public final static String SHELL_CMD_CHMOD = "chmod";
19 | public final static String SHELL_CMD_KILL = "kill -9";
20 | public final static String SHELL_CMD_RM = "rm";
21 | public final static String SHELL_CMD_PS = "ps";
22 | public final static String SHELL_CMD_PIDOF = "pidof";
23 |
24 | public final static String CHMOD_EXE_VALUE = "700";
25 |
26 | public static boolean isRootPossible()
27 | {
28 |
29 | StringBuilder log = new StringBuilder();
30 |
31 | try {
32 |
33 | // Check if Superuser.apk exists
34 | File fileSU = new File("/system/app/Superuser.apk");
35 | if (fileSU.exists())
36 | return true;
37 |
38 | fileSU = new File("/system/bin/su");
39 | if (fileSU.exists())
40 | return true;
41 |
42 | //Check for 'su' binary
43 | String[] cmd = {"which su"};
44 | int exitCode = ShellUtils.doShellCommand(null,cmd, new ShellCallback ()
45 | {
46 |
47 | @Override
48 | public void shellOut(String msg) {
49 |
50 | //System.out.print(msg);
51 |
52 | }
53 |
54 | @Override
55 | public void processComplete(int exitValue) {
56 | // TODO Auto-generated method stub
57 |
58 | }
59 |
60 | }, false, true).exitValue();
61 |
62 | if (exitCode == 0) {
63 | logMessage("Can acquire root permissions");
64 | return true;
65 |
66 | }
67 |
68 | } catch (IOException e) {
69 | //this means that there is no root to be had (normally) so we won't log anything
70 | logException("Error checking for root access",e);
71 |
72 | }
73 | catch (Exception e) {
74 | logException("Error checking for root access",e);
75 | //this means that there is no root to be had (normally)
76 | }
77 |
78 | logMessage("Could not acquire root permissions");
79 |
80 |
81 | return false;
82 | }
83 |
84 |
85 | public static int findProcessId(String command)
86 | {
87 | int procId = -1;
88 |
89 | try
90 | {
91 | procId = findProcessIdWithPidOf(command);
92 |
93 | if (procId == -1)
94 | procId = findProcessIdWithPS(command);
95 | }
96 | catch (Exception e)
97 | {
98 | try
99 | {
100 | procId = findProcessIdWithPS(command);
101 | }
102 | catch (Exception e2)
103 | {
104 | logException("Unable to get proc id for: " + command,e2);
105 | }
106 | }
107 |
108 | return procId;
109 | }
110 |
111 | //use 'pidof' command
112 | public static int findProcessIdWithPidOf(String command) throws Exception
113 | {
114 |
115 | int procId = -1;
116 |
117 | Runtime r = Runtime.getRuntime();
118 |
119 | Process procPs = null;
120 |
121 | String baseName = new File(command).getName();
122 | //fix contributed my mikos on 2010.12.10
123 | procPs = r.exec(new String[] {SHELL_CMD_PIDOF, baseName});
124 | //procPs = r.exec(SHELL_CMD_PIDOF);
125 |
126 | BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream()));
127 | String line = null;
128 |
129 | while ((line = reader.readLine())!=null)
130 | {
131 |
132 | try
133 | {
134 | //this line should just be the process id
135 | procId = Integer.parseInt(line.trim());
136 | break;
137 | }
138 | catch (NumberFormatException e)
139 | {
140 | logException("unable to parse process pid: " + line,e);
141 | }
142 | }
143 |
144 |
145 | return procId;
146 |
147 | }
148 |
149 | //use 'ps' command
150 | public static int findProcessIdWithPS(String command) throws Exception
151 | {
152 |
153 | int procId = -1;
154 |
155 | Runtime r = Runtime.getRuntime();
156 |
157 | Process procPs = null;
158 |
159 | procPs = r.exec(SHELL_CMD_PS);
160 |
161 | BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream()));
162 | String line = null;
163 |
164 | while ((line = reader.readLine())!=null)
165 | {
166 | if (line.indexOf(' ' + command)!=-1)
167 | {
168 |
169 | StringTokenizer st = new StringTokenizer(line," ");
170 | st.nextToken(); //proc owner
171 |
172 | procId = Integer.parseInt(st.nextToken().trim());
173 |
174 | break;
175 | }
176 | }
177 |
178 |
179 |
180 | return procId;
181 |
182 | }
183 |
184 | public static int doShellCommand(String[] cmds, ShellCallback sc, boolean runAsRoot, boolean waitFor) throws Exception
185 | {
186 | return doShellCommand (null, cmds, sc, runAsRoot, waitFor).exitValue();
187 |
188 | }
189 |
190 | public static Process doShellCommand(Process proc, String[] cmds, ShellCallback sc, boolean runAsRoot, boolean waitFor) throws Exception
191 | {
192 |
193 |
194 | if (proc == null)
195 | {
196 | if (runAsRoot)
197 | proc = Runtime.getRuntime().exec("su");
198 | else
199 | proc = Runtime.getRuntime().exec("sh");
200 | }
201 |
202 | OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream());
203 |
204 | for (int i = 0; i < cmds.length; i++)
205 | {
206 | logMessage("executing shell cmd: " + cmds[i] + "; runAsRoot=" + runAsRoot + ";waitFor=" + waitFor);
207 |
208 | out.write(cmds[i]);
209 | out.write("\n");
210 | }
211 |
212 | out.flush();
213 | out.write("exit\n");
214 | out.flush();
215 |
216 | if (waitFor)
217 | {
218 |
219 | final char buf[] = new char[20];
220 |
221 | // Consume the "stdout"
222 | InputStreamReader reader = new InputStreamReader(proc.getInputStream());
223 | int read=0;
224 | while ((read=reader.read(buf)) != -1) {
225 | if (sc != null) sc.shellOut(new String(buf));
226 | }
227 |
228 | // Consume the "stderr"
229 | reader = new InputStreamReader(proc.getErrorStream());
230 | read=0;
231 | while ((read=reader.read(buf)) != -1) {
232 | if (sc != null) sc.shellOut(new String(buf));
233 | }
234 |
235 | proc.waitFor();
236 |
237 | }
238 |
239 | sc.processComplete(proc.exitValue());
240 |
241 | return proc;
242 |
243 | }
244 |
245 | public static void logMessage (String msg)
246 | {
247 |
248 | }
249 |
250 | public static void logException (String msg, Exception e)
251 | {
252 |
253 | }
254 |
255 | public interface ShellCallback
256 | {
257 | public void shellOut (String shellLine);
258 |
259 | public void processComplete (int exitValue);
260 | }
261 | }
262 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/CropVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | public class CropVideoFilter extends VideoFilter {
4 |
5 | private String mOutWidth;
6 | private String mOutHeight;
7 | private String mX;
8 | private String mY;
9 |
10 | public CropVideoFilter (String width, String height, String x, String y)
11 | {
12 | mOutWidth = width;
13 | mOutHeight = height;
14 | mX = x;
15 | mY = y;
16 | }
17 |
18 | @Override
19 | public String getFilterString() {
20 |
21 | StringBuffer result = new StringBuffer();
22 |
23 | result.append("crop=");
24 |
25 | if (mOutWidth != null)
26 | result.append(mOutWidth).append(":");
27 |
28 | if (mOutHeight != null)
29 | result.append(mOutHeight).append(":");
30 |
31 | if (mX != null)
32 | result.append(mX).append(":");
33 |
34 | if (mY != null)
35 | result.append(mY).append(":");
36 |
37 | result.deleteCharAt(result.length()-1); //remove the last semicolon!
38 |
39 | return result.toString();
40 | }
41 |
42 | }
43 |
44 | /*
45 | Crop the input video to out_w:out_h:x:y:keep_aspect
46 |
47 | The keep_aspect parameter is optional, if specified and set to a non-zero value will force the output display aspect ratio to be the same of the input, by changing the output sample aspect ratio.
48 |
49 | The out_w, out_h, x, y parameters are expressions containing the following constants:
50 |
51 | ‘x, y’
52 | the computed values for x and y. They are evaluated for each new frame.
53 |
54 | ‘in_w, in_h’
55 | the input width and height
56 |
57 | ‘iw, ih’
58 | same as in_w and in_h
59 |
60 | ‘out_w, out_h’
61 | the output (cropped) width and height
62 |
63 | ‘ow, oh’
64 | same as out_w and out_h
65 |
66 | ‘a’
67 | same as iw / ih
68 |
69 | ‘sar’
70 | input sample aspect ratio
71 |
72 | ‘dar’
73 | input display aspect ratio, it is the same as (iw / ih) * sar
74 |
75 | ‘hsub, vsub’
76 | horizontal and vertical chroma subsample values. For example for the pixel format "yuv422p" hsub is 2 and vsub is 1.
77 |
78 | ‘n’
79 | the number of input frame, starting from 0
80 |
81 | ‘pos’
82 | the position in the file of the input frame, NAN if unknown
83 |
84 | ‘t’
85 | timestamp expressed in seconds, NAN if the input timestamp is unknown
86 |
87 | The out_w and out_h parameters specify the expressions for the width and height of the output (cropped) video. They are evaluated just at the configuration of the filter.
88 |
89 | The default value of out_w is "in_w", and the default value of out_h is "in_h".
90 |
91 | The expression for out_w may depend on the value of out_h, and the expression for out_h may depend on out_w, but they cannot depend on x and y, as x and y are evaluated after out_w and out_h.
92 |
93 | The x and y parameters specify the expressions for the position of the top-left corner of the output (non-cropped) area. They are evaluated for each frame. If the evaluated value is not valid, it is approximated to the nearest valid value.
94 |
95 | The default value of x is "(in_w-out_w)/2", and the default value for y is "(in_h-out_h)/2", which set the cropped area at the center of the input image.
96 |
97 | The expression for x may depend on y, and the expression for y may depend on x.
98 |
99 | Follow some examples:
100 |
101 |
102 | # crop the central input area with size 100x100
103 | crop=100:100
104 |
105 | # crop the central input area with size 2/3 of the input video
106 | "crop=2/3*in_w:2/3*in_h"
107 |
108 | # crop the input video central square
109 | crop=in_h
110 |
111 | # delimit the rectangle with the top-left corner placed at position
112 | # 100:100 and the right-bottom corner corresponding to the right-bottom
113 | # corner of the input image.
114 | crop=in_w-100:in_h-100:100:100
115 |
116 | # crop 10 pixels from the left and right borders, and 20 pixels from
117 | # the top and bottom borders
118 | "crop=in_w-2*10:in_h-2*20"
119 |
120 | # keep only the bottom right quarter of the input image
121 | "crop=in_w/2:in_h/2:in_w/2:in_h/2"
122 |
123 | # crop height for getting Greek harmony
124 | "crop=in_w:1/PHI*in_w"
125 |
126 | # trembling effect
127 | "crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(n/7)"
128 |
129 | # erratic camera effect depending on timestamp
130 | "crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(t*10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(t*13)"
131 |
132 | # set x depending on the value of y
133 | "crop=in_w/2:in_h/2:y:10+10*sin(n/10)"
134 | */
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/DrawBoxVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 |
7 | import android.content.Context;
8 | import android.graphics.Bitmap;
9 | import android.graphics.Bitmap.Config;
10 | import android.graphics.Canvas;
11 | import android.graphics.Color;
12 | import android.graphics.Paint;
13 |
14 | public class DrawBoxVideoFilter extends OverlayVideoFilter {
15 |
16 | public int x;
17 | public int y;
18 | public int width;
19 | public int height;
20 | public String color;
21 |
22 | public DrawBoxVideoFilter (int x, int y, int width, int height, int alpha, String color, File tmpDir) throws Exception
23 | {
24 | this.x = x;
25 | this.y = y;
26 | this.width = width;
27 | this.height = height;
28 | this.color = color;
29 |
30 | if( alpha < 0 || alpha > 255 ) {
31 | throw new IllegalArgumentException("Alpha must be an integer betweeen 0 and 255");
32 | }
33 | Paint paint = new Paint();
34 | paint.setAlpha(alpha);
35 |
36 |
37 | Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
38 | bitmap.eraseColor(Color.parseColor(color));
39 |
40 | Bitmap temp_box = Bitmap.createBitmap(width, height, Config.ARGB_8888);
41 | Canvas canvas = new Canvas(temp_box);
42 | canvas.drawBitmap(bitmap, 0, 0, paint);
43 |
44 | File outputFile;
45 | outputFile = File.createTempFile("box_"+width+height+color, ".png", tmpDir);
46 | FileOutputStream os = new FileOutputStream(outputFile);
47 | temp_box.compress(Bitmap.CompressFormat.PNG, 100, os);
48 | overlayFile = outputFile;
49 | xParam = Integer.toString(x);
50 | yParam = Integer.toString(y);
51 |
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/DrawTextVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | import java.io.File;
4 |
5 | public class DrawTextVideoFilter extends VideoFilter {
6 |
7 | private String mX;
8 | private String mY;
9 | private String mText;
10 | private String mFontColor;
11 | private int mFontSize;
12 | private File mFileFont;
13 | private int mBox;
14 | private String mBoxColor;
15 |
16 | public final static String X_CENTERED = "(w-text_w)/2";
17 | public final static String Y_CENTERED = "(h-text_h-line_h)/2";
18 |
19 | public final static String X_LEFT = "0";
20 | public final static String Y_BOTTOM = "(h-text_h-line_h)";
21 |
22 | public DrawTextVideoFilter (String text)
23 | {
24 | mX = X_CENTERED;
25 | mY = Y_CENTERED;
26 |
27 | mText = text;
28 | mFontColor = "white";
29 | mFontSize = 36;
30 | mFileFont = new File("/system/fonts/Roboto-Regular.ttf");
31 | if (!mFileFont.exists())
32 | mFileFont = new File("/system/fonts/DroidSerif-Regular.ttf");
33 |
34 | mBox = 1;
35 | mBoxColor = "black@0.5";//0x00000000@1
36 |
37 | }
38 |
39 | public DrawTextVideoFilter (String text, String x, String y, String fontColor, int fontSize, File fontFile, boolean showBox, String boxColor, String boxOpacity)
40 | {
41 | mX = x;
42 | mY = y;
43 |
44 | mText = text;
45 | mFontColor = fontColor;
46 | mFontSize = fontSize;
47 |
48 | mFileFont = fontFile;
49 |
50 | mBox = showBox? 1 : 0;
51 | mBoxColor = boxColor + '@' + boxOpacity;
52 |
53 | }
54 |
55 | @Override
56 | public String getFilterString() {
57 |
58 | StringBuffer result = new StringBuffer ();
59 | result.append("drawtext=");
60 | result.append("fontfile='").append(mFileFont.getAbsolutePath()).append("':");
61 | result.append("text='").append(mText).append("':");
62 | result.append("x=").append(mX).append(":");
63 | result.append("y=").append(mY).append(":");
64 | result.append("fontcolor=").append(mFontColor).append(":");
65 | result.append("fontsize=").append(mFontSize).append(":");
66 | result.append("box=").append(mBox).append(":");
67 | result.append("boxcolor=").append(mBoxColor);
68 |
69 | return result.toString();
70 | }
71 |
72 | }
73 |
74 | /*
75 | * //mdout.videoFilter = "drawtext=fontfile=/system/fonts/DroidSans.ttf: text='this is awesome':x=(w-text_w)/2:y=H-60 :fontcolor=white :box=1:boxcolor=0x00000000@1";
76 |
77 | File fontFile = new File("/system/fonts/Roboto-Regular.ttf");
78 | if (!fontFile.exists())
79 | fontFile = new File("/system/fonts/DroidSans.ttf");
80 |
81 | mdout.videoFilter = "drawtext=fontfile='" + fontFile.getAbsolutePath() + "':text='this is awesome':x=(main_w-text_w)/2:y=50:fontsize=24:fontcolor=white";
82 | */
83 |
84 | /**
85 |
86 |
87 | /system/fonts
88 |
89 | AndroidClock.ttf
90 | AndroidClock_Highlight.ttf
91 | AndroidClock_Solid.ttf
92 | AndroidEmoji.ttf
93 | AnjaliNewLipi-light.ttf
94 | Clockopia.ttf
95 | DroidNaskh-Regular-SystemUI.ttf
96 | DroidNaskh-Regular.ttf
97 | DroidSans-Bold.ttf
98 | DroidSans.ttf
99 | DroidSansArmenian.ttf
100 | DroidSansDevanagari-Regular.ttf
101 | DroidSansEthiopic-Regular.ttf
102 | DroidSansFallback.ttf
103 | DroidSansGeorgian.ttf
104 | DroidSansHebrew-Bold.ttf
105 | DroidSansHebrew-Regular.ttf
106 | DroidSansMono.ttf
107 | DroidSansTamil-Bold.ttf
108 | DroidSansTamil-Regular.ttf
109 | DroidSansThai.ttf
110 | DroidSerif-Bold.ttf
111 | DroidSerif-BoldItalic.ttf
112 | DroidSerif-Italic.ttf
113 | DroidSerif-Regular.ttf
114 | Lohit-Bengali.ttf
115 | Lohit-Kannada.ttf
116 | Lohit-Telugu.ttf
117 | MTLmr3m.ttf
118 | Roboto-Bold.ttf
119 | Roboto-BoldItalic.ttf
120 | Roboto-Italic.ttf
121 | Roboto-Light.ttf
122 | Roboto-LightItalic.ttf
123 | Roboto-Regular.ttf
124 | RobotoCondensed-Bold.ttf
125 | RobotoCondensed-BoldItalic.ttf
126 | RobotoCondensed-Italic.ttf
127 | RobotoCondensed-Regular.ttf
128 | */
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/FadeVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | public class FadeVideoFilter extends VideoFilter {
4 |
5 | private String mAction; //in our out
6 | private int mStart;
7 | private int mLength;
8 |
9 | public FadeVideoFilter (String action, int start, int length)
10 | {
11 | mAction = action;
12 | mStart = start;
13 | mLength = length;
14 | }
15 |
16 | @Override
17 | public String getFilterString() {
18 |
19 | StringBuffer result = new StringBuffer ();
20 | result.append("fade=");
21 | result.append(mAction).append(':').append(mStart).append(':').append(mLength);
22 |
23 | return result.toString();
24 | }
25 |
26 | }
27 |
28 | ///fade=in:0:25, fade=out:975:25
29 |
30 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/OverlayVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * @class overlay overlay one image or video on top of another
7 | *
8 | * @desc x is the x coordinate of the overlayed video on the main video,
9 | * y is the y coordinate. The parameters are expressions containing
10 | * the following parameters:
11 | *
12 | * main_w, main_h
13 | * main input width and height
14 | *
15 | * W, H
16 | * same as main_w and main_h
17 | *
18 | * overlay_w, overlay_h
19 | * overlay input width and height
20 | *
21 | * w, h
22 | * same as overlay_w and overlay_h
23 | *
24 | * @examples
25 | * draw the overlay at 10 pixels from the bottom right
26 | * corner of the main video.
27 | * main_w-overlay_w-10
28 | * main_h-overlay_h-10
29 | * draw the overlay in the bottom left corner of the input
30 | * 10
31 | * main_h-overlay_h-10 [out]
32 | *
33 | */
34 | public class OverlayVideoFilter extends VideoFilter {
35 |
36 | public File overlayFile;
37 | public String xParam, yParam;
38 |
39 | public OverlayVideoFilter() {
40 |
41 | }
42 |
43 | public OverlayVideoFilter (File fileMovieOverlay, int x, int y)
44 | {
45 | this.overlayFile = fileMovieOverlay;
46 | this.xParam = Integer.toString(x);
47 | this.yParam = Integer.toString(y);
48 | }
49 |
50 | public OverlayVideoFilter (File fileMovieOverlay, String xExpression, String yExpression)
51 | {
52 | this.overlayFile = fileMovieOverlay;
53 | this.xParam = xExpression;
54 | this.yParam = yExpression;
55 | }
56 |
57 | public String getFilterString ()
58 | {
59 | if (overlayFile != null)
60 | return "movie="
61 | + overlayFile.getAbsolutePath()
62 | + " [logo];[in][logo] "
63 | + "overlay=" + xParam + ":" + yParam
64 | + " [out]";
65 | else
66 | return "";
67 |
68 | }
69 | }
70 |
71 | //"\"movie="+ overlayImage.getPath() +" [logo];[in][logo] overlay=0:0 [out]\"",
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/RedactVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | import java.io.File;
4 |
5 | public class RedactVideoFilter extends VideoFilter {
6 |
7 | private File fileRedactList;
8 |
9 | public RedactVideoFilter (File fileRedactList)
10 | {
11 | this.fileRedactList = fileRedactList;
12 | }
13 |
14 | public String getFilterString ()
15 | {
16 | if (fileRedactList != null)
17 | return "redact=" + fileRedactList.getAbsolutePath();
18 | else
19 | return "";
20 |
21 | }
22 | }
23 |
24 | //redact=blurbox.txt [out] [d], [d]nullsink
25 | //"redact=" + Environment.getExternalStorageDirectory().getPath() + "/" + PACKAGENAME + "/redact_unsort.txt",
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/TransposeVideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | /*
4 | * works for video and images
5 | * 0 = 90CounterCLockwise and Vertical Flip (default)
6 | 1 = 90Clockwise
7 | 2 = 90CounterClockwise
8 | 3 = 90Clockwise and Vertical Flip
9 | */
10 | public class TransposeVideoFilter extends VideoFilter {
11 |
12 | private int mTranspose = -1;
13 |
14 | public final static int NINETY_COUNTER_CLOCKWISE_AND_VERTICAL_FLIP = 0;
15 | public final static int NINETY_CLOCKWISE = 1;
16 | public final static int NINETY_COUNTER_CLOCKWISE = 2;
17 | public final static int NINETY_CLOCKWISE_AND_VERTICAL_FLIP = 3;
18 |
19 | public TransposeVideoFilter (int transpose)
20 | {
21 | mTranspose = transpose;
22 | }
23 |
24 | @Override
25 | public String getFilterString() {
26 |
27 | return "transpose=" + mTranspose;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/filters/VideoFilter.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.filters;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Iterator;
5 |
6 | public abstract class VideoFilter {
7 |
8 | public abstract String getFilterString ();
9 |
10 | public static String format (ArrayList listFilters)
11 | {
12 | StringBuffer result = new StringBuffer();
13 |
14 | Iterator it = listFilters.iterator();
15 | VideoFilter vf;
16 |
17 | while (it.hasNext())
18 | {
19 | vf = it.next();
20 | result.append(vf.getFilterString());
21 |
22 | if (it.hasNext())
23 | result.append(",");
24 | }
25 | return result.toString();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/test/ConcatTest.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.test;
2 |
3 |
4 | import java.io.File;
5 | import java.util.ArrayList;
6 | import java.util.Locale;
7 |
8 | import net.sourceforge.sox.SoxController;
9 |
10 | import org.ffmpeg.android.Clip;
11 | import org.ffmpeg.android.FFmpegController;
12 | import org.ffmpeg.android.ShellUtils;
13 |
14 | public class ConcatTest {
15 |
16 | public static void test (String videoRoot, String fileTmpPath, String fileOut, double fadeLen) throws Exception
17 | {
18 | File fileTmp = new File(fileTmpPath);
19 | File fileAppRoot = new File("");
20 | File fileVideoRoot = new File(videoRoot);
21 |
22 | FFmpegController fc = new FFmpegController(null, fileTmp);
23 | SoxController sxCon = new SoxController(null, fileAppRoot, null);
24 |
25 | ArrayList listVideos = new ArrayList();
26 |
27 | String[] fileList = fileVideoRoot.list();
28 | for (String fileVideo : fileList)
29 | {
30 | if (fileVideo.endsWith("mp4"))
31 | {
32 | Clip clip = new Clip();
33 | clip.path = new File(fileVideoRoot,fileVideo).getCanonicalPath();
34 |
35 | fc.getInfo(clip);
36 |
37 | clip.duration = clip.duration-fadeLen;
38 | listVideos.add(clip);
39 |
40 |
41 | }
42 | }
43 |
44 | Clip clipOut = new Clip ();
45 | clipOut.path = new File(fileOut).getCanonicalPath();
46 |
47 | fc.concatAndTrimFilesMP4Stream(listVideos, clipOut, false, false, new ShellUtils.ShellCallback() {
48 |
49 | @Override
50 | public void shellOut(String shellLine) {
51 |
52 | System.out.println("fc>" + shellLine);
53 | }
54 |
55 | @Override
56 | public void processComplete(int exitValue) {
57 |
58 | if (exitValue < 0)
59 | System.err.println("concat non-zero exit: " + exitValue);
60 | }
61 | });
62 |
63 |
64 |
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/test/ConvertTest.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.test;
2 |
3 | public class ConvertTest {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/test/CrossfadeTest.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.test;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.util.ArrayList;
6 | import java.util.Locale;
7 |
8 | import net.sourceforge.sox.CrossfadeCat;
9 | import net.sourceforge.sox.SoxController;
10 |
11 | import org.ffmpeg.android.Clip;
12 | import org.ffmpeg.android.FFmpegController;
13 | import org.ffmpeg.android.ShellUtils;
14 |
15 | public class CrossfadeTest {
16 |
17 |
18 | public static void test (String videoRoot, String fileTmpPath, String clipOutPath, double fadeLen) throws Exception
19 | {
20 | File fileTmp = new File(fileTmpPath);
21 | File fileAppRoot = new File("");
22 | File fileVideoRoot = new File(videoRoot);
23 |
24 | String fadeType = "l";
25 | int sampleRate = 22050;
26 | int channels = 1;
27 |
28 | FFmpegController ffmpegc = new FFmpegController (null, fileTmp);
29 |
30 | Clip clipOut = new Clip();
31 | clipOut.path = clipOutPath;
32 | clipOut.audioCodec="aac";
33 | clipOut.audioBitrate=56;
34 |
35 |
36 | ArrayList listVideos = new ArrayList();
37 |
38 | String[] fileList = fileVideoRoot.list();
39 | for (String fileVideo : fileList)
40 | {
41 | if (fileVideo.endsWith("mp4"))
42 | {
43 | Clip clip = new Clip();
44 | clip.path = new File(fileVideoRoot,fileVideo).getCanonicalPath();
45 | //clip.startTime = "00:00:03";
46 | //clip.duration = "00:00:02";
47 |
48 | ffmpegc.getInfo(clip);
49 |
50 | //System.out.println("clip " + fileVideo + " duration=" + clip.duration);
51 |
52 | listVideos.add(clip);
53 |
54 | }
55 | }
56 |
57 | //now add 1 second cross fade to each audio file and cat them together
58 | SoxController sxCon = new SoxController(null, fileAppRoot, new ShellUtils.ShellCallback() {
59 |
60 | @Override
61 | public void shellOut(String shellLine) {
62 |
63 | // System.out.println("sxCon> " + shellLine);
64 |
65 | }
66 |
67 | @Override
68 | public void processComplete(int exitValue) {
69 |
70 |
71 | if (exitValue != 0)
72 | {
73 | System.err.println("sxCon> EXIT=" + exitValue);
74 |
75 | RuntimeException re = new RuntimeException("non-zero exit: " + exitValue);
76 | re.printStackTrace();
77 | throw re;
78 | }
79 |
80 | }
81 | });
82 |
83 | ArrayList alAudio = new ArrayList();
84 |
85 | //convert each input file to a WAV so we can use Sox to process
86 | int wavIdx = 0;
87 |
88 | for (Clip mediaIn : listVideos)
89 | {
90 | if (new File(mediaIn.path).exists())
91 | {
92 |
93 | if (mediaIn.audioCodec == null)
94 | {
95 | //there is no audio track so let's generate silence
96 |
97 |
98 | }
99 | else
100 | {
101 | Clip audioOut = ffmpegc.convertToWaveAudio(mediaIn, new File(fileTmp, wavIdx+".wav").getCanonicalPath(),sampleRate,channels, new ShellUtils.ShellCallback() {
102 |
103 | @Override
104 | public void shellOut(String shellLine) {
105 |
106 | // System.out.println("convertToWav> " + shellLine);
107 |
108 | }
109 |
110 | @Override
111 | public void processComplete(int exitValue) {
112 |
113 | if (exitValue != 0)
114 | {
115 |
116 | System.err.println("convertToWav> EXIT=" + exitValue);
117 |
118 | RuntimeException re = new RuntimeException("non-zero exit: " + exitValue);
119 | re.printStackTrace();
120 | throw re;
121 | }
122 | }
123 | });
124 |
125 | alAudio.add(audioOut);
126 |
127 | /*
128 | float duration = (float) sxCon.getLength(new File(audioOut.path).getCanonicalPath());
129 |
130 | if (mediaIn.duration == null)
131 | {
132 | mediaIn.duration = String.format(Locale.US, "%f", duration);
133 | }*/
134 | ffmpegc.getInfo(mediaIn);
135 |
136 |
137 | wavIdx++;
138 | }
139 | }
140 | else
141 | {
142 | throw new FileNotFoundException(mediaIn.path);
143 | }
144 | }
145 |
146 | if (alAudio.size() > 0)
147 | {
148 | String fileOut = alAudio.get(0).path;
149 |
150 | System.out.println("mix length=" + sxCon.getLength(fileOut));
151 |
152 | for (int i = 1; i < alAudio.size(); i++)
153 | {
154 |
155 | File fileAdd = new File(alAudio.get(i).path);
156 |
157 | CrossfadeCat xCat = new CrossfadeCat(sxCon, fileOut, fileAdd.getCanonicalPath(), fadeLen, fileOut);
158 | xCat.start();
159 |
160 | fileAdd.deleteOnExit();
161 |
162 | System.out.println("mix length=" + sxCon.getLength(fileOut));
163 |
164 | }
165 |
166 |
167 | //1 second fade in and fade out, t = triangle or linear
168 | //String fadeLenStr = sxCon.formatTimePeriod(fadeLen);
169 |
170 |
171 |
172 | String fadeFileOut = sxCon.fadeAudio(fileOut, fadeType, fadeLen, sxCon.getLength(fileOut)-fadeLen, fadeLen);
173 |
174 | //now export the final file to our requested output format mOut.mimeType = AppConstants.MimeTypes.MP4_AUDIO;
175 |
176 | Clip mdFinalIn = new Clip();
177 | mdFinalIn.path = fadeFileOut;
178 |
179 |
180 | System.out.println ("final duration: " + sxCon.getLength(fadeFileOut));
181 |
182 | Clip exportOut = ffmpegc.convertTo3GPAudio(mdFinalIn, clipOut, new ShellUtils.ShellCallback() {
183 |
184 | @Override
185 | public void shellOut(String shellLine) {
186 |
187 | //System.out.println("convertTo3gp> " + shellLine);
188 | }
189 |
190 | @Override
191 | public void processComplete(int exitValue) {
192 |
193 | if (exitValue < 0)
194 | {
195 | RuntimeException re = new RuntimeException("non-zero exit: " + exitValue);
196 | re.printStackTrace();
197 | throw re;
198 | }
199 | }
200 | });
201 | }
202 | }
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/test/FilterTest.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.test;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.ArrayList;
6 |
7 | import org.ffmpeg.android.filters.CropVideoFilter;
8 | import org.ffmpeg.android.filters.DrawBoxVideoFilter;
9 | import org.ffmpeg.android.filters.DrawTextVideoFilter;
10 | import org.ffmpeg.android.filters.FadeVideoFilter;
11 | import org.ffmpeg.android.filters.TransposeVideoFilter;
12 | import org.ffmpeg.android.filters.VideoFilter;
13 |
14 | import android.app.Activity;
15 | import android.content.Context;
16 |
17 | public class FilterTest {
18 |
19 |
20 | public static void test (String title, String textColor, File fileFont, String boxColor, String opacity) throws Exception
21 | {
22 | ArrayList listFilters = new ArrayList();
23 |
24 | File fileDir = new File("tmp");
25 | fileDir.mkdir();
26 |
27 | int height = 480;
28 | int width = 720;
29 | int lowerThird = height / 3;
30 | DrawBoxVideoFilter vf = new DrawBoxVideoFilter(0,height-lowerThird,width,lowerThird,100,"blue",fileDir);
31 |
32 | DrawTextVideoFilter vfTitle =
33 | new DrawTextVideoFilter(title,
34 | DrawTextVideoFilter.X_CENTERED,DrawTextVideoFilter.Y_CENTERED,
35 | textColor,
36 | 38,
37 | fileFont,
38 | true,
39 | boxColor,
40 | opacity);
41 |
42 | float fps = 29.97f;
43 | int fadeTime = (int)(fps*3);
44 | //fades in first 3 seconds
45 | FadeVideoFilter vfFadeIn = new FadeVideoFilter("in",0,fadeTime);
46 |
47 | //fades out last 50 frames
48 | int totalFrames = (int)(14.37*29.97);
49 | FadeVideoFilter vfFadeOut = new FadeVideoFilter("out",totalFrames-fadeTime,fadeTime);
50 |
51 | //crops video in 100 pixels on each side
52 | CropVideoFilter vfCrop = new CropVideoFilter("in_w-100","in_h-100","100","100");
53 |
54 | //rotates video 90 degress clockwise
55 | TransposeVideoFilter vfTranspose = new TransposeVideoFilter(TransposeVideoFilter.NINETY_CLOCKWISE);
56 |
57 | listFilters.add(vfTranspose);
58 | listFilters.add(vfCrop);
59 | listFilters.add(vfTitle);
60 | listFilters.add(vfFadeIn);
61 | listFilters.add(vfFadeOut);
62 |
63 |
64 |
65 | fileDir.deleteOnExit();
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/test/MixTest.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.test;
2 |
3 | import java.io.File;
4 |
5 | import org.ffmpeg.android.Clip;
6 | import org.ffmpeg.android.FFmpegController;
7 | import org.ffmpeg.android.ShellUtils;
8 |
9 | public class MixTest {
10 |
11 | public static void test (String fileTmpPath, String videoClipPath, String audioClipPath, Clip clipOut) throws Exception
12 | {
13 | File fileTmp = new File(fileTmpPath);
14 | File fileAppRoot = new File("");
15 |
16 | FFmpegController fc = new FFmpegController(null, fileTmp);
17 |
18 | Clip clipVideo = new Clip(videoClipPath);
19 | //fc.getInfo(clipVideo);
20 |
21 | Clip clipAudio = new Clip(audioClipPath);
22 | //fc.getInfo(clipAudio);
23 |
24 | fc.combineAudioAndVideo(clipVideo, clipAudio, clipOut, new ShellUtils.ShellCallback() {
25 |
26 | @Override
27 | public void shellOut(String shellLine) {
28 | // System.out.println("MIX> " + shellLine);
29 | }
30 |
31 | @Override
32 | public void processComplete(int exitValue) {
33 |
34 | if (exitValue != 0)
35 | System.err.println("concat non-zero exit: " + exitValue);
36 | }
37 | });
38 |
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/java/org/ffmpeg/android/test/Tests.java:
--------------------------------------------------------------------------------
1 | package org.ffmpeg.android.test;
2 |
3 | import java.io.File;
4 |
5 | import org.ffmpeg.android.Clip;
6 |
7 | public class Tests {
8 |
9 | /**
10 | * @param args
11 | */
12 | public static void main(String[] args) throws Exception {
13 |
14 |
15 |
16 | String[] testpaths = {
17 | // "/home/n8fr8/Desktop/smcampmovie",
18 | // "/home/n8fr8/Desktop/smcampmovie2",
19 | "/home/n8fr8/Desktop/sm3"
20 |
21 | };
22 |
23 | int idx = -1;
24 |
25 | double fadeLen = 1;
26 |
27 | for (String testpath : testpaths)
28 | {
29 | idx++;
30 |
31 | System.out.println ("************************************");
32 | System.out.println ("CONCAT TEST: " + testpath);
33 |
34 | File fileVideoOutput = new File("/tmp/test" + idx + ".mp4");
35 | fileVideoOutput.delete();
36 |
37 | ConcatTest.test(testpath, "/tmp", fileVideoOutput.getCanonicalPath(), fadeLen);
38 |
39 | if (!fileVideoOutput.exists())
40 | {
41 | System.out.println("FAIL!! > output file did not get created: " + fileVideoOutput.getCanonicalPath());
42 | continue;
43 | }
44 | else
45 | System.out.println("SUCCESS!! > " + fileVideoOutput.getCanonicalPath());
46 |
47 | System.out.println ("************************************");
48 | System.out.println ("CROSSFADE TEST: " + testpath);
49 |
50 | File fileAudioOutput = new File("/tmp/test" + idx + ".3gp");
51 | fileAudioOutput.delete();
52 | CrossfadeTest.test(testpath, "/tmp", fileAudioOutput.getCanonicalPath(),fadeLen);
53 | if (!fileAudioOutput.exists())
54 | {
55 | System.out.println("FAIL!! > output file did not get created: " + fileAudioOutput.getCanonicalPath());
56 | continue;
57 | }
58 | else
59 | System.out.println("SUCCESS!! > " + fileAudioOutput.getCanonicalPath());
60 |
61 | System.out.println ("************************************");
62 | System.out.println ("MIX TEST: " + testpath);
63 |
64 | File fileMix = new File("/tmp/test" + idx + "mix.mp4");
65 | fileMix.delete();
66 | Clip clipMixOut = new Clip(fileMix.getCanonicalPath());
67 | MixTest.test("/tmp", fileVideoOutput.getCanonicalPath(), fileAudioOutput.getCanonicalPath(), clipMixOut);
68 | if (!fileMix.exists())
69 | System.out.println("FAIL!! > output file did not get created: " + fileMix.getCanonicalPath());
70 | else
71 | System.out.println("SUCCESS!! > " + fileMix.getCanonicalPath());
72 |
73 |
74 | }
75 |
76 | System.out.println("**********************");
77 | System.out.println("*******FIN**********");
78 |
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/drawable-hdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/drawable-hdpi/ic_action_search.png
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/drawable-mdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/drawable-mdpi/ic_action_search.png
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/drawable-xhdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/drawable-xhdpi/ic_action_search.png
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/raw/ffmpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/raw/ffmpeg
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/raw/sox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/ffmpeg_java_wrapper_lib/src/main/res/raw/sox
--------------------------------------------------------------------------------
/ffmpeg_java_wrapper_lib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | android-ffmpeg-library
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shutup/android-ffmpeg-java-demo/dd5f0a6fdc4640046dad3676ac86efb7facd3837/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':ffmpeg_java_wrapper_lib', ':ffmpeg_java_wrapper_demo'
2 |
--------------------------------------------------------------------------------