├── .gitignore ├── DemosXamarinMovieProcessing.sln ├── DemosXamarinMovieProcessing.userprefs ├── README.md ├── XamarinAndroidFFmpeg ├── Helpers │ ├── ffmpeg │ │ ├── Clip.cs │ │ ├── FFMpeg.cs │ │ ├── ShellUtils.cs │ │ ├── filters │ │ │ ├── ColorVideoFilter.cs │ │ │ ├── CropVideoFilter.cs │ │ │ ├── DrawBoxVideoFilter.cs │ │ │ ├── DrawTextVideoFilter.cs │ │ │ ├── FadeVideoFilter.cs │ │ │ ├── OverlayVideoFilter.cs │ │ │ ├── RedactVideoFilter.cs │ │ │ ├── TransposeVideoFilter.cs │ │ │ └── VideoFilter.cs │ │ └── test │ │ │ ├── ConcatTest.cs │ │ │ ├── ConvertTest.cs │ │ │ ├── CrossfadeTest.cs │ │ │ ├── FilterTest.cs │ │ │ ├── MixTest.cs │ │ │ └── Tests.cs │ └── sox │ │ ├── CrossfadeCat.cs │ │ └── SoxHelpers.cs ├── Resources │ ├── Resource.designer.cs │ ├── raw │ │ ├── ffmpeg │ │ └── sox │ └── values │ │ └── Strings.xml └── XamarinAndroidFFmpeg.csproj ├── XamarinAndroidFFmpegTests ├── Assets │ └── AboutAssets.txt ├── MainActivity.cs ├── Properties │ ├── AndroidManifest.xml │ └── AssemblyInfo.cs ├── Resources │ ├── AboutResources.txt │ ├── Resource.designer.cs │ ├── drawable-hdpi │ │ └── Icon.png │ ├── drawable-mdpi │ │ └── Icon.png │ ├── drawable-xhdpi │ │ └── Icon.png │ ├── drawable-xxhdpi │ │ └── Icon.png │ ├── drawable-xxxhdpi │ │ └── Icon.png │ ├── layout │ │ └── Main.axml │ ├── raw │ │ ├── big_buck.mov │ │ └── cat1.mp4 │ └── values │ │ └── Strings.xml ├── XamarinAndroidFFmpegTests.csproj └── isoparser.dll ├── ffmpeg.userprefs └── packages ├── NUnit.2.6.3 ├── NUnit.2.6.3.nupkg ├── lib │ ├── nunit.framework.dll │ └── nunit.framework.xml └── license.txt ├── Xamarin.UITest.0.7.1 ├── Xamarin.UITest-License.rtf ├── Xamarin.UITest.0.7.1.nupkg ├── lib │ ├── Xamarin.UITest.dll │ └── Xamarin.UITest.xml ├── release-notes.md └── tools │ └── test-cloud.exe └── repositories.config /.gitignore: -------------------------------------------------------------------------------- 1 | XamarinAndroidFFmpegTests/obj/ 2 | XamarinAndroidFFmpegTests/bin/ 3 | XamarinAndroidFFmpeg/obj/ 4 | XamarinAndroidFFmpeg/bin/ 5 | -------------------------------------------------------------------------------- /DemosXamarinMovieProcessing.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamarinAndroidFFmpegTests", "XamarinAndroidFFmpegTests\XamarinAndroidFFmpegTests.csproj", "{87A5E21C-8AAF-4744-AA7A-92F87DB1684B}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamarinAndroidFFmpeg", "XamarinAndroidFFmpeg\XamarinAndroidFFmpeg.csproj", "{FBB10D9B-A045-4077-BE56-D71CC8A113AE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {87A5E21C-8AAF-4744-AA7A-92F87DB1684B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {87A5E21C-8AAF-4744-AA7A-92F87DB1684B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {87A5E21C-8AAF-4744-AA7A-92F87DB1684B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {87A5E21C-8AAF-4744-AA7A-92F87DB1684B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {FBB10D9B-A045-4077-BE56-D71CC8A113AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {FBB10D9B-A045-4077-BE56-D71CC8A113AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {FBB10D9B-A045-4077-BE56-D71CC8A113AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {FBB10D9B-A045-4077-BE56-D71CC8A113AE}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /DemosXamarinMovieProcessing.userprefs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | XamarinAndroidFFmpegLibs\XamarinAndroidFFmpegLibs.csproj 24 | 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XamarinAndroidFFmpeg 2 | 3 | Ported from: https://github.com/guardianproject 4 | 5 | Xamarin Android FFmpeg as a process - Examples 6 | 7 | This Xamarin Android application is showing how to use a ARMv7 compiled FFmpeg as a process in Android the same way 8 | it is used in a Windows command line. 9 | 10 | There are some video conversion examples. 11 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/Clip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace XamarinAndroidFFmpeg 4 | { 5 | 6 | public class Clip : ICloneable 7 | { 8 | 9 | public int width = -1; 10 | public int height = -1; 11 | 12 | public string videoCodec; 13 | public string videoFps; 14 | public int videoBitrate = -1; 15 | public string videoBitStreamFilter; 16 | 17 | public string audioCodec; 18 | public int audioChannels = -1; 19 | public int audioBitrate = -1; 20 | public string audioQuality; 21 | public int audioVolume = -1; 22 | public string audioBitStreamFilter; 23 | 24 | public string path; 25 | public string format; 26 | public string mimeType; 27 | 28 | public string startTime; //00:00:00 or seconds format 29 | public double duration = -1; //00:00:00 or seconds format 30 | 31 | public string videoFilter; 32 | public string audioFilter; 33 | 34 | public string qscaleVideo; 35 | public string qscaleAudio; 36 | public string qscale; 37 | 38 | public string H264_CRF; 39 | 40 | public string aspect; 41 | public int passCount = 1; //default 42 | 43 | public Clip() 44 | { 45 | 46 | } 47 | 48 | public Clip(string path) 49 | { 50 | this.path = path; 51 | } 52 | 53 | object ICloneable.Clone() { 54 | return Clone (); 55 | } 56 | 57 | public virtual Clip Clone() 58 | { 59 | return new Clip (this.path) { 60 | aspect = this.aspect, 61 | audioBitrate = this.audioBitrate, 62 | audioBitStreamFilter = this.audioBitStreamFilter, 63 | audioChannels = audioChannels, 64 | audioCodec = this.audioCodec, 65 | audioFilter = this.audioFilter, 66 | audioQuality = this.audioQuality, 67 | audioVolume = this.audioVolume, 68 | duration = this.duration, 69 | format = this.format, 70 | height = this.height, 71 | mimeType = this.mimeType, 72 | passCount = this.passCount, 73 | path = this.path, 74 | qscale = this.qscale, 75 | startTime = this.startTime, 76 | videoBitrate = this.videoBitrate, 77 | videoBitStreamFilter = this.videoBitStreamFilter, 78 | videoCodec = this.videoCodec, 79 | videoFilter = this.videoFilter, 80 | videoFps = this.videoFps, 81 | width = this.width 82 | }; 83 | } 84 | 85 | public virtual bool Image 86 | { 87 | get 88 | { 89 | if (mimeType != null) 90 | { 91 | return mimeType.StartsWith("image"); 92 | } 93 | else 94 | { 95 | return false; 96 | } 97 | } 98 | } 99 | 100 | public virtual bool Video 101 | { 102 | get 103 | { 104 | if (mimeType != null) 105 | { 106 | return mimeType.StartsWith("video"); 107 | } 108 | else 109 | { 110 | return false; 111 | } 112 | } 113 | } 114 | 115 | public virtual bool Audio 116 | { 117 | get 118 | { 119 | if (mimeType != null) 120 | { 121 | return mimeType.StartsWith("audio"); 122 | } 123 | else 124 | { 125 | return false; 126 | } 127 | } 128 | } 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/FFMpeg.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpeg/Helpers/ffmpeg/FFMpeg.cs -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/ShellUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | /* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ 5 | /* See LICENSE for licensing information */ 6 | using Java.IO; 7 | using Java.Lang; 8 | using System.Windows.Input; 9 | 10 | 11 | namespace XamarinAndroidFFmpeg 12 | { 13 | public class ShellUtils 14 | { 15 | 16 | //various console cmds 17 | public const string SHELL_CMD_CHMOD = "chmod"; 18 | public const string SHELL_CMD_KILL = "kill -9"; 19 | public const string SHELL_CMD_RM = "rm"; 20 | public const string SHELL_CMD_PS = "ps"; 21 | public const string SHELL_CMD_PIDOF = "pidof"; 22 | 23 | public const string CHMOD_EXE_VALUE = "700"; 24 | 25 | public static bool RootPossible 26 | { 27 | get 28 | { 29 | 30 | var log = new Java.Lang.StringBuilder(); 31 | 32 | try 33 | { 34 | 35 | // Check if Superuser.apk exists 36 | File fileSU = new File("/system/app/Superuser.apk"); 37 | if (fileSU.Exists()) 38 | { 39 | return true; 40 | } 41 | 42 | fileSU = new File("/system/bin/su"); 43 | if (fileSU.Exists()) 44 | { 45 | return true; 46 | } 47 | 48 | //Check for 'su' binary 49 | string[] cmd = new string[] {"which su"}; 50 | int exitCode = ShellUtils.doShellCommand(null,cmd, new ShellCallbackAnonymousInnerClassHelper(null, null), false, true).ExitValue(); 51 | 52 | if (exitCode == 0) 53 | { 54 | logMessage("Can acquire root permissions"); 55 | return true; 56 | 57 | } 58 | 59 | } 60 | catch (IOException e) 61 | { 62 | //this means that there is no root to be had (normally) so we won't log anything 63 | logException("Error checking for root access",e); 64 | 65 | } 66 | catch (System.Exception) 67 | { 68 | // logException("Error checking for root access",e); 69 | //this means that there is no root to be had (normally) 70 | } 71 | 72 | logMessage("Could not acquire root permissions"); 73 | 74 | 75 | return false; 76 | } 77 | } 78 | 79 | public static int FindProcessId(string command) 80 | { 81 | int procId = -1; 82 | 83 | try 84 | { 85 | procId = FindProcessIdWithPidOf(command); 86 | 87 | if (procId == -1) 88 | { 89 | procId = findProcessIdWithPS(command); 90 | } 91 | } 92 | catch (System.Exception) 93 | { 94 | try 95 | { 96 | procId = findProcessIdWithPS(command); 97 | } 98 | catch (System.Exception) 99 | { 100 | //logException("Unable to get proc id for: " + command,e2); 101 | } 102 | } 103 | 104 | return procId; 105 | } 106 | 107 | //use 'pidof' command 108 | public static int FindProcessIdWithPidOf(string command) 109 | { 110 | 111 | int procId = -1; 112 | 113 | Process procPs = null; 114 | 115 | string baseName = (new System.IO.FileInfo(command)).Name; 116 | //fix contributed my mikos on 2010.12.10 117 | var r = Runtime.GetRuntime(); 118 | procPs = r.Exec(new string[] {SHELL_CMD_PIDOF, baseName}); 119 | //procPs = r.exec(SHELL_CMD_PIDOF); 120 | 121 | BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.InputStream)); 122 | string line = null; 123 | 124 | while ((line = reader.ReadLine()) != null) 125 | { 126 | 127 | try 128 | { 129 | //this line should just be the process id 130 | procId = Convert.ToInt32(line.Trim()); 131 | break; 132 | } 133 | catch (NumberFormatException e) 134 | { 135 | logException("unable to parse process pid: " + line,e); 136 | } 137 | } 138 | 139 | 140 | return procId; 141 | 142 | } 143 | 144 | //use 'ps' command 145 | public static int findProcessIdWithPS(string command) 146 | { 147 | int procId = -1; 148 | 149 | Process procPs = null; 150 | var r = Runtime.GetRuntime (); 151 | procPs = r.Exec(SHELL_CMD_PS); 152 | 153 | BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.InputStream)); 154 | string line = null; 155 | 156 | while ((line = reader.ReadLine()) != null) 157 | { 158 | if (line.IndexOf(' ' + command) != -1) 159 | { 160 | 161 | var st = new Java.Util.StringTokenizer(line," "); 162 | st.NextToken(); //proc owner 163 | 164 | procId = Convert.ToInt32(st.NextToken().Trim()); 165 | 166 | break; 167 | } 168 | } 169 | 170 | 171 | 172 | return procId; 173 | 174 | } 175 | 176 | public static int doShellCommand(string[] cmds, FFMpegCallbacks sc, bool runAsRoot, bool waitFor) 177 | { 178 | return doShellCommand(null, cmds, sc, runAsRoot, waitFor).ExitValue(); 179 | } 180 | 181 | public static Process doShellCommand(Java.Lang.Process proc, string[] cmds, FFMpegCallbacks sc, bool runAsRoot, bool waitFor) 182 | { 183 | var r = Runtime.GetRuntime (); 184 | 185 | if (proc == null) 186 | { 187 | if (runAsRoot) 188 | { 189 | proc = r.Exec("su"); 190 | } 191 | else 192 | { 193 | proc = r.Exec("sh"); 194 | } 195 | } 196 | 197 | OutputStreamWriter outputStream = new OutputStreamWriter(proc.OutputStream); 198 | 199 | for (int i = 0; i < cmds.Length; i++) 200 | { 201 | logMessage("executing shell cmd: " + cmds[i] + "; runAsRoot=" + runAsRoot + ";waitFor=" + waitFor); 202 | 203 | outputStream.Write(cmds[i]); 204 | outputStream.Write("\n"); 205 | } 206 | 207 | outputStream.Flush(); 208 | outputStream.Write("exit\n"); 209 | outputStream.Flush(); 210 | 211 | if (waitFor) 212 | { 213 | char[] buf = new char[20]; 214 | 215 | // Consume the "stdout" 216 | InputStreamReader reader = new InputStreamReader(proc.InputStream); 217 | int read = 0; 218 | while ((read = reader.Read(buf)) != -1) 219 | { 220 | if (sc != null) 221 | { 222 | sc.ShellOut(new string(buf)); 223 | } 224 | } 225 | 226 | // Consume the "stderr" 227 | reader = new InputStreamReader(proc.ErrorStream); 228 | read = 0; 229 | while ((read = reader.Read(buf)) != -1) 230 | { 231 | if (sc != null) 232 | { 233 | sc.ShellOut(new string(buf)); 234 | } 235 | } 236 | 237 | proc.WaitFor(); 238 | 239 | } 240 | 241 | sc.ProcessComplete(proc.ExitValue()); 242 | 243 | return proc; 244 | 245 | } 246 | 247 | public static void logMessage(string msg) 248 | { 249 | } 250 | 251 | public static void logException(string msg, Java.Lang.Exception e) 252 | { 253 | } 254 | } 255 | 256 | public class ShellCallbackAnonymousInnerClassHelper : FFMpegCallbacks 257 | { 258 | public ShellCallbackAnonymousInnerClassHelper(ICommand completedAction, ICommand messageAction) : base(completedAction, messageAction) 259 | { 260 | } 261 | 262 | public override void ShellOut(string msg) 263 | { 264 | } 265 | 266 | public override void ProcessComplete(int exitValue) 267 | { 268 | base.ProcessComplete(exitValue); 269 | } 270 | 271 | } 272 | 273 | public class FFMpegCallbacks 274 | { 275 | public ICommand _completedAction {get;set;} 276 | 277 | public ICommand _messageAction {get;set;} 278 | 279 | public FFMpegCallbacks(ICommand completedAction, ICommand messageAction) { 280 | _completedAction = completedAction; 281 | _messageAction = messageAction; 282 | } 283 | 284 | public virtual void ShellOut(string shellLine) { 285 | _messageAction.Execute (shellLine); 286 | } 287 | 288 | public virtual void ProcessComplete(int exitValue) { 289 | _completedAction.Execute (null); 290 | } 291 | } 292 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/ColorVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace XamarinAndroidFFmpeg 4 | { 5 | 6 | public class ColorVideoFilter : VideoFilter 7 | { 8 | 9 | // // mp=eq2=gamma:contrast:brightness:saturation:rg:gg:bg:weight 10 | // // cmd.Add ("'mp=eq2=0.5:0.68:0.6:0.46:1:0.96:1'"); 11 | public ColorVideoFilter(decimal gamma = 1.0m, decimal contrast = 1.0m, decimal brightness = 0.0m, decimal saturation = 1.0m, decimal redGamma = 1.0m, decimal greenGamma = 1.0m, decimal blueGamma = 1.0m, decimal weight = 1.0m) 12 | { 13 | _filterString = string.Format ("mp=eq2={0}:{1}:{2}:{3}:{4}:{5}", gamma, contrast, brightness, saturation, redGamma, greenGamma, blueGamma, weight); 14 | } 15 | 16 | string _filterString = ""; 17 | 18 | public override string FilterString 19 | { 20 | get { 21 | return _filterString; 22 | } 23 | } 24 | } 25 | 26 | ///fade=in:0:25, fade=out:975:25 27 | 28 | 29 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/CropVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace XamarinAndroidFFmpeg 4 | { 5 | 6 | public class CropVideoFilter : VideoFilter 7 | { 8 | 9 | private string mOutWidth; 10 | private string mOutHeight; 11 | private string mX; 12 | private string mY; 13 | 14 | public CropVideoFilter(string width, string height, string x, string y) 15 | { 16 | mOutWidth = width; 17 | mOutHeight = height; 18 | mX = x; 19 | mY = y; 20 | } 21 | 22 | public override string FilterString 23 | { 24 | get 25 | { 26 | 27 | StringBuilder result = new StringBuilder(); 28 | 29 | result.Append("crop="); 30 | 31 | if (mOutWidth != null) 32 | { 33 | result.Append(mOutWidth).Append(":"); 34 | } 35 | 36 | if (mOutHeight != null) 37 | { 38 | result.Append(mOutHeight).Append(":"); 39 | } 40 | 41 | if (mX != null) 42 | { 43 | result.Append(mX).Append(":"); 44 | } 45 | 46 | if (mY != null) 47 | { 48 | result.Append(mY).Append(":"); 49 | } 50 | 51 | result.Remove(result.Length - 1, 1); //remove the last semicolon! 52 | 53 | return result.ToString(); 54 | } 55 | } 56 | 57 | } 58 | 59 | /* 60 | Crop the input video to out_w:out_h:x:y:keep_aspect 61 | 62 | 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. 63 | 64 | The out_w, out_h, x, y parameters are expressions containing the following constants: 65 | 66 | ‘x, y’ 67 | the computed values for x and y. They are evaluated for each new frame. 68 | 69 | ‘in_w, in_h’ 70 | the input width and height 71 | 72 | ‘iw, ih’ 73 | same as in_w and in_h 74 | 75 | ‘out_w, out_h’ 76 | the output (cropped) width and height 77 | 78 | ‘ow, oh’ 79 | same as out_w and out_h 80 | 81 | ‘a’ 82 | same as iw / ih 83 | 84 | ‘sar’ 85 | input sample aspect ratio 86 | 87 | ‘dar’ 88 | input display aspect ratio, it is the same as (iw / ih) * sar 89 | 90 | ‘hsub, vsub’ 91 | horizontal and vertical chroma subsample values. For example for the pixel format "yuv422p" hsub is 2 and vsub is 1. 92 | 93 | ‘n’ 94 | the number of input frame, starting from 0 95 | 96 | ‘pos’ 97 | the position in the file of the input frame, NAN if unknown 98 | 99 | ‘t’ 100 | timestamp expressed in seconds, NAN if the input timestamp is unknown 101 | 102 | 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. 103 | 104 | The default value of out_w is "in_w", and the default value of out_h is "in_h". 105 | 106 | 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. 107 | 108 | 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. 109 | 110 | 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. 111 | 112 | The expression for x may depend on y, and the expression for y may depend on x. 113 | 114 | Follow some examples: 115 | 116 | 117 | # crop the central input area with size 100x100 118 | crop=100:100 119 | 120 | # crop the central input area with size 2/3 of the input video 121 | "crop=2/3*in_w:2/3*in_h" 122 | 123 | # crop the input video central square 124 | crop=in_h 125 | 126 | # delimit the rectangle with the top-left corner placed at position 127 | # 100:100 and the right-bottom corner corresponding to the right-bottom 128 | # corner of the input image. 129 | crop=in_w-100:in_h-100:100:100 130 | 131 | # crop 10 pixels from the left and right borders, and 20 pixels from 132 | # the top and bottom borders 133 | "crop=in_w-2*10:in_h-2*20" 134 | 135 | # keep only the bottom right quarter of the input image 136 | "crop=in_w/2:in_h/2:in_w/2:in_h/2" 137 | 138 | # crop height for getting Greek harmony 139 | "crop=in_w:1/PHI*in_w" 140 | 141 | # trembling effect 142 | "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)" 143 | 144 | # erratic camera effect depending on timestamp 145 | "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)" 146 | 147 | # set x depending on the value of y 148 | "crop=in_w/2:in_h/2:y:10+10*sin(n/10)" 149 | */ 150 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/DrawBoxVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Java.IO; 3 | using Microsoft.Win32.SafeHandles; 4 | 5 | namespace XamarinAndroidFFmpeg 6 | { 7 | 8 | 9 | using FileStream = System.IO.FileStream; 10 | using Context = Android.Content.Context; 11 | using Bitmap = Android.Graphics.Bitmap; 12 | using Config = Android.Graphics.Bitmap.Config; 13 | using Canvas = Android.Graphics.Canvas; 14 | using Color = Android.Graphics.Color; 15 | using Paint = Android.Graphics.Paint; 16 | 17 | public class DrawBoxVideoFilter : OverlayVideoFilter 18 | { 19 | 20 | public int x; 21 | public int y; 22 | public int width; 23 | public int height; 24 | public string color; 25 | 26 | public DrawBoxVideoFilter(int x, int y, int width, int height, int alpha, string color, string tmpDir) 27 | { 28 | this.x = x; 29 | this.y = y; 30 | this.width = width; 31 | this.height = height; 32 | this.color = color; 33 | 34 | if (alpha < 0 || alpha > 255) 35 | { 36 | throw new System.ArgumentException("Alpha must be an integer betweeen 0 and 255"); 37 | } 38 | Paint paint = new Paint(); 39 | paint.Alpha = alpha; 40 | 41 | 42 | Bitmap bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888); 43 | bitmap.EraseColor(Color.ParseColor(color)); 44 | Bitmap temp_box = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888); 45 | Canvas canvas = new Canvas(temp_box); 46 | canvas.DrawBitmap(bitmap, 0, 0, paint); 47 | 48 | File outputFile; 49 | outputFile = File.CreateTempFile("box_" + width + height + color, ".png", new File(tmpDir)); 50 | 51 | // TODO: Warning - risky and untested, trying to jump between java.lang.io and system.io using a handle 52 | var os = new FileStream(outputFile.Handle, System.IO.FileAccess.ReadWrite); 53 | temp_box.Compress(Bitmap.CompressFormat.Png, 100, os); 54 | overlayFile = outputFile; 55 | xParam = Convert.ToString(x); 56 | yParam = Convert.ToString(y); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/DrawTextVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Java.IO; 3 | 4 | namespace XamarinAndroidFFmpeg 5 | { 6 | 7 | public class DrawTextVideoFilter : VideoFilter 8 | { 9 | 10 | private string mX; 11 | private string mY; 12 | private string mText; 13 | private string mFontColor; 14 | private int mFontSize; 15 | private File mFileFont; 16 | private int mBox; 17 | private string mBoxColor; 18 | 19 | public const string X_CENTERED = "(w-text_w)/2"; 20 | public const string Y_CENTERED = "(h-text_h-line_h)/2"; 21 | 22 | public const string X_LEFT = "0"; 23 | public const string Y_BOTTOM = "(h-text_h-line_h)"; 24 | 25 | public DrawTextVideoFilter(string text) 26 | { 27 | mX = X_CENTERED; 28 | mY = Y_CENTERED; 29 | 30 | mText = text; 31 | mFontColor = "white"; 32 | mFontSize = 36; 33 | mFileFont = new File("/system/fonts/Roboto-Regular.ttf"); 34 | if (!mFileFont.Exists()) 35 | { 36 | mFileFont = new File("/system/fonts/DroidSerif-Regular.ttf"); 37 | } 38 | 39 | mBox = 1; 40 | mBoxColor = "black@0.5"; //0x00000000@1 41 | 42 | } 43 | 44 | public DrawTextVideoFilter(string text, string x, string y, string fontColor, int fontSize, File fontFile, bool showBox, string boxColor, string boxOpacity) 45 | { 46 | mX = x; 47 | mY = y; 48 | 49 | mText = text; 50 | mFontColor = fontColor; 51 | mFontSize = fontSize; 52 | 53 | mFileFont = fontFile; 54 | 55 | mBox = showBox? 1 : 0; 56 | mBoxColor = boxColor + '@' + boxOpacity; 57 | 58 | } 59 | 60 | public override string FilterString 61 | { 62 | get 63 | { 64 | 65 | StringBuilder result = new StringBuilder(); 66 | result.Append("drawtext="); 67 | result.Append("fontfile='").Append(mFileFont.AbsolutePath).Append("':"); 68 | result.Append("text='").Append(mText).Append("':"); 69 | result.Append("x=").Append(mX).Append(":"); 70 | result.Append("y=").Append(mY).Append(":"); 71 | result.Append("fontcolor=").Append(mFontColor).Append(":"); 72 | result.Append("fontsize=").Append(mFontSize).Append(":"); 73 | result.Append("box=").Append(mBox).Append(":"); 74 | result.Append("boxcolor=").Append(mBoxColor); 75 | 76 | return result.ToString(); 77 | } 78 | } 79 | 80 | } 81 | 82 | /* 83 | * //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"; 84 | 85 | File fontFile = new File("/system/fonts/Roboto-Regular.ttf"); 86 | if (!fontFile.exists()) 87 | fontFile = new File("/system/fonts/DroidSans.ttf"); 88 | 89 | mdout.videoFilter = "drawtext=fontfile='" + fontFile.getAbsolutePath() + "':text='this is awesome':x=(main_w-text_w)/2:y=50:fontsize=24:fontcolor=white"; 90 | */ 91 | 92 | /// 93 | /// 94 | /// 95 | /// /system/fonts 96 | /// 97 | /// AndroidClock.ttf 98 | /// AndroidClock_Highlight.ttf 99 | /// AndroidClock_Solid.ttf 100 | /// AndroidEmoji.ttf 101 | /// AnjaliNewLipi-light.ttf 102 | /// Clockopia.ttf 103 | /// DroidNaskh-Regular-SystemUI.ttf 104 | /// DroidNaskh-Regular.ttf 105 | /// DroidSans-Bold.ttf 106 | /// DroidSans.ttf 107 | /// DroidSansArmenian.ttf 108 | /// DroidSansDevanagari-Regular.ttf 109 | /// DroidSansEthiopic-Regular.ttf 110 | /// DroidSansFallback.ttf 111 | /// DroidSansGeorgian.ttf 112 | /// DroidSansHebrew-Bold.ttf 113 | /// DroidSansHebrew-Regular.ttf 114 | /// DroidSansMono.ttf 115 | /// DroidSansTamil-Bold.ttf 116 | /// DroidSansTamil-Regular.ttf 117 | /// DroidSansThai.ttf 118 | /// DroidSerif-Bold.ttf 119 | /// DroidSerif-BoldItalic.ttf 120 | /// DroidSerif-Italic.ttf 121 | /// DroidSerif-Regular.ttf 122 | /// Lohit-Bengali.ttf 123 | /// Lohit-Kannada.ttf 124 | /// Lohit-Telugu.ttf 125 | /// MTLmr3m.ttf 126 | /// Roboto-Bold.ttf 127 | /// Roboto-BoldItalic.ttf 128 | /// Roboto-Italic.ttf 129 | /// Roboto-Light.ttf 130 | /// Roboto-LightItalic.ttf 131 | /// Roboto-Regular.ttf 132 | /// RobotoCondensed-Bold.ttf 133 | /// RobotoCondensed-BoldItalic.ttf 134 | /// RobotoCondensed-Italic.ttf 135 | /// RobotoCondensed-Regular.ttf 136 | /// 137 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/FadeVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace XamarinAndroidFFmpeg 4 | { 5 | 6 | public class FadeVideoFilter : VideoFilter 7 | { 8 | 9 | private string mAction; //in our out 10 | private int mStart; 11 | private int mLength; 12 | 13 | public FadeVideoFilter(string action, int start, int length) 14 | { 15 | mAction = action; 16 | mStart = start; 17 | mLength = length; 18 | } 19 | 20 | public override string FilterString 21 | { 22 | get 23 | { 24 | 25 | StringBuilder result = new StringBuilder(); 26 | result.Append("fade="); 27 | result.Append (mAction).Append (':').Append (mStart).Append (":").Append (mLength); 28 | 29 | return result.ToString(); 30 | } 31 | } 32 | } 33 | 34 | ///fade=in:0:25, fade=out:975:25 35 | 36 | 37 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/OverlayVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Java.IO; 3 | 4 | namespace XamarinAndroidFFmpeg 5 | { 6 | 7 | /// 8 | /// @class overlay overlay one image or video on top of another 9 | /// 10 | /// @desc x is the x coordinate of the overlayed video on the main video, 11 | /// y is the y coordinate. The parameters are expressions containing 12 | /// the following parameters: 13 | ///
14 | 	///      	main_w, main_h
15 | 	///          main input width and height
16 | 	/// 
17 | 	///       W, H
18 | 	///           same as main_w and main_h
19 | 	/// 
20 | 	///       overlay_w, overlay_h
21 | 	///           overlay input width and height
22 | 	/// 
23 | 	///       w, h
24 | 	///           same as overlay_w and overlay_h
25 | 	/// 
26 | /// @examples 27 | ///
draw the overlay at 10 pixels from the bottom right
28 | 	/// corner of the main video.
29 | 	/// 		main_w-overlay_w-10
30 | 	/// 		main_h-overlay_h-10
31 | 	/// draw the overlay in the bottom left corner of the input
32 | 	///  10
33 | 	///  main_h-overlay_h-10 [out]
34 | /// 35 | ///
36 | public class OverlayVideoFilter : VideoFilter 37 | { 38 | 39 | public File overlayFile; 40 | public string xParam, yParam; 41 | 42 | public OverlayVideoFilter() 43 | { 44 | 45 | } 46 | 47 | public OverlayVideoFilter(File fileMovieOverlay, int x, int y) 48 | { 49 | this.overlayFile = fileMovieOverlay; 50 | this.xParam = Convert.ToString(x); 51 | this.yParam = Convert.ToString(y); 52 | } 53 | 54 | public OverlayVideoFilter(File fileMovieOverlay, string xExpression, string yExpression) 55 | { 56 | this.overlayFile = fileMovieOverlay; 57 | this.xParam = xExpression; 58 | this.yParam = yExpression; 59 | } 60 | 61 | public override string FilterString 62 | { 63 | get 64 | { 65 | if (overlayFile != null) 66 | { 67 | return "movie=" + overlayFile.AbsolutePath + " [logo];[in][logo] " + "overlay=" + xParam + ":" + yParam + " [out]"; 68 | } 69 | else 70 | { 71 | return ""; 72 | } 73 | 74 | } 75 | } 76 | } 77 | 78 | //"\"movie="+ overlayImage.getPath() +" [logo];[in][logo] overlay=0:0 [out]\"", 79 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/RedactVideoFilter.cs: -------------------------------------------------------------------------------- 1 | using Java.IO; 2 | 3 | namespace XamarinAndroidFFmpeg 4 | { 5 | 6 | public class RedactVideoFilter : VideoFilter 7 | { 8 | 9 | private File fileRedactList; 10 | 11 | public RedactVideoFilter(File fileRedactList) 12 | { 13 | this.fileRedactList = fileRedactList; 14 | } 15 | 16 | public override string FilterString 17 | { 18 | get 19 | { 20 | if (fileRedactList != null) 21 | { 22 | return "redact=" + fileRedactList.AbsolutePath; 23 | } 24 | else 25 | { 26 | return ""; 27 | } 28 | 29 | } 30 | } 31 | } 32 | 33 | //redact=blurbox.txt [out] [d], [d]nullsink 34 | //"redact=" + Environment.getExternalStorageDirectory().getPath() + "/" + PACKAGENAME + "/redact_unsort.txt", 35 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/TransposeVideoFilter.cs: -------------------------------------------------------------------------------- 1 | namespace XamarinAndroidFFmpeg 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 : VideoFilter 11 | { 12 | private int mTranspose = -1; 13 | 14 | public const int NINETY_COUNTER_CLOCKWISE_AND_VERTICAL_FLIP = 0; 15 | public const int NINETY_CLOCKWISE = 1; 16 | public const int NINETY_COUNTER_CLOCKWISE = 2; 17 | public const int NINETY_CLOCKWISE_AND_VERTICAL_FLIP = 3; 18 | 19 | public TransposeVideoFilter(int transpose) 20 | { 21 | mTranspose = transpose; 22 | } 23 | 24 | public override string FilterString 25 | { 26 | get 27 | { 28 | return "transpose=" + mTranspose; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/filters/VideoFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | 4 | namespace XamarinAndroidFFmpeg 5 | { 6 | 7 | 8 | public abstract class VideoFilter 9 | { 10 | 11 | public abstract string FilterString {get;} 12 | 13 | public static string Build(List listFilters) 14 | { 15 | StringBuilder result = new StringBuilder(); 16 | 17 | IEnumerator it = listFilters.GetEnumerator(); 18 | VideoFilter vf; 19 | 20 | while (it.MoveNext()) 21 | { 22 | vf = it.Current; 23 | result.Append(vf.FilterString).Append(", "); 24 | } 25 | 26 | var res = result.ToString(); 27 | if (res.Substring (res.Length - 2) == ", ") { 28 | res = res.Substring (0, res.Length - 2); 29 | } 30 | 31 | //return @"'" + res + @"'"; 32 | return res; 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/test/ConcatTest.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using Java.IO; 4 | // 5 | //namespace FFMpegLib 6 | //{ 7 | // 8 | // 9 | // 10 | // using SoxController = net.sourceforge.sox.SoxController; 11 | // 12 | // 13 | // public class ConcatTest 14 | // { 15 | // public static void test(string videoRoot, string fileTmpPath, string fileOut, double fadeLen) 16 | // { 17 | // File fileTmp = new File(fileTmpPath); 18 | // File fileAppRoot = new File(""); 19 | // File fileVideoRoot = new File(videoRoot); 20 | // 21 | // FFMpegHelpers fc = new FFMpegHelpers(null, fileTmp); 22 | // SoxController sxCon = new SoxController(null, fileAppRoot, null); 23 | // 24 | // List listVideos = new List(); 25 | // 26 | // string[] fileList = fileVideoRoot.List(); 27 | // foreach (string fileVideo in fileList) 28 | // { 29 | // if (fileVideo.EndsWith("mp4")) 30 | // { 31 | // Clip clip = new Clip(); 32 | // clip.path = (new File(fileVideoRoot,fileVideo)).CanonicalPath; 33 | // 34 | // fc.getInfo(clip); 35 | // 36 | // clip.duration = clip.duration - fadeLen; 37 | // listVideos.Add(clip); 38 | // 39 | // 40 | // } 41 | // } 42 | // 43 | // Clip clipOut = new Clip(); 44 | // clipOut.path = (new File(fileOut)).CanonicalPath; 45 | // 46 | // fc.concatAndTrimFilesMP4Stream(listVideos, clipOut, false, false, new ShellCallbackAnonymousInnerClassHelper()); 47 | // 48 | // 49 | // 50 | // } 51 | // 52 | // private class ShellCallbackAnonymousInnerClassHelper : ShellUtils.IShellCallback 53 | // { 54 | // public ShellCallbackAnonymousInnerClassHelper() 55 | // { 56 | // } 57 | // 58 | // 59 | // public virtual void ShellOut(string shellLine) 60 | // { 61 | // 62 | // Console.WriteLine("fc>" + shellLine); 63 | // } 64 | // 65 | // public virtual void ProcessComplete(int exitValue) 66 | // { 67 | // 68 | // if (exitValue < 0) 69 | // { 70 | // Console.Error.WriteLine("concat non-zero exit: " + exitValue); 71 | // } 72 | // } 73 | // } 74 | // } 75 | // 76 | //} -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/test/ConvertTest.cs: -------------------------------------------------------------------------------- 1 | //namespace FFMpegLib 2 | //{ 3 | // 4 | // public class ConvertTest 5 | // { 6 | // 7 | // } 8 | // 9 | //} -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/test/CrossfadeTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | //using System; 3 | //using System.Collections.Generic; 4 | // 5 | //namespace FFMpegLib 6 | //{ 7 | // 8 | // 9 | // using CrossfadeCat = net.sourceforge.sox.CrossfadeCat; 10 | // using SoxController = net.sourceforge.sox.SoxController; 11 | // 12 | // 13 | // public class CrossfadeTest 14 | // { 15 | // 16 | // 17 | // public static void test(string videoRoot, string fileTmpPath, string clipOutPath, double fadeLen) 18 | // { 19 | // File fileTmp = new File(fileTmpPath); 20 | // File fileAppRoot = new File(""); 21 | // File fileVideoRoot = new File(videoRoot); 22 | // 23 | // string fadeType = "l"; 24 | // int sampleRate = 22050; 25 | // int channels = 1; 26 | // 27 | // FFMpegHelpers ffmpegc = new FFMpegHelpers(null, fileTmp); 28 | // 29 | // Clip clipOut = new Clip(); 30 | // clipOut.path = clipOutPath; 31 | // clipOut.audioCodec = "aac"; 32 | // clipOut.audioBitrate = 56; 33 | // 34 | // 35 | // List listVideos = new List(); 36 | // 37 | // string[] fileList = fileVideoRoot.list(); 38 | // foreach (string fileVideo in fileList) 39 | // { 40 | // if (fileVideo.EndsWith("mp4")) 41 | // { 42 | // Clip clip = new Clip(); 43 | // clip.path = (new File(fileVideoRoot,fileVideo)).CanonicalPath; 44 | // //clip.startTime = "00:00:03"; 45 | // //clip.duration = "00:00:02"; 46 | // 47 | // ffmpegc.getInfo(clip); 48 | // 49 | // //System.out.println("clip " + fileVideo + " duration=" + clip.duration); 50 | // 51 | // listVideos.Add(clip); 52 | // 53 | // } 54 | // } 55 | // 56 | // //now add 1 second cross fade to each audio file and cat them together 57 | // SoxController sxCon = new SoxController(null, fileAppRoot, new ShellCallbackAnonymousInnerClassHelper()); 58 | // 59 | // List alAudio = new List(); 60 | // 61 | // //convert each input file to a WAV so we can use Sox to process 62 | // int wavIdx = 0; 63 | // 64 | // foreach (Clip mediaIn in listVideos) 65 | // { 66 | // if (System.IO.Directory.Exists(mediaIn.path) || System.IO.File.Exists(mediaIn.path)) 67 | // { 68 | // 69 | // if (mediaIn.audioCodec == null) 70 | // { 71 | // //there is no audio track so let's generate silence 72 | // 73 | // 74 | // } 75 | // else 76 | // { 77 | // Clip audioOut = ffmpegc.convertToWaveAudio(mediaIn, (new File(fileTmp, wavIdx + ".wav")).CanonicalPath,sampleRate,channels, new ShellCallbackAnonymousInnerClassHelper2()); 78 | // 79 | // alAudio.Add(audioOut); 80 | // 81 | // /* 82 | // float duration = (float) sxCon.getLength(new File(audioOut.path).getCanonicalPath()); 83 | // 84 | // if (mediaIn.duration == null) 85 | // { 86 | // mediaIn.duration = string.format(Locale.US, "%f", duration); 87 | // }*/ 88 | // ffmpegc.getInfo(mediaIn); 89 | // 90 | // 91 | // wavIdx++; 92 | // } 93 | // } 94 | // else 95 | // { 96 | // throw new FileNotFoundException(mediaIn.path); 97 | // } 98 | // } 99 | // 100 | // if (alAudio.Count > 0) 101 | // { 102 | // string fileOut = alAudio[0].path; 103 | // 104 | // Console.WriteLine("mix length=" + sxCon.getLength(fileOut)); 105 | // 106 | // for (int i = 1; i < alAudio.Count; i++) 107 | // { 108 | // 109 | // File fileAdd = new File(alAudio[i].path); 110 | // 111 | // CrossfadeCat xCat = new CrossfadeCat(sxCon, fileOut, fileAdd.CanonicalPath, fadeLen, fileOut); 112 | // xCat.start(); 113 | // 114 | // fileAdd.deleteOnExit(); 115 | // 116 | // Console.WriteLine("mix length=" + sxCon.getLength(fileOut)); 117 | // 118 | // } 119 | // 120 | // 121 | // //1 second fade in and fade out, t = triangle or linear 122 | // //String fadeLenStr = sxCon.formatTimePeriod(fadeLen); 123 | // 124 | // 125 | // 126 | // string fadeFileOut = sxCon.fadeAudio(fileOut, fadeType, fadeLen, sxCon.getLength(fileOut) - fadeLen, fadeLen); 127 | // 128 | // //now export the final file to our requested output format mOut.mimeType = AppConstants.MimeTypes.MP4_AUDIO; 129 | // 130 | // Clip mdFinalIn = new Clip(); 131 | // mdFinalIn.path = fadeFileOut; 132 | // 133 | // 134 | // Console.WriteLine("final duration: " + sxCon.getLength(fadeFileOut)); 135 | // 136 | // Clip exportOut = ffmpegc.convertTo3GPAudio(mdFinalIn, clipOut, new ShellCallbackAnonymousInnerClassHelper3()); 137 | // } 138 | // } 139 | // 140 | // private class ShellCallbackAnonymousInnerClassHelper : ShellUtils.IShellCallback 141 | // { 142 | // public ShellCallbackAnonymousInnerClassHelper() 143 | // { 144 | // } 145 | // 146 | // 147 | // public virtual void ShellOut(string shellLine) 148 | // { 149 | // 150 | // // System.out.println("sxCon> " + shellLine); 151 | // 152 | // } 153 | // 154 | // public virtual void ProcessComplete(int exitValue) 155 | // { 156 | // 157 | // 158 | // if (exitValue != 0) 159 | // { 160 | // Console.Error.WriteLine("sxCon> EXIT=" + exitValue); 161 | // 162 | // Exception re = new Exception("non-zero exit: " + exitValue); 163 | // Console.WriteLine(re.ToString()); 164 | // Console.Write(re.StackTrace); 165 | // throw re; 166 | // } 167 | // 168 | // } 169 | // } 170 | // 171 | // private class ShellCallbackAnonymousInnerClassHelper2 : ShellUtils.IShellCallback 172 | // { 173 | // public ShellCallbackAnonymousInnerClassHelper2() 174 | // { 175 | // } 176 | // 177 | // 178 | // public virtual void ShellOut(string shellLine) 179 | // { 180 | // 181 | // // System.out.println("convertToWav> " + shellLine); 182 | // 183 | // } 184 | // 185 | // public virtual void ProcessComplete(int exitValue) 186 | // { 187 | // 188 | // if (exitValue != 0) 189 | // { 190 | // 191 | // Console.Error.WriteLine("convertToWav> EXIT=" + exitValue); 192 | // 193 | // Exception re = new Exception("non-zero exit: " + exitValue); 194 | // Console.WriteLine(re.ToString()); 195 | // Console.Write(re.StackTrace); 196 | // throw re; 197 | // } 198 | // } 199 | // } 200 | // 201 | // private class ShellCallbackAnonymousInnerClassHelper3 : ShellUtils.IShellCallback 202 | // { 203 | // public ShellCallbackAnonymousInnerClassHelper3() 204 | // { 205 | // } 206 | // 207 | // 208 | // public virtual void ShellOut(string shellLine) 209 | // { 210 | // 211 | // //System.out.println("convertTo3gp> " + shellLine); 212 | // } 213 | // 214 | // public virtual void ProcessComplete(int exitValue) 215 | // { 216 | // 217 | // if (exitValue < 0) 218 | // { 219 | // Exception re = new Exception("non-zero exit: " + exitValue); 220 | // Console.WriteLine(re.ToString()); 221 | // Console.Write(re.StackTrace); 222 | // throw re; 223 | // } 224 | // } 225 | // } 226 | // 227 | // } 228 | // 229 | //} 230 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/test/FilterTest.cs: -------------------------------------------------------------------------------- 1 | //using System.Collections.Generic; 2 | //using Java.IO; 3 | // 4 | //namespace FFMpegLib 5 | //{ 6 | // 7 | // 8 | // using CropVideoFilter = FFMpegLib.CropVideoFilter; 9 | // using DrawBoxVideoFilter = FFMpegLib.DrawBoxVideoFilter; 10 | // using DrawTextVideoFilter = FFMpegLib.DrawTextVideoFilter; 11 | // using FadeVideoFilter = FFMpegLib.FadeVideoFilter; 12 | // using TransposeVideoFilter = FFMpegLib.TransposeVideoFilter; 13 | // using VideoFilter = FFMpegLib.VideoFilter; 14 | // 15 | // using Activity = Android.App.Activity; 16 | // using Context = Android.Content.Context; 17 | // 18 | // public class FilterTest 19 | // { 20 | // 21 | // 22 | // public static void test(string title, string textColor, File fileFont, string boxColor, string opacity) 23 | // { 24 | // List listFilters = new List(); 25 | // 26 | // File fileDir = new File("tmp"); 27 | // fileDir.mkdir(); 28 | // 29 | // int height = 480; 30 | // int width = 720; 31 | // int lowerThird = height / 3; 32 | // DrawBoxVideoFilter vf = new DrawBoxVideoFilter(0,height - lowerThird,width,lowerThird,100,"blue",fileDir); 33 | // 34 | // DrawTextVideoFilter vfTitle = new DrawTextVideoFilter(title, DrawTextVideoFilter.X_CENTERED,DrawTextVideoFilter.Y_CENTERED, textColor, 38, fileFont, true, boxColor, opacity); 35 | // 36 | // float fps = 29.97f; 37 | // int fadeTime = (int)(fps * 3); 38 | // //fades in first 3 seconds 39 | // FadeVideoFilter vfFadeIn = new FadeVideoFilter("in",0,fadeTime); 40 | // 41 | // //fades out last 50 frames 42 | // int totalFrames = (int)(14.37 * 29.97); 43 | // FadeVideoFilter vfFadeOut = new FadeVideoFilter("out",totalFrames - fadeTime,fadeTime); 44 | // 45 | // //crops video in 100 pixels on each side 46 | // CropVideoFilter vfCrop = new CropVideoFilter("in_w-100","in_h-100","100","100"); 47 | // 48 | // //rotates video 90 degress clockwise 49 | // TransposeVideoFilter vfTranspose = new TransposeVideoFilter(TransposeVideoFilter.NINETY_CLOCKWISE); 50 | // 51 | // listFilters.Add(vfTranspose); 52 | // listFilters.Add(vfCrop); 53 | // listFilters.Add(vfTitle); 54 | // listFilters.Add(vfFadeIn); 55 | // listFilters.Add(vfFadeOut); 56 | // 57 | // 58 | // 59 | // fileDir.deleteOnExit(); 60 | // } 61 | // } 62 | // 63 | //} -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/test/MixTest.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | // 3 | //namespace FFMpegLib 4 | //{ 5 | // 6 | // 7 | // public class MixTest 8 | // { 9 | // public static void test(string fileTmpPath, string videoClipPath, string audioClipPath, Clip clipOut) 10 | // { 11 | // File fileTmp = new File(fileTmpPath); 12 | // File fileAppRoot = new File(""); 13 | // 14 | // FFMpegHelpers fc = new FFMpegHelpers(null, fileTmp); 15 | // 16 | // Clip clipVideo = new Clip(videoClipPath); 17 | // //fc.getInfo(clipVideo); 18 | // 19 | // Clip clipAudio = new Clip(audioClipPath); 20 | // //fc.getInfo(clipAudio); 21 | // 22 | // fc.combineAudioAndVideo(clipVideo, clipAudio, clipOut, new ShellCallbackAnonymousInnerClassHelper()); 23 | // 24 | // } 25 | // 26 | // private class ShellCallbackAnonymousInnerClassHelper : ShellUtils.IShellCallback 27 | // { 28 | // public ShellCallbackAnonymousInnerClassHelper() 29 | // { 30 | // } 31 | // 32 | // 33 | // public virtual void ShellOut(string shellLine) 34 | // { 35 | // // System.out.println("MIX> " + shellLine); 36 | // } 37 | // 38 | // public virtual void ProcessComplete(int exitValue) 39 | // { 40 | // 41 | // if (exitValue != 0) 42 | // { 43 | // Console.Error.WriteLine("concat non-zero exit: " + exitValue); 44 | // } 45 | // } 46 | // } 47 | // 48 | // } 49 | // 50 | //} -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/ffmpeg/test/Tests.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | // 3 | //namespace FFMpegLib 4 | //{ 5 | // 6 | // 7 | // public class Tests 8 | // { 9 | // 10 | // /// 11 | // public static void Main(string[] args) 12 | // { 13 | // 14 | // 15 | // 16 | // string[] testpaths = new string[] {"/home/n8fr8/Desktop/sm3"}; 17 | // 18 | // int idx = -1; 19 | // 20 | // double fadeLen = 1; 21 | // 22 | // foreach (string testpath in testpaths) 23 | // { 24 | // idx++; 25 | // 26 | // Console.WriteLine("************************************"); 27 | // Console.WriteLine("CONCAT TEST: " + testpath); 28 | // 29 | // File fileVideoOutput = new File("/tmp/test" + idx + ".mp4"); 30 | // fileVideoOutput.delete(); 31 | // 32 | // ConcatTest.test(testpath, "/tmp", fileVideoOutput.CanonicalPath, fadeLen); 33 | // 34 | // if (!fileVideoOutput.exists()) 35 | // { 36 | // Console.WriteLine("FAIL!! > output file did not get created: " + fileVideoOutput.CanonicalPath); 37 | // continue; 38 | // } 39 | // else 40 | // { 41 | // Console.WriteLine("SUCCESS!! > " + fileVideoOutput.CanonicalPath); 42 | // } 43 | // 44 | // Console.WriteLine("************************************"); 45 | // Console.WriteLine("CROSSFADE TEST: " + testpath); 46 | // 47 | // File fileAudioOutput = new File("/tmp/test" + idx + ".3gp"); 48 | // fileAudioOutput.delete(); 49 | // CrossfadeTest.test(testpath, "/tmp", fileAudioOutput.CanonicalPath,fadeLen); 50 | // if (!fileAudioOutput.exists()) 51 | // { 52 | // Console.WriteLine("FAIL!! > output file did not get created: " + fileAudioOutput.CanonicalPath); 53 | // continue; 54 | // } 55 | // else 56 | // { 57 | // Console.WriteLine("SUCCESS!! > " + fileAudioOutput.CanonicalPath); 58 | // } 59 | // 60 | // Console.WriteLine("************************************"); 61 | // Console.WriteLine("MIX TEST: " + testpath); 62 | // 63 | // File fileMix = new File("/tmp/test" + idx + "mix.mp4"); 64 | // fileMix.delete(); 65 | // Clip clipMixOut = new Clip(fileMix.CanonicalPath); 66 | // MixTest.test("/tmp", fileVideoOutput.CanonicalPath, fileAudioOutput.CanonicalPath, clipMixOut); 67 | // if (!fileMix.exists()) 68 | // { 69 | // Console.WriteLine("FAIL!! > output file did not get created: " + fileMix.CanonicalPath); 70 | // } 71 | // else 72 | // { 73 | // Console.WriteLine("SUCCESS!! > " + fileMix.CanonicalPath); 74 | // } 75 | // 76 | // 77 | // } 78 | // 79 | // Console.WriteLine("**********************"); 80 | // Console.WriteLine("*******FIN**********"); 81 | // 82 | // } 83 | // 84 | // } 85 | // 86 | //} -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/sox/CrossfadeCat.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace SoxTools 5 | { 6 | 7 | 8 | /// 9 | /// Concatenates two files together with a crossfade of user 10 | /// defined mClipLength. 11 | /// 12 | /// It is a Java port of the scripts/crossfade_cat.sh script 13 | /// in the sox source tree. 14 | /// 15 | /// Original script by Kester Clegg, with modifications by Chris 16 | /// Bagwell. 17 | /// 18 | /// @author Abel Luck 19 | /// 20 | /// 21 | // TODO make runnable? 22 | public class CrossfadeCat 23 | { 24 | private const string TAG = "SOX-XFADE"; 25 | private SoxHelpers _soxHelper; 26 | private string mFirstFile; 27 | private string mSecondFile; 28 | private double mFadeLength; 29 | private string mFinalMix; 30 | 31 | public CrossfadeCat(SoxHelpers soxHelper, string firstFile, string secondFile, double fadeLength, string outFile) 32 | { 33 | _soxHelper = soxHelper; 34 | mFirstFile = firstFile; 35 | mSecondFile = secondFile; 36 | mFadeLength = fadeLength; 37 | mFinalMix = outFile; 38 | 39 | //double mClipLength = mController.getLength(mFirstFile); 40 | } 41 | 42 | public virtual bool start() 43 | { 44 | // find mClipLength of first file 45 | 46 | 47 | // Obtain trimLength seconds of fade out position from the first File 48 | double firstFileLength = _soxHelper.GetLength(mFirstFile); 49 | double trimLength = firstFileLength - mFadeLength; 50 | 51 | string trimmedOne = _soxHelper.TrimAudio(mFirstFile, trimLength, mFadeLength); 52 | 53 | if (trimmedOne == null) 54 | { 55 | throw new IOException("audio trim did not complete: " + mFirstFile); 56 | } 57 | 58 | // We assume a fade out is needed (i.e., firstFile doesn't already fade out) 59 | 60 | string fadedOne = _soxHelper.FadeAudio(trimmedOne, "t", 0, mFadeLength, mFadeLength); 61 | if (fadedOne == null) 62 | { 63 | throw new IOException("audio fade did not complete: " + trimmedOne); 64 | } 65 | 66 | // Get crossfade section from the second file 67 | string trimmedTwo = _soxHelper.TrimAudio(mSecondFile, 0, mFadeLength); 68 | if (trimmedTwo == null) 69 | { 70 | throw new IOException("audio trim did not complete: " + mSecondFile); 71 | } 72 | 73 | string fadedTwo = _soxHelper.FadeAudio(trimmedTwo, "t", mFadeLength, -1, -1); 74 | if (fadedTwo == null) 75 | { 76 | throw new IOException("audio fade did not complete: " + trimmedTwo); 77 | } 78 | 79 | // Mix crossfaded files together at full volume 80 | List files = new List(); 81 | files.Add(fadedOne); 82 | files.Add(fadedTwo); 83 | 84 | string crossfaded = (new Java.IO.File(mFirstFile)).CanonicalPath + "-x-" + (new System.IO.FileInfo(mSecondFile)).Name + ".wav"; 85 | crossfaded = _soxHelper.CombineMix(files, crossfaded); 86 | if (crossfaded == null) 87 | { 88 | throw new IOException("crossfade did not complete"); 89 | } 90 | 91 | // Trim off crossfade sections from originals 92 | string trimmedThree = _soxHelper.TrimAudio(mFirstFile, 0, trimLength); 93 | if (trimmedThree == null) 94 | { 95 | throw new IOException("crossfade trim beginning did not complete"); 96 | } 97 | 98 | string trimmedFour = _soxHelper.TrimAudio(mSecondFile, mFadeLength, -1); 99 | if (trimmedFour == null) 100 | { 101 | throw new IOException("crossfade trim end did not complete"); 102 | } 103 | 104 | // Combine into final mix 105 | files.Clear(); 106 | files.Add(trimmedThree); 107 | files.Add(crossfaded); 108 | files.Add(trimmedFour); 109 | mFinalMix = _soxHelper.Combine(files, mFinalMix); 110 | 111 | if (mFinalMix == null) 112 | { 113 | throw new IOException("final mix did not complete"); 114 | } 115 | 116 | return true; 117 | } 118 | 119 | 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Helpers/sox/SoxHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Java.Lang; 5 | using Java.IO; 6 | using XamarinAndroidFFmpeg; 7 | using System.Windows.Input; 8 | 9 | namespace SoxTools 10 | { 11 | using R = Android.Resource; 12 | 13 | using Context = Android.Content.Context; 14 | using Log = Android.Util.Log; 15 | 16 | public class SoxHelpers 17 | { 18 | private const string TAG = "SOX"; 19 | internal string[] libraryAssets = new string[] {"sox"}; 20 | private string soxBin; 21 | private File fileBinDir; 22 | private FFMpegCallbacks _globalCallback; 23 | private Context _context; 24 | 25 | public SoxHelpers(Context context, int soxResId, Java.IO.File fileAppRoot, FFMpegCallbacks callback) 26 | { 27 | _globalCallback = callback; 28 | _context = context; 29 | InstallBinaries(soxResId, false); 30 | fileBinDir = (new File(soxBin)).ParentFile; 31 | } 32 | 33 | 34 | public void InstallBinaries(int soxResId, bool overwrite) 35 | { 36 | soxBin = InstallBinary(soxResId, "sox", overwrite); 37 | } 38 | 39 | public string BinaryPath 40 | { 41 | get 42 | { 43 | return soxBin; 44 | } 45 | } 46 | 47 | private string InstallBinary(int resId, string filename, bool upgrade) 48 | { 49 | try 50 | { 51 | File f = new File(_context.GetDir("bin", 0), filename); 52 | if (f.Exists()) 53 | { 54 | f.Delete(); 55 | } 56 | CopyRawFile(resId, f.AbsolutePath, "0755"); 57 | return f.CanonicalPath; 58 | } 59 | catch (System.Exception) 60 | { 61 | // Log.e(TAG, "installBinary failed: " + e.LocalizedMessage); 62 | return null; 63 | } 64 | } 65 | 66 | /// 67 | /// Copies a raw resource file, given its ID to the given location 68 | /// context 69 | /// resource id 70 | /// destination file 71 | /// file permissions (E.g.: "755") 72 | /// on error 73 | /// when interrupted 74 | private void CopyRawFile(int resid, string fileFullPath, string mode) 75 | { 76 | 77 | // Write the iptables binary 78 | var outputStream = new System.IO.FileStream(fileFullPath, System.IO.FileMode.Create); 79 | 80 | var inputStream = _context.Resources.OpenRawResource(resid); 81 | var buf = new byte[1024]; 82 | int len; 83 | while ((len = inputStream.Read(buf, 0, buf.Length)) > 0) 84 | { 85 | outputStream.Write(buf, 0, len); 86 | } 87 | outputStream.Close(); 88 | inputStream.Close(); 89 | // Change the permissions 90 | var r = Runtime.GetRuntime (); 91 | r.Exec("chmod " + mode + " " + fileFullPath).WaitFor(); 92 | } 93 | 94 | private class LengthParser : FFMpegCallbacks 95 | { 96 | private readonly SoxHelpers _outerInstance; 97 | 98 | public LengthParser(SoxHelpers outerInstance, FFMpegCallbacks callbacks) : base(callbacks._completedAction, callbacks._messageAction) 99 | { 100 | _outerInstance = outerInstance; 101 | _messageAction = callbacks._messageAction; 102 | _completedAction= callbacks._completedAction; 103 | } 104 | 105 | public double length; 106 | public int retValue = -1; 107 | 108 | public override void ShellOut(string shellLine) 109 | { 110 | if (!shellLine.StartsWith("Length")) 111 | { 112 | return; 113 | } 114 | string[] split = shellLine.Split(':'); 115 | if (split.Length != 2) 116 | { 117 | return; 118 | } 119 | 120 | string lengthStr = split[1].Trim(); 121 | 122 | try 123 | { 124 | length = Convert.ToDouble(lengthStr); 125 | } catch (System.Exception e) { 126 | _messageAction.Execute (e.ToString ()); 127 | _messageAction.Execute (e.StackTrace); 128 | } 129 | } 130 | 131 | public override void ProcessComplete(int exitValue) 132 | { 133 | retValue = exitValue; 134 | base.ProcessComplete (exitValue); 135 | } 136 | } 137 | 138 | /// 139 | /// Retrieve the length of the audio file 140 | /// sox file.wav 2>&1 -n stat | grep Length | cut -d : -f 2 | cut -f 1 141 | /// the length in seconds or null 142 | public double GetLength(string path) 143 | { 144 | List cmd = new List(); 145 | 146 | cmd.Add(soxBin); 147 | cmd.Add(path); 148 | cmd.Add("-n"); 149 | cmd.Add("stat"); 150 | 151 | LengthParser sc = new LengthParser (this, _globalCallback); 152 | 153 | try 154 | { 155 | ExecSox(cmd, sc); 156 | } 157 | catch (System.Exception) 158 | { 159 | return -1; 160 | } 161 | 162 | return sc.length; 163 | } 164 | 165 | /// 166 | /// Discard all audio not between start and length (length = end by default) 167 | /// sox -e signed-integer -b 16 outFile trim 168 | /// 169 | /// (optional) 170 | /// path to trimmed audio 171 | public string TrimAudio(string path, double start, double length) 172 | { 173 | List cmd = new List(); 174 | 175 | File file = new File(path); 176 | string outFile = file.CanonicalPath + "_trimmed.wav"; 177 | cmd.Add(soxBin); 178 | cmd.Add(path); 179 | cmd.Add("-e"); 180 | cmd.Add("signed-integer"); 181 | cmd.Add("-b"); 182 | cmd.Add("16"); 183 | cmd.Add(outFile); 184 | cmd.Add("trim"); 185 | cmd.Add(start + ""); 186 | if (length != -1) 187 | { 188 | cmd.Add(length.ToString() + ""); 189 | } 190 | 191 | int rc = ExecSox (cmd, _globalCallback);; 192 | if (rc != 0) 193 | { 194 | outFile = null; 195 | } 196 | 197 | if (file.Exists()) 198 | { 199 | return outFile; 200 | } 201 | else 202 | { 203 | return null; 204 | } 205 | 206 | } 207 | 208 | /// 209 | /// Fade audio file 210 | /// sox outFile fade 211 | /// 212 | /// 213 | /// specify 0 if no fade in is desired 214 | /// (optional) 215 | /// (optional) 216 | /// @return 217 | public string FadeAudio(string path, string type, double fadeInLength, double stopTime, double fadeOutLength) 218 | { 219 | var curves = new List {"q", "h", "t", "l", "p"}; 220 | 221 | if (!curves.Contains(type)) 222 | { 223 | throw new System.Exception("fadeAudio: passed invalid type: " + type); 224 | 225 | } 226 | 227 | File file = new File(path); 228 | string outFile = file.CanonicalPath + "_faded.wav"; 229 | 230 | List cmd = new List(); 231 | cmd.Add(soxBin); 232 | cmd.Add(path); 233 | cmd.Add(outFile); 234 | cmd.Add("fade"); 235 | cmd.Add(type); 236 | cmd.Add(fadeInLength + ""); 237 | if (stopTime != -1) 238 | { 239 | cmd.Add(stopTime + ""); 240 | } 241 | if (fadeOutLength != -1) 242 | { 243 | cmd.Add(fadeOutLength + ""); 244 | } 245 | 246 | try 247 | { 248 | int rc = ExecSox(cmd, _globalCallback); 249 | if (rc != 0) 250 | { 251 | //Log.e(TAG, "fadeAudio receieved non-zero return code!"); 252 | 253 | outFile = null; 254 | } 255 | } 256 | catch (IOException e) 257 | { 258 | // TODO Auto-generated catch block 259 | _globalCallback._messageAction.Execute(e.ToString()); 260 | _globalCallback._messageAction.Execute(e.StackTrace); 261 | } 262 | catch (InterruptedException e) 263 | { 264 | // TODO Auto-generated catch block 265 | _globalCallback._messageAction.Execute(e.ToString()); 266 | _globalCallback._messageAction.Execute(e.StackTrace); 267 | } 268 | return outFile; 269 | } 270 | 271 | /// 272 | /// Combine and mix audio files 273 | /// sox -m -v 1.0 file[0] -v 1.0 file[1] ... -v 1.0 file[n] outFile 274 | /// Should support passing of volume 275 | /// 276 | /// combined and mixed file (null on failure) 277 | public string CombineMix(IList files, string outFile) 278 | { 279 | List cmd = new List(); 280 | cmd.Add(soxBin); 281 | cmd.Add("-m"); 282 | 283 | foreach (string file in files) 284 | { 285 | cmd.Add("-v"); 286 | cmd.Add("1.0"); 287 | cmd.Add(file); 288 | } 289 | cmd.Add(outFile); 290 | 291 | try 292 | { 293 | int rc = ExecSox(cmd, _globalCallback); 294 | if (rc != 0) 295 | { 296 | // Log.e(TAG, "combineMix receieved non-zero return code!"); 297 | outFile = null; 298 | } 299 | } 300 | catch (IOException e) 301 | { 302 | _globalCallback._messageAction.Execute(e.ToString()); 303 | _globalCallback._messageAction.Execute(e.StackTrace); 304 | } 305 | catch (InterruptedException e) 306 | { 307 | _globalCallback._messageAction.Execute(e.ToString()); 308 | _globalCallback._messageAction.Execute(e.StackTrace); 309 | } 310 | return outFile; 311 | } 312 | 313 | /// 314 | /// Simple combiner 315 | /// sox file[0] file[1] ... file[n] 316 | /// 317 | /// 318 | /// outFile or null on failure 319 | public string Combine(IList files, string outFile) 320 | { 321 | List cmd = new List(); 322 | cmd.Add(soxBin); 323 | 324 | foreach (string file in files) 325 | { 326 | cmd.Add(file); 327 | } 328 | cmd.Add(outFile); 329 | 330 | int rc = ExecSox(cmd, _globalCallback); 331 | if (rc != 0) 332 | { 333 | throw new System.Exception("exit code: " + rc); 334 | 335 | } 336 | 337 | return outFile; 338 | } 339 | 340 | public int ExecSox(IList cmd, FFMpegCallbacks sc) 341 | { 342 | 343 | string soxBin = (new File(fileBinDir, "sox")).CanonicalPath; 344 | var r = Runtime.GetRuntime (); 345 | r.Exec("chmod 700 " + soxBin); 346 | return ExecProcess(cmd, sc); 347 | } 348 | 349 | private int ExecProcess(IList cmds, FFMpegCallbacks sc) 350 | { 351 | //ensure that the arguments are in the correct Locale format 352 | // TODO: Useless since SOX is called internally. Remove. 353 | for ( int i = 0; i < cmds.Count; i++) 354 | { 355 | cmds[i] = string.Format(System.Globalization.CultureInfo.GetCultureInfo("en-US"), "%s", cmds[i]); 356 | } 357 | 358 | ProcessBuilder pb = new ProcessBuilder(cmds); 359 | pb.Directory(fileBinDir); 360 | 361 | var cmdlog = new Java.Lang.StringBuilder(); 362 | 363 | foreach (string cmd in cmds) 364 | { 365 | cmdlog.Append(cmd); 366 | cmdlog.Append(' '); 367 | } 368 | 369 | sc.ShellOut(cmdlog.ToString()); 370 | 371 | pb.RedirectErrorStream(true); 372 | var process = pb.Start(); 373 | 374 | StreamGobbler errorGobbler = new StreamGobbler(this, process.ErrorStream, "ERROR", sc); 375 | StreamGobbler outputGobbler = new StreamGobbler(this, process.InputStream, "OUTPUT", sc); 376 | 377 | errorGobbler.Run(); 378 | outputGobbler.Run(); 379 | 380 | int exitVal = process.WaitFor(); 381 | 382 | while (outputGobbler.IsAlive || errorGobbler.IsAlive); 383 | 384 | sc.ProcessComplete(exitVal); 385 | 386 | return exitVal; 387 | } 388 | 389 | internal class StreamGobbler : Thread 390 | { 391 | private readonly SoxHelpers outerInstance; 392 | 393 | internal System.IO.Stream inputStream; 394 | internal string type; 395 | internal FFMpegCallbacks sc; 396 | 397 | internal StreamGobbler(SoxHelpers outerInstance, System.IO.Stream inputStream, string type, FFMpegCallbacks sc) 398 | { 399 | this.outerInstance = outerInstance; 400 | this.inputStream = inputStream; 401 | this.type = type; 402 | this.sc = sc; 403 | } 404 | 405 | public override void Run() 406 | { 407 | try 408 | { 409 | var isr = new Java.IO.InputStreamReader(inputStream); 410 | BufferedReader br = new BufferedReader(isr); 411 | string line = null; 412 | while ((line = br.ReadLine()) != null) 413 | { 414 | if (sc != null) 415 | { 416 | sc.ShellOut(line); 417 | } 418 | } 419 | } 420 | catch (IOException ioe) 421 | { 422 | // _messageAction.Invoke(ioe.ToString()); 423 | // _messageAction.Invoke(ioe.StackTrace); 424 | } 425 | } 426 | } 427 | } 428 | } -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Resources/Resource.designer.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 1591 2 | //------------------------------------------------------------------------------ 3 | // 4 | // This code was generated by a tool. 5 | // Runtime Version:4.0.30319.34014 6 | // 7 | // Changes to this file may cause incorrect behavior and will be lost if 8 | // the code is regenerated. 9 | // 10 | //------------------------------------------------------------------------------ 11 | 12 | [assembly: global::Android.Runtime.ResourceDesignerAttribute("XamarinAndroidFFmpeg.Resource", IsApplication=false)] 13 | 14 | namespace XamarinAndroidFFmpeg 15 | { 16 | 17 | 18 | [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] 19 | public partial class Resource 20 | { 21 | 22 | static Resource() 23 | { 24 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 25 | } 26 | 27 | public partial class Attribute 28 | { 29 | 30 | static Attribute() 31 | { 32 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 33 | } 34 | 35 | private Attribute() 36 | { 37 | } 38 | } 39 | 40 | public partial class Raw 41 | { 42 | 43 | // aapt resource value: 0x7f020000 44 | public static int ffmpeg = 2130837504; 45 | 46 | // aapt resource value: 0x7f020001 47 | public static int sox = 2130837505; 48 | 49 | static Raw() 50 | { 51 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 52 | } 53 | 54 | private Raw() 55 | { 56 | } 57 | } 58 | 59 | public partial class String 60 | { 61 | 62 | // aapt resource value: 0x7f030000 63 | public static int library_name = 2130903040; 64 | 65 | static String() 66 | { 67 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 68 | } 69 | 70 | private String() 71 | { 72 | } 73 | } 74 | } 75 | } 76 | #pragma warning restore 1591 77 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Resources/raw/ffmpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpeg/Resources/raw/ffmpeg -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Resources/raw/sox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpeg/Resources/raw/sox -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/Resources/values/Strings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | XamarinAndroidFFmpeg 4 | 5 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpeg/XamarinAndroidFFmpeg.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 7 | {FBB10D9B-A045-4077-BE56-D71CC8A113AE} 8 | Library 9 | XamarinAndroidFFmpeg 10 | Resources\Resource.designer.cs 11 | Resource 12 | Resources 13 | Assets 14 | False 15 | XamarinAndroidFFmpeg 16 | v4.1 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug 23 | DEBUG; 24 | prompt 25 | 4 26 | false 27 | None 28 | 29 | 30 | full 31 | true 32 | bin\Release 33 | prompt 34 | 4 35 | false 36 | false 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 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with your package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/MainActivity.cs: -------------------------------------------------------------------------------- 1 | // This project is based on https://github.com/guardianproject/android-ffmpeg-java 2 | // Thus, it is licensed under the GPL 3 | 4 | 5 | using Android.Widget; 6 | using Android.App; 7 | using Android.OS; 8 | using System.Threading.Tasks; 9 | using XamarinAndroidFFmpeg; 10 | using System.Collections.Generic; 11 | using System.IO; 12 | using System.Windows.Input; 13 | using System; 14 | 15 | namespace XamarinAndroidFFmpegTests 16 | { 17 | [Activity (Label = "XamarinAndroidFFmpegTests", MainLauncher = true, Icon = "@drawable/icon")] 18 | public class MainActivity : Activity 19 | { 20 | static string _workingDirectory = ""; 21 | 22 | protected override void OnCreate (Bundle bundle) 23 | { 24 | base.OnCreate (bundle); 25 | SetContentView (Resource.Layout.Main); 26 | _logView = FindViewById (Resource.Id.message); 27 | Task.Run (() => Start ()); 28 | } 29 | 30 | EditText _logView; 31 | 32 | void Start() { 33 | 34 | _workingDirectory = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath; 35 | var sourceMp4 = "cat1.mp4"; 36 | var destinationPathAndFilename = System.IO.Path.Combine (_workingDirectory, "cat1_out.mp4"); 37 | var destinationPathAndFilename2 = System.IO.Path.Combine (_workingDirectory, "cat1_out2.mp4"); 38 | var destinationPathAndFilename4 = System.IO.Path.Combine (_workingDirectory, "cat1_out4.wav"); 39 | if (File.Exists (destinationPathAndFilename)) 40 | File.Delete (destinationPathAndFilename); 41 | CreateSampleFile(Resource.Raw.cat1, _workingDirectory, sourceMp4); 42 | 43 | 44 | var ffmpeg = new FFMpeg (this, _workingDirectory); 45 | 46 | var sourceClip = new Clip (System.IO.Path.Combine(_workingDirectory, sourceMp4)); 47 | 48 | var result = ffmpeg.GetInfo (sourceClip); 49 | 50 | var br = System.Environment.NewLine; 51 | 52 | // There are callbacks based on Standard Output and Standard Error when ffmpeg binary is running as a process: 53 | 54 | var onComplete = new MyCommand ((_) => { 55 | RunOnUiThread(() =>_logView.Append("DONE!" + br + br)); 56 | }); 57 | 58 | var onMessage = new MyCommand ((message) => { 59 | RunOnUiThread(() =>_logView.Append(message + br + br)); 60 | }); 61 | 62 | var callbacks = new FFMpegCallbacks (onComplete, onMessage); 63 | 64 | // 1. The idea of this first test is to show that video editing is possible via FFmpeg: 65 | // It results in a 150x150 movie that eventually zooms on a cat ear. This is desaturated, and there's a fade in. 66 | 67 | var filters = new List (); 68 | filters.Add (new FadeVideoFilter ("in", 0, 100)); 69 | filters.Add(new CropVideoFilter("150","150","0","0")); 70 | filters.Add(new ColorVideoFilter(1.0m, 1.0m, 0.0m, 0.5m, 1.0m, 1.0m, 1.0m, 1.0m)); 71 | var outputClip = new Clip (destinationPathAndFilename) { videoFilter = VideoFilter.Build (filters) }; 72 | outputClip.H264_CRF = "18"; // It's the quality coefficient for H264 - Default is 28. I think 18 is pretty good. 73 | ffmpeg.ProcessVideo(sourceClip, outputClip, true, new FFMpegCallbacks(onComplete, onMessage)); 74 | 75 | //2. This is a similar version version in command line only: 76 | string[] cmds = new string[] { 77 | "-y", 78 | "-i", 79 | sourceClip.path, 80 | "-strict", 81 | "-2", 82 | "-vf", 83 | "mp=eq2=1:1.68:0.3:1.25:1:0.96:1", 84 | destinationPathAndFilename2, 85 | "-acodec", 86 | "copy", 87 | }; 88 | ffmpeg.Execute (cmds, callbacks); 89 | 90 | // 3. This lists codecs: 91 | string[] cmds3 = new string[] { 92 | "-codecs", 93 | }; 94 | ffmpeg.Execute (cmds, callbacks); 95 | 96 | // 4. This convers to WAV 97 | // Note that the cat movie just has some silent house noise. 98 | ffmpeg.ConvertToWaveAudio(sourceClip, destinationPathAndFilename4, 44100, 2, callbacks, true); 99 | 100 | // Etc... 101 | 102 | // Rules of thumb: 103 | // a) Provide the minimum of info to ffmpeg to not mix it up 104 | // b) These helpers are cool to test capabilities, but useless otherwise, and crashy: Use command lines. 105 | // c) Try to compile a newer FFmpeg :) 106 | 107 | } 108 | 109 | 110 | private void CreateSampleFile(int resource, string destinationFolder, string filename) { 111 | var data = new byte[0]; 112 | using (var file = Resources.OpenRawResource (resource)) 113 | using (var fileInMemory = new MemoryStream ()) { 114 | file.CopyTo (fileInMemory); 115 | data = fileInMemory.ToArray (); 116 | } 117 | var fileName = System.IO.Path.Combine (destinationFolder, filename); 118 | System.IO.File.WriteAllBytes (fileName, data); 119 | } 120 | 121 | void RemoveSampleFile(string sourceFolder, string name) { 122 | System.IO.File.Delete (System.IO.Path.Combine (sourceFolder, name)); 123 | } 124 | 125 | public class MyCommand : ICommand 126 | { 127 | public delegate void ICommandOnExecute(object parameter = null); 128 | public delegate bool ICommandOnCanExecute(object parameter); 129 | 130 | private ICommandOnExecute _execute; 131 | private ICommandOnCanExecute _canExecute; 132 | 133 | public MyCommand(ICommandOnExecute onExecuteMethod) 134 | { 135 | _execute = onExecuteMethod; 136 | } 137 | 138 | public MyCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod) 139 | { 140 | _execute = onExecuteMethod; 141 | _canExecute = onCanExecuteMethod; 142 | } 143 | 144 | #region ICommand Members 145 | 146 | public event EventHandler CanExecuteChanged 147 | { 148 | add { throw new NotImplementedException(); } 149 | remove { throw new NotImplementedException(); } 150 | } 151 | 152 | public bool CanExecute(object parameter) 153 | { 154 | if (_canExecute == null && _execute != null) 155 | return true; 156 | 157 | return _canExecute.Invoke(parameter); 158 | } 159 | 160 | public void Execute(object parameter) 161 | { 162 | if (_execute == null) 163 | return; 164 | 165 | _execute.Invoke(parameter); 166 | } 167 | 168 | #endregion 169 | } 170 | 171 | } 172 | } 173 | 174 | 175 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using Android.App; 4 | 5 | // Information about this assembly is defined by the following attributes. 6 | // Change them to the values specific to your project. 7 | 8 | [assembly: AssemblyTitle ("ffmpeg")] 9 | [assembly: AssemblyDescription ("")] 10 | [assembly: AssemblyConfiguration ("")] 11 | [assembly: AssemblyCompany ("")] 12 | [assembly: AssemblyProduct ("")] 13 | [assembly: AssemblyCopyright ("leon.pelletier")] 14 | [assembly: AssemblyTrademark ("")] 15 | [assembly: AssemblyCulture ("")] 16 | 17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 20 | 21 | [assembly: AssemblyVersion ("1.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | 29 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.axml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.axml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. 45 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/Resource.designer.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 1591 2 | //------------------------------------------------------------------------------ 3 | // 4 | // This code was generated by a tool. 5 | // Runtime Version:4.0.30319.34014 6 | // 7 | // Changes to this file may cause incorrect behavior and will be lost if 8 | // the code is regenerated. 9 | // 10 | //------------------------------------------------------------------------------ 11 | 12 | [assembly: global::Android.Runtime.ResourceDesignerAttribute("XamarinAndroidFFmpegTests.Resource", IsApplication=true)] 13 | 14 | namespace XamarinAndroidFFmpegTests 15 | { 16 | 17 | 18 | [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] 19 | public partial class Resource 20 | { 21 | 22 | static Resource() 23 | { 24 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 25 | } 26 | 27 | public static void UpdateIdValues() 28 | { 29 | global::XamarinAndroidFFmpeg.Resource.Raw.ffmpeg = global::XamarinAndroidFFmpegTests.Resource.Raw.ffmpeg; 30 | global::XamarinAndroidFFmpeg.Resource.Raw.sox = global::XamarinAndroidFFmpegTests.Resource.Raw.sox; 31 | global::XamarinAndroidFFmpeg.Resource.String.library_name = global::XamarinAndroidFFmpegTests.Resource.String.library_name; 32 | } 33 | 34 | public partial class Attribute 35 | { 36 | 37 | static Attribute() 38 | { 39 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 40 | } 41 | 42 | private Attribute() 43 | { 44 | } 45 | } 46 | 47 | public partial class Drawable 48 | { 49 | 50 | // aapt resource value: 0x7f020000 51 | public const int Icon = 2130837504; 52 | 53 | static Drawable() 54 | { 55 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 56 | } 57 | 58 | private Drawable() 59 | { 60 | } 61 | } 62 | 63 | public partial class Id 64 | { 65 | 66 | // aapt resource value: 0x7f060000 67 | public const int message = 2131099648; 68 | 69 | static Id() 70 | { 71 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 72 | } 73 | 74 | private Id() 75 | { 76 | } 77 | } 78 | 79 | public partial class Layout 80 | { 81 | 82 | // aapt resource value: 0x7f030000 83 | public const int Main = 2130903040; 84 | 85 | static Layout() 86 | { 87 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 88 | } 89 | 90 | private Layout() 91 | { 92 | } 93 | } 94 | 95 | public partial class Raw 96 | { 97 | 98 | // aapt resource value: 0x7f040000 99 | public const int big_buck = 2130968576; 100 | 101 | // aapt resource value: 0x7f040001 102 | public const int cat1 = 2130968577; 103 | 104 | // aapt resource value: 0x7f040002 105 | public const int ffmpeg = 2130968578; 106 | 107 | // aapt resource value: 0x7f040003 108 | public const int sox = 2130968579; 109 | 110 | static Raw() 111 | { 112 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 113 | } 114 | 115 | private Raw() 116 | { 117 | } 118 | } 119 | 120 | public partial class String 121 | { 122 | 123 | // aapt resource value: 0x7f050002 124 | public const int app_name = 2131034114; 125 | 126 | // aapt resource value: 0x7f050001 127 | public const int hello = 2131034113; 128 | 129 | // aapt resource value: 0x7f050000 130 | public const int library_name = 2131034112; 131 | 132 | static String() 133 | { 134 | global::Android.Runtime.ResourceIdManager.UpdateIdValues(); 135 | } 136 | 137 | private String() 138 | { 139 | } 140 | } 141 | } 142 | } 143 | #pragma warning restore 1591 144 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/drawable-hdpi/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/drawable-hdpi/Icon.png -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/drawable-mdpi/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/drawable-mdpi/Icon.png -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/drawable-xhdpi/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/drawable-xhdpi/Icon.png -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/drawable-xxhdpi/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/drawable-xxhdpi/Icon.png -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/drawable-xxxhdpi/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/drawable-xxxhdpi/Icon.png -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/layout/Main.axml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/raw/big_buck.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/raw/big_buck.mov -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/raw/cat1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/Resources/raw/cat1.mp4 -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/Resources/values/Strings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | Hello World, Click Me! 4 | ffmpeg 5 | 6 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/XamarinAndroidFFmpegTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 7 | {87A5E21C-8AAF-4744-AA7A-92F87DB1684B} 8 | Library 9 | XamarinAndroidFFmpegTests 10 | True 11 | Resources\Resource.designer.cs 12 | Resource 13 | Properties\AndroidManifest.xml 14 | Resources 15 | Assets 16 | False 17 | ffmpeg 18 | v4.1 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug 25 | DEBUG; 26 | prompt 27 | 4 28 | false 29 | None 30 | False 31 | true 32 | true 33 | 34 | 35 | full 36 | true 37 | bin\Release 38 | prompt 39 | 4 40 | false 41 | false 42 | true 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 | {FBB10D9B-A045-4077-BE56-D71CC8A113AE} 77 | XamarinAndroidFFmpeg 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /XamarinAndroidFFmpegTests/isoparser.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/XamarinAndroidFFmpegTests/isoparser.dll -------------------------------------------------------------------------------- /ffmpeg.userprefs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /packages/NUnit.2.6.3/NUnit.2.6.3.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/packages/NUnit.2.6.3/NUnit.2.6.3.nupkg -------------------------------------------------------------------------------- /packages/NUnit.2.6.3/lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/packages/NUnit.2.6.3/lib/nunit.framework.dll -------------------------------------------------------------------------------- /packages/NUnit.2.6.3/license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/packages/NUnit.2.6.3/license.txt -------------------------------------------------------------------------------- /packages/Xamarin.UITest.0.7.1/Xamarin.UITest-License.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 2 | {\fonttbl\f0\fswiss\fcharset0 ArialMT;\f1\froman\fcharset0 TimesNewRomanPSMT;} 3 | {\colortbl;\red255\green255\blue255;\red0\green0\blue255;} 4 | {\info 5 | {\author Joseph Hill} 6 | {\*\company Orrick}}\vieww21420\viewh16600\viewkind1\viewscale200 7 | \deftab709 8 | \pard\pardeftab709\ri0\qr 9 | 10 | \f0\b\fs20 \cf0 \ 11 | \pard\pardeftab709\ri0 12 | \cf0 Xamarin.UITest\ 13 | Xamarin\'99 Software License Agreement\ 14 | \ 15 | \pard\pardeftab709\ri0\qj 16 | 17 | \fs16 \cf0 PLEASE READ THIS AGREEMENT CAREFULLY. BY INSTALLING, DOWNLOADING OR OTHERWISE USING THE SOFTWARE (INCLUDING ITS COMPONENTS), YOU AGREE TO THE TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT DOWNLOAD, INSTALL OR USE THE SOFTWARE. \ 18 | \ 19 | 1. RIGHTS AND LICENSES\ 20 | \ 21 | \pard\tx720\pardeftab709\ri0\qj 22 | 23 | \b0 \cf0 1.1. This Xamarin Software License Agreement (\'93Agreement\'94) is a legal agreement between You (an entity or a person) and Xamarin Inc. (\'93Xamarin\'94). The software product identified in the title of this Agreement, any media and accompanying documentation (collectively the \'93Software\'94) is protected by the copyright laws and treaties of the United States (\'93U.S.\'94) and other countries and is subject to the terms of this Agreement. Any update or support release to the Software that You may download or receive that is not accompanied by a license agreement expressly superseding this Agreement is Software and governed by this Agreement. If the Software is an update or support release, then You must have validly licensed the version and quantity of the Software being updated or supported in order to install or use the update or support release. If Software You download or receive hereunder is an update or support release for a prior version of Xamarin.UITest software You had that was subject to the terms of a prior Xamarin software license agreement that differs from this Agreement and may apply to such Software You download or receive hereunder, then this Agreement supersedes such prior license agreement but only with respect to such Software downloaded or received hereunder.\ 24 | \ 25 | \pard\pardeftab709\ri0\qj 26 | \cf0 1.2. \ul Components; Other License Terms.\ulnone The Software may be comprised of numerous components that may be accompanied by separate license terms. In that case, the Software is a collective work of Xamarin; although Xamarin may not own the copyright to every component of the Software, Xamarin owns the collective work copyright for the Software.\ 27 | \ 28 | Some of the components may be open source packages, developed independently, and accompanied by separate license terms. Your license rights with respect to any individual components accompanied by separate license terms are defined by those terms; nothing in this agreement shall restrict, limit, or otherwise affect any rights or obligations You may have, or conditions to which You may be subject, under such license terms.\ 29 | \ 30 | 1.3. \ul Instances.\ulnone "Instance" means the initial copy of the Software necessary for use of the Software, and each additional copy (or partial copy) of the Software stored or loaded in memory or virtual memory. \ 31 | \ 32 | 1.4. \ul Software License Grant.\ulnone Subject to the terms and conditions of this Agreement, Xamarin hereby grants to You a world-wide, nonexclusive, non-transferable license to internally use the Software, during the term of this Agreement.\ 33 | \pard\pardeftab709\ri0 34 | \cf0 \ 35 | 1.5. 36 | \b 37 | \b0 \ul Other License Terms and Restrictions 38 | \b \ulnone .\ 39 | \pard\pardeftab709\ri0\qj 40 | 41 | \b0 \cf0 \ 42 | The Software is protected by the copyright laws and treaties of the United States ("U.S.") and other countries and is subject to the terms of this Agreement. The Software is licensed to You, not sold.\ 43 | \ 44 | The Software may be bundled with other software programs ("Bundled Programs"). Your license rights with respect to Bundled Programs accompanied by separate license terms are defined by those terms; nothing in this Agreement shall restrict, limit, or otherwise affect any rights or obligations You may have, or conditions to which You may be subject, under such license terms.\'a0 \ 45 | \pard\pardeftab709\ri0 46 | \cf0 \ 47 | Xamarin reserves all rights not expressly granted to You. You may not: \ 48 | (1) reverse engineer, decompile, or disassemble any Software provided that to the extent the foregoing prohibitions are expressly prohibited by applicable statutory law, Xamarin shall retain the maximum protection available against reverse engineering, decompiling, or disassembly under applicable law; \ 49 | (2) assign, sublicense, distribute, or otherwise transfer any Software to any third party (without limitation, this prohibits You from (a) bundling any Software (including any Xamarin tools, libraries, or runtime) into a competing platform and (b) distributing Xamarin tools, libraries, or runtimes as library, source project, or other unfinished work;\ 50 | (3) reproduce any Software; \ 51 | (4) create derivative works of, modify, adapt or translate any Software; \ 52 | (5) use any Software to provide services for any third party; \ 53 | (6) lease, rent, loan, share or otherwise use, or permit use of, any Software by or for any third party; \ 54 | (7) remove any proprietary notices on or in any Software; \ 55 | (8) use any Software in a manner not in accordance with its documentation; or\ 56 | (9) use any Software in an illegal or fraudulent manner.\ 57 | \pard\pardeftab709\ri0\qj 58 | \cf0 \ 59 | 1.6. \ul Evaluation Software 60 | \b \ulnone . 61 | \b0 If the Software is an evaluation version or is provided to You for evaluation purposes, then Your license to use the Software is limited solely to internal evaluation purposes and in accordance with the terms of the evaluation offering under which You received the Software, including any limited evaluation period that may apply (which may also be indicated within the Software). Upon expiration of the evaluation period, You must discontinue use of the Software, return to an original state any actions performed by the Software, and delete the Software entirely from Your system. The Software may contain an automatic disabling mechanism that prevents its use after a certain period of time, so You should back up Your system and take other measures to prevent any loss of files or data. Without limiting the above, You may not use Evaluation Software to create an App.\ 62 | \ 63 | \pard\pardeftab709\ri0\qj 64 | 65 | \b \cf0 2. MAINTENANCE AND SUPPORT\ 66 | \pard\pardeftab709\ri0 67 | 68 | \b0 \cf0 \ 69 | \pard\pardeftab709\ri0\qj 70 | \cf0 Xamarin has no obligation to provide support or maintenance for the Software. If Xamarin does provide any such support or maintenance and no separate agreement specifically applies to such support or maintenance, then the terms of this Agreement will govern the provision of such support or maintenance services (\'93Services\'93) and Xamarin may cease Services, in whole or part, at any time. For more information on Xamarin's current support offerings, see {\field{\*\fldinst{HYPERLINK "http://support.xamarin.com"}}{\fldrslt \cf2 \ul \ulc2 http://support.xamarin.com}}. 71 | \b \ 72 | \ 73 | 3. OWNERSHIP \ 74 | 75 | \b0 \ 76 | No title to or ownership of the Software is transferred to You. Xamarin and/or its licensors retain all right, title and interest in and to all intellectual property rights in the Software and Services, including any adaptations or copies thereof. You acquire only a conditional license to use the Software.\ 77 | \ 78 | \pard\pardeftab709\ri0\qj 79 | 80 | \b \cf0 4. WARRANTY DISCLAIMER\ 81 | \pard\pardeftab709\ri0\qj 82 | 83 | \b0 \cf0 \ 84 | 4.1. \ul Software.\ulnone THE SOFTWARE IS PROVIDED \'93AS IS\'94 WITHOUT ANY WARRANTIES OF ANY KIND.\ 85 | \ 86 | THE SOFTWARE IS NOT DESIGNED, MANUFACTURED OR INTENDED FOR USE OR DISTRIBUTION WITH ON-LINE CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT NAVIGATION, COMMUNICATION, OR CONTROL SYSTEMS, DIRECT LIFE SUPPORT MACHINES, WEAPONS SYSTEMS, OR OTHER USES IN WHICH FAILURE OF THE SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE.\ 87 | \ 88 | THE SOFTWARE IS ONLY COMPATIBLE WITH CERTAIN COMPUTERS AND OPERATING SYSTEMS. Call Xamarin or Your reseller for information about compatibility.\ 89 | \ 90 | 4.2. \ul Services\ulnone . THE SERVICES (IF ANY) ARE PROVIDED \'93AS IS\'94 WITHOUT ANY WARRANTIES OF ANY KIND. As files may be altered or damaged in the course of Xamarin providing technical services, You agree to take appropriate measures to isolate and back up Your systems.\ 91 | \ 92 | 4.3. \ul Non-Xamarin Products\ulnone . The Software may include or be bundled with hardware or other software programs or services licensed or sold by an entity other than Xamarin. XAMARIN DOES NOT WARRANT NON-XAMARIN PRODUCTS OR SERVICES. ANY SUCH PRODUCTS OR SERVICES ARE PROVIDED ON AN \'93AS IS\'94 BASIS. WARRANTY SERVICE IF ANY FOR NON-XAMARIN PRODUCTS IS PROVIDED BY THE PRODUCT LICENSOR IN ACCORDANCE WITH THE APPLICABLE LICENSOR WARRANTY.\ 93 | \ 94 | 4.4. \ul General Disclaimer\ulnone . EXCEPT AS OTHERWISE RESTRICTED BY LAW, XAMARIN DISCLAIMS AND EXCLUDES ANY AND ALL IMPLIED WARRANTIES, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. XAMARIN MAKES NO WARRANTIES, REPRESENTATIONS OR PROMISES. XAMARIN DOES NOT WARRANT THAT THE SOFTWARE OR SERVICES WILL SATISFY YOUR REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE OR SERVICES WILL BE UNINTERRUPTED. Some jurisdictions do not allow certain disclaimers and limitations of warranties, so portions of the above limitations may not apply to You. You may also have other rights which vary by state or jurisdiction. \ 95 | \ 96 | \pard\pardeftab709\ri0\qj 97 | 98 | \b \cf0 5. LIMITATION OF LIABILITY\ 99 | \pard\pardeftab709\ri0\qj 100 | 101 | \b0 \cf0 \ 102 | 5.1. \ul Consequential Losses\ulnone . NEITHER XAMARIN NOR ANY OF ITS LICENSORS, SUBSIDIARIES, OR EMPLOYEES WILL IN ANY CASE BE LIABLE FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT, TORT, ECONOMIC OR PUNITIVE DAMAGES ARISING OUT OF OR RELATING TO THIS AGREEMENT OR THE USE OF OR INABILITY TO USE THE SOFTWARE OR SERVICES, INCLUDING LOSS OF PROFITS, BUSINESS OR DATA, EVEN IF ADVISED OF THE POSSIBILITY OF THOSE DAMAGES.\ 103 | \ 104 | 5.2. \ul Direct Damages\ulnone . IN NO EVENT WILL XAMARIN'S AGGREGATE LIABILITY FOR DIRECT DAMAGES ARISING OUT OF OR RELATING TO THIS AGREEMENT OR THE USE OF OR INABILITY TO USE THE SOFTWARE OR SERVICES (WHETHER IN ONE INSTANCE OR A SERIES OF INSTANCES) EXCEED FIFTY UNITED STATES DOLLARS ($50 (U.S.)). \ 105 | \ 106 | 5.3. \ul Exclusions\ulnone . The above exclusions and limitations will not apply to claims relating to death or personal injury. In those jurisdictions that do not allow the exclusion or limitation of damages, Xamarin's liability shall be limited or excluded to the maximum extent allowed within those jurisdictions.\ 107 | \ 108 | \pard\pardeftab709\ri0\qj 109 | 110 | \b \cf0 6. GENERAL TERMS\ 111 | \pard\pardeftab709\ri0\qj 112 | 113 | \b0 \cf0 \ 114 | 6.1. \ul Term\ulnone . This Agreement becomes effective on the date You legally acquire the Software and will automatically terminate on Your breach any of the terms of this Agreement. \ul \ 115 | \ulnone 6.2. \ul Benchmark Testing\ulnone . This benchmark testing restriction applies to You if You are a software developer or licensor or if You are performing testing on the Software at the direction of or on behalf of a software developer or licensor. You may not, without Xamarin's prior written consent not to be unreasonably withheld, publish or disclose to any third party the results of any benchmark test of the Software. If You are a licensor of products that are functionally similar to or compete with the Software (\'93Similar Products\'94), or are acting on behalf of such a licensor, and You publish or disclose benchmark information on the Software in violation of this restriction, then notwithstanding anything to the contrary in the Similar Product's end user license agreement, and in addition to any other remedies Xamarin may have, Xamarin shall have the right to perform benchmark testing on Similar Products and to disclose and publish that benchmark information and You hereby represent that You have authority to grant such right to Xamarin.\ 116 | 6.3. \ul Open Source\ulnone . Nothing in this Agreement shall restrict, limit or otherwise affect any rights or obligations You may have, or conditions to which You may be subject, under any applicable open source licenses to any open source code contained in the Software. \ 117 | 6.4. \ul Assignment; Transfer\ulnone . Neither this Agreement, nor any rights or obligations hereunder, may be transferred, assigned or delegated without the prior written approval of Xamarin. Any such transfer, assignment or delegation made in contravention of this paragraph shall be null and void.\ 118 | 6.5. \ul Law and Jurisdiction\ulnone . This Agreement is and will be governed by and construed under the laws of the State of California, U.S., without giving effect to any conflicts of laws provision thereof or of any other jurisdiction that would produce a contrary result. Any action arising out of or relating to this Agreement may be brought before the courts of competent jurisdiction of the State of California, U.S., and You consent to the jurisdiction of such courts and waive any objections of improper venue or inconvenient forum. You consent to service of process by mail, nationally-recognized courier service, fax or email, to the contact information you provided to Xamarin at the time of your acquisition of the Software or thereafter. \ 119 | 6.6. \ul Entire Agreement\ulnone . This Agreement sets forth the entire understanding and agreement between You and Xamarin and may be amended or modified only by a written agreement agreed to by You and an authorized representative of Xamarin. NO LICENSOR, DISTRIBUTOR, DEALER, RETAILER, RESELLER, SALES PERSON, OR EMPLOYEE IS AUTHORIZED TO MODIFY THIS AGREEMENT OR TO MAKE ANY REPRESENTATION OR PROMISE THAT IS DIFFERENT FROM, OR IN ADDITION TO, THE TERMS OF THIS AGREEMENT. \ 120 | 6.7. \ul Waiver\ulnone . No waiver of any right under this Agreement will be effective unless in writing, signed by a duly authorized representative of the party to be bound. No waiver of any past or present right arising from any breach or failure to perform will be deemed to be a waiver of any future right arising under this Agreement.\ 121 | 6.8. \ul Severability\ulnone . If any provision in this Agreement is invalid or unenforceable, that provision will be construed, limited, modified or, if necessary, severed, to the extent necessary, to eliminate its invalidity or unenforceability, and the other provisions of this Agreement will remain unaffected. \ 122 | 6.9. \ul Export Compliance\ulnone . Any Software or technical information received under this Agreement (collectively, \'93Received Items\'94) may be subject to U.S. export controls and the trade laws of other countries. You agree to comply with all applicable export control regulations and to obtain any required licenses or classification to export, re-export or import Received Items. You may not use or otherwise export or re-export the Received Items except as authorized by U.S. law and the law of each jurisdiction that applies to Your activities. Without limiting the foregoing, You agree not to export or re-export any Received Items to (a) entities or persons on the then-current U.S. Treasury Department's list of Specially Designated Nationals, the then-current U.S. Department of Commerce Denied Person\'92s List or Entity List, or any other U.S. export exclusion list that is then applicable or (b) any embargoed or terrorist country as specified in the U.S. export laws. By installing, downloading or otherwise using the Received Items, You represent and warrant that You are not located in any such embargoed or terrorist country or on any such exclusion list. In addition, You agree not to use any Received Items for any purposes prohibited by United States law, including the development, design, manufacture or production of nuclear, missile, or chemical or biological weapons. Upon request, Xamarin will provide You specific information regarding applicable restrictions. However, Xamarin assumes no responsibility for Your failure to obtain any necessary export approvals.\ul \ 123 | \ulnone 6.10. \ul U.S. Government Restricted Rights\ulnone . Use, duplication, or disclosure by the U.S. Government is subject to the restrictions in FAR 52.227-14 (June 1987) Alternate III (June 1987), FAR 52.227-19 (June 1987), or DFARS 252.227-7013 (b) (3) (Nov 1995), or applicable successor clauses. Contractor/Manufacturer is Xamarin Inc., 430 Pacific Avenue, San Francisco, CA 94133.\ 124 | 6.11. \ul Headings; Interpretation.\ulnone Headings are provided for convenience only and will not be used to interpret the substance of this Agreement. The use of \'93include,\'94 \'93includes,\'94 or \'93including\'94 herein will be read as if followed by the phrase \'93without limitation.\'94\ 125 | 6.12. \ul Trademarks\ulnone . Nothing in this Agreement shall be construed as conferring any right to You to use any name, logo, or other trademark of Xamarin, its affiliates or licensors.\ 126 | 6.13. \ul Other\ulnone . The application of the United Nations Convention of Contracts for the International Sale of Goods is expressly excluded.\ 127 | \ 128 | \'a9 2014 Xamarin Inc. All Rights Reserved.\ 129 | \ 130 | Xamarin is a trademark of Xamarin Inc. in the United States and other countries. \ 131 | \pard\pardeftab709\ri0\qj 132 | 133 | \f1\fs24 \cf0 \ 134 | \pard\pardeftab709\ri0\qj 135 | 136 | \f0\fs18 \cf0 20140512 137 | \f1\fs24 \ 138 | } -------------------------------------------------------------------------------- /packages/Xamarin.UITest.0.7.1/Xamarin.UITest.0.7.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/packages/Xamarin.UITest.0.7.1/Xamarin.UITest.0.7.1.nupkg -------------------------------------------------------------------------------- /packages/Xamarin.UITest.0.7.1/lib/Xamarin.UITest.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/packages/Xamarin.UITest.0.7.1/lib/Xamarin.UITest.dll -------------------------------------------------------------------------------- /packages/Xamarin.UITest.0.7.1/release-notes.md: -------------------------------------------------------------------------------- 1 | # Xamarin.UITest release notes 2 | 3 | ## 0.7.1 4 | 5 | * Readded --async option to anonymous submit command in uploader (test-cloud.exe) 6 | * Fixed typo in default locale value in uploader (test-cloud.exe) 7 | * Reduced memory usage in loggers 8 | * Improved error reporting in IOS host run loop 9 | * Fixed error in naming of inherited [Test] 10 | * Added support for parameterized test fixtures in uploader (test-cloud.exe) 11 | * Fixed an error when querying with All().Css() 12 | 13 | ## 0.7.0 14 | 15 | * Added methods for Pinch gestures on Android 16 | * Added `PreferIdeSettings` to configuration for upcoming IDE integration 17 | * Added an experimental `AppDataMode` parameter in `StartApp` for controlling whether data is cleared or not in Android test runs 18 | * Fixed upload issues with test chunking when uploading to Xamarin Test Cloud when encountering assemblies that couldn't be resolved 19 | * Removed the legacy positional device parameter in `test-cloud.exe submit` - you should now use `--devices` instead 20 | * Added support for trace sources 21 | * Added `test-cloud.exe repl` command for launching a REPL without a test suite 22 | * Added support for `InstalledApp` for Android as an alternative to `ApkFile` 23 | * Added support for `LogPath` to control the log output directory for both Android and iOS 24 | * Added label printing to `tree` in the REPL 25 | * Added `DragAndDrop` support for Android 26 | * Added `DoubleTap` support for web views on Android 27 | * Fixed an error in `WaitForElement` if the element was visible briefly and then disappeared 28 | * Added support for specifying an activity to launch using `LaunchableActivity` on Android 29 | * Improved discovery of the Android SDK if using Xamarin Studio on OSX 30 | * Increased the length of `SwipeRight` and `SwipeLeft` on Android to make them more useful 31 | 32 | ## 0.6.9 33 | 34 | * Improved test detection in uploader 35 | * `tree` command speedup on IOS 36 | * Updated communication with Test Cloud Agent to support 12.0.x 37 | * Android test server updated to 0.5.6.pre2 to fix issue with invoking methods on main Activity 38 | 39 | ## 0.6.8 40 | 41 | * Removed assembly loading from the REPL when looking for extension methods to avoid crash on Mono 42 | * Fixed an issue that would sometimes cause waits longer than expected after gestures 43 | 44 | ## 0.6.7 45 | 46 | * Added `app.PressUserAction` for Android 47 | * Added `app.SendAppToBackground` for iOS 48 | * Improved stability of detection of connected iOS devices 49 | * Improved error message when the REPL fails to load assemblies 50 | * Improved error message when UIAutomation is not enabled on iOS 8 devices 51 | * Improved detection of Android emulators 52 | * Fixed an issue with Android `app.Invoke` 53 | * Fixed wait for keyboard on iOS in Test Cloud 54 | * Added support for launching Android apps using activity aliases 55 | * Fixed `tree` on Android where some visible elements would not show up 56 | 57 | ## 0.6.6 58 | 59 | * Adds methods for clearing text fields with `app.ClearText` 60 | * Improved iOS physical device detection 61 | * Fixes an issue on iOS 8 with coordinates being off in some cases 62 | * Fixed an issue where the REPL would not work with ReSharper shadow copy 63 | * Improved error reporting when the REPL fails to launch properly 64 | * Added XPath selectors as an alternative to Css for web views 65 | * Added double tap gesture for Android 66 | * Fixed a hang issue in Android with multiple UI threads and modal dialogs 67 | 68 | ## 0.6.5 69 | 70 | * Re-enabled shared runtime check 71 | * Fixes an issue with iOS version parsing 72 | 73 | ## 0.6.4 74 | 75 | * Disable shared runtime check 76 | 77 | ## 0.6.2 78 | 79 | * Improved test execution speed for locally connected iOS 8 devices 80 | * Improved tree command output 81 | * Repl extented to support extension methods, including custom ones 82 | 83 | ## 0.6.1 84 | 85 | * Fixes an issue where api key wasn't being properly passed to REPL 86 | 87 | ## 0.6.0 88 | 89 | * Support added for XCode 6 and iOS 8 90 | * Added activation. An api key must be provided in order to run on physical devices or test runs for 15+ minutes 91 | * Added `Back` on iOS apps 92 | * Added `TextField` and `Switch` to the query api 93 | * Added automatic clean-up of test artifacts in the temp folder so they don't grow forever 94 | * Added proper exit codes to `test-cloud.exe` for various error scenarios 95 | * Fixed a bug in `Scroll` 96 | * Changed REPL intellisense to use NRefactory (same as XS) - much better now 97 | * Added the `copy` command in the REPL to copy your command history to clipboard for easy paste into test 98 | * Added the first tab completion shortcuts to REPL. `tap` + (tab) expands to `app.Tap(x => x.`, `query` + (tab) expands to `app.Query(x => x.` 99 | * Improved stability of tests with smarter waiting for both Android and iOS. Should be less need for waits before gestures and screenshots now 100 | * iOS `PanCoordinates` was renamed to `DragCoordinates` and added to the `IApp` interface 101 | 102 | ## 0.5.0 103 | 104 | * `xut-console.exe` has been renamed to `test-cloud.exe` 105 | * The `Xamarin.UITest.Console` NuGet package has been removed. Everything is (and has been for a while) contained in the `Xamarin.UITest` NuGet package 106 | * `.DeviceIdentifier(...)` can now accept iOS simulator strings for running on a specific simulator. Entering an invalid text produces and error with all the valid options 107 | * Support for `[TestFixtureSetUp]` has been added for Test Cloud 108 | * Android test start up time has been improved 109 | * Direct HTTP access to the test server is available through `.TestServer` 110 | * `.Parent()`, `.Sibling()`, `.Descendant()` and `.Child()` can all accept an integer index for the element - so `.Child(1)` is equivalent to the current `.Child().Index(1)` 111 | * The query language contains `.WebView()` for cross platform web view selection 112 | * The query language has `.InvokeJS(...)` for evaluating JavaScript in matched web views 113 | * Dynamic wait times has been added - currently used for longer default waits in Test Cloud and shorter default waits in the REPL 114 | * `iOSApp` and `IApp` now also have support for `.Back()` 115 | * Android `.EnterText()` has been converted from old `setText` approach to touching the input field and entering text 116 | 117 | ## 0.4.10 118 | 119 | * Adds `EnterText(text)` to `IApp` and `AndroidApp` for typing into the currently focused view element 120 | 121 | ## 0.4.9 122 | 123 | * Allows direct access to iOS UIA using JavaScript via `InvokeUia(script)` for advanced scenarios and workarounds 124 | * Fixes an issue with proxying HTTP over USB for iOS on physical devices on some systems 125 | * Improves the error message when trying to use `SetLocation` on Android without having the `android.permission.ALLOW_MOCK_LOCATIONS` permission 126 | 127 | ## 0.4.8 128 | 129 | * Both Android and iOS now have support for `.Flash(...)` to highlight view elements matched by the query 130 | * Both Android and iOS now have support for `.SetLocation(...)` - it can be found under `app.Device` 131 | * Invoking methods on Android where the result cannot be serialized by calabash are handled more gracefully 132 | * Running tests on both iOS simulators and physical devices should no longer produce port conflicts 133 | * Deserializing json results have better support for `object` and nullables 134 | * Configuration properties on `.Config` have found a new home in `.Device` for clearer naming 135 | * Android scrolling works again, after adapting to the new method used by calabash-android 136 | * Uploading iOS tests no longer fail if user does not have the Android SDK installed 137 | * Improved a bunch of error messages in different scenarios 138 | -------------------------------------------------------------------------------- /packages/Xamarin.UITest.0.7.1/tools/test-cloud.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leye0/XamarinAndroidFFmpeg/fbe3e9e577c832f6b50bf5a5ce85958aaf7b9a0c/packages/Xamarin.UITest.0.7.1/tools/test-cloud.exe -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------