From a417aae011dbc0bb57d9aff1d4e194b84a96a75b Mon Sep 17 00:00:00 2001 From: Ilja Kosynkin Date: Mon, 3 Oct 2016 07:50:03 +0200 Subject: [PATCH] 1.0.1 minor fixes --- .idea/.name | 1 - .idea/compiler.xml | 22 -------- .idea/copyright/profiles_settings.xml | 3 - .idea/dictionaries/Ilja.xml | 7 --- .idea/encodings.xml | 6 -- .idea/gradle.xml | 26 --------- .idea/misc.xml | 46 --------------- .idea/modules.xml | 10 ---- .idea/runConfigurations.xml | 12 ---- .idea/vcs.xml | 6 -- README.md | 39 ++++++++----- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- sample/build.gradle | 6 +- .../ffmpeg/videokit/sample/MainActivity.java | 4 +- videokit/build.gradle | 6 +- .../ffmpeg/videokit/CommandBuilder.java | 4 +- .../ffmpeg/videokit/VideoCommandBuilder.java | 56 +++++++++++++++---- .../processing/ffmpeg/videokit/VideoKit.java | 2 +- .../videokit/VideoProcessingResult.java | 6 +- .../ffmpeg/videokit/CommandBuilderTest.java | 21 +++++-- .../ffmpeg/videokit/CommandTest.java | 4 +- 22 files changed, 105 insertions(+), 190 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/dictionaries/Ilja.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/runConfigurations.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index d01d297..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -video-kit-ffmpeg-android \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43e..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/dictionaries/Ilja.xml b/.idea/dictionaries/Ilja.xml deleted file mode 100644 index 13cbe0c..0000000 --- a/.idea/dictionaries/Ilja.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - ffmpeg - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 85d0c74..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 5d19981..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 2016b5c..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 45eaaa5..e5d80f8 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ # Video processing library based on FFmpeg ## Main purpose -Main purpose of this library is to allow developers to embed FFmpeg into their application with literally one line of code -in gradle.build. Using native code in Java in general and in Android environment especially always related to some problems. +Main purpose of this library is to allow developers to embed FFmpeg into their application with literally one line of code +in gradle.build. Using native code in Java in general and in Android environment especially always related to some problems. Hopefully VideoKit will resolve some of them. ## Setup -Basic setup just add following line of code to yout gradle.build file: -`compile 'com.infullmobile.android:videokit-release:1.0'` -Also, if you haven't use inFullMobile public maven in your project before, don't forget to add following line to your +Basic setup just add following line of code to your gradle.build file: +`compile 'com.infullmobile.android:videokit-release:1.0.1'` +Also, if you haven't use inFullMobile public maven in your project before, don't forget to add following line to your repositories: `maven { url 'https://maven.infullmobile.com/public' }` -That's pretty much all. +That's pretty much all. ## Example usage -Module sample is showing usage of VideoKit. Please note, that VideoKit is basically invoking FFmpeg main() with CLI arguments +Module sample is showing usage of VideoKit. Please note, that VideoKit is basically invoking FFmpeg main() with CLI arguments so you will use commands almost like you use standard FFmpeg on Linux or Windows or MacOS. Well, let me show you some code: ``` @@ -21,21 +21,21 @@ Well, let me show you some code: final Command command = videoKit.createCommand() .overwriteOutput() .addInputPath(path) - .addOutputPath(path + POSTFIX) + .outputPath(path + POSTFIX) .addCustomCommand("-ss 1 -t 3") .copyVideoCodec() - .addExperimentalFlag() + .experimentalFlag() .build(); ``` -Command is basically set of instructions for FFmpeg. Please note, that order in which you adding instructions in +Command is basically set of instructions for FFmpeg. Please note, that order in which you adding instructions in CommandBuilder is quite important. Sometimes, when you mess up order, FFmpeg will not recognize command and end up -with error. After you've built a command you should execute it: either with execute() or you can pass it to +with error. After you've built a command you should execute it: either with execute() or you can pass it to AsyncCommandExecutor. Please note, that: `command.execute();` will be executed on thread on which it was called, while: `new AsyncCommandExecutor(command, this).execute();` -will be executed in background thread and you have to provide implementation of ProcessingListener to get result of +will be executed in background thread and you have to provide implementation of ProcessingListener to get result of processing either in onSuccess (you will get path to processed file here) or onFailure (you will get error code here). ## Other functions @@ -48,10 +48,19 @@ ERRORS_ONLY FULL ``` -## Error codes -I've tryed to make library as debuggable as it even possible, taking in account that we're working with native code. +## Specific behavior of flags +As I already have mentioned: FFmpeg is quite sensible to the order of flags. To help out with that +to user VideoKit have default behavior for particular flags, namely: input paths, output path and experimental flag. +The order in which VideoKit is laying those flags is following: + +1. Input paths are always going first (doesn't matter in which place of chain you have added particular path) +2. Output path is always going at the end of command +3. Experimental flag is always just before output path + +## Error codes +I've tried to make library as debuggable as it even possible, taking in account that we're working with native code. If you getting failures from VideoKit and log in not really helpfull try to look into *docs* folder in *ffmpeg_return_codes* -file. In this file you not only have list of possible return codes with which FFMpeg can exit, but also file and number of +file. In this file you not only have list of possible return codes with which FFMpeg can exit, but also file and number of line of code in which exit was called. Version of FFmpeg is 2.8.4 and changed sources can be found over here: [Development Kit](https://github.com/IljaKosynkin/FFmpeg-Development-Kit) diff --git a/build.gradle b/build.gradle index 8fd731d..ec8354d 100644 --- a/build.gradle +++ b/build.gradle @@ -3,14 +3,14 @@ buildscript { repositories { mavenCentral() } - classpath 'com.android.tools.build:gradle:2.1.2' + classpath 'com.android.tools.build:gradle:2.2.0' } } allprojects { repositories { - mavenLocal() jcenter() + mavenLocal() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 122a0dc..5efdcec 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 28 10:00:20 PST 2015 +#Mon Oct 03 06:57:42 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/sample/build.gradle b/sample/build.gradle index cb3631a..a2d4cc7 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -8,8 +8,8 @@ android { applicationId "ffmpeg.videokit.sample" minSdkVersion 10 targetSdkVersion 22 - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "1.0.1" } buildTypes { release { @@ -25,6 +25,6 @@ dependencies { compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:design:23.4.0' compile project(':videokit') - //compile 'com.infullmobile.android:video-kit-ffmpeg:1.0' + //compile 'com.infullmobile.android:videokit-release:1.0.1' } diff --git a/sample/src/main/java/ffmpeg/videokit/sample/MainActivity.java b/sample/src/main/java/ffmpeg/videokit/sample/MainActivity.java index 330da0c..1c1e720 100644 --- a/sample/src/main/java/ffmpeg/videokit/sample/MainActivity.java +++ b/sample/src/main/java/ffmpeg/videokit/sample/MainActivity.java @@ -72,10 +72,10 @@ public void onMediaFileSelected(String path) { final Command command = videoKit.createCommand() .overwriteOutput() .addInputPath(path) - .addOutputPath(path + POSTFIX) + .outputPath(path + POSTFIX) .addCustomCommand("-ss 1 -t 3") .copyVideoCodec() - .addExperimentalFlag() + .experimentalFlag() .build(); new AsyncCommandExecutor(command, this).execute(); diff --git a/videokit/build.gradle b/videokit/build.gradle index c0a4ae3..37884a2 100644 --- a/videokit/build.gradle +++ b/videokit/build.gradle @@ -5,7 +5,7 @@ repositories { mavenCentral() } group 'com.infullmobile.android' -version '1.0' +version '1.0.1' task sourceJar(type: Jar) { from android.sourceSets.main.java.srcDirs @@ -73,8 +73,8 @@ android { defaultConfig { minSdkVersion 10 targetSdkVersion 22 - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "1.0.1" } testOptions { diff --git a/videokit/src/main/java/processing/ffmpeg/videokit/CommandBuilder.java b/videokit/src/main/java/processing/ffmpeg/videokit/CommandBuilder.java index 49e978c..43d1561 100644 --- a/videokit/src/main/java/processing/ffmpeg/videokit/CommandBuilder.java +++ b/videokit/src/main/java/processing/ffmpeg/videokit/CommandBuilder.java @@ -8,14 +8,14 @@ public interface CommandBuilder { CommandBuilder overwriteOutput(); CommandBuilder addInputPath(String inputFilePath); - CommandBuilder addOutputPath(String outputPath); + CommandBuilder outputPath(String outputPath); CommandBuilder trimForDuration(int startPosition, int duration); CommandBuilder withoutAudio(); CommandBuilder copyVideoCodec(); CommandBuilder addCrop(int x, int y, int width, int height); CommandBuilder addCustomCommand(String customCommand); CommandBuilder limitVideoBitrate(String bitrate); - CommandBuilder addExperimentalFlag(); + CommandBuilder experimentalFlag(); CommandBuilder limitFrameRate(int framerate); CommandBuilder setTuneToFast(); Command build(); diff --git a/videokit/src/main/java/processing/ffmpeg/videokit/VideoCommandBuilder.java b/videokit/src/main/java/processing/ffmpeg/videokit/VideoCommandBuilder.java index 26d89c8..c2f5756 100644 --- a/videokit/src/main/java/processing/ffmpeg/videokit/VideoCommandBuilder.java +++ b/videokit/src/main/java/processing/ffmpeg/videokit/VideoCommandBuilder.java @@ -32,8 +32,10 @@ class VideoCommandBuilder implements CommandBuilder { private final VideoKit videoKit; + private final List inputPaths = new ArrayList<>(); private String outputPath; - private boolean inputWasSet; + + private boolean experimentalFlagSet; VideoCommandBuilder(VideoKit videoKit) { this.videoKit = videoKit; @@ -52,14 +54,12 @@ public CommandBuilder addInputPath(String inputFilePath) { throw new RuntimeException("File provided by you does not exists"); } - inputWasSet = true; - flags.add(INPUT_FILE_FLAG); - flags.add(inputFilePath); + inputPaths.add(inputFilePath); return this; } @Override - public CommandBuilder addOutputPath(String outputPath) { + public CommandBuilder outputPath(String outputPath) { if (TextUtils.isEmpty(outputPath)) { throw new RuntimeException("It's not a good idea to pass empty path here"); } @@ -120,9 +120,8 @@ public CommandBuilder limitVideoBitrate(String bitrate) { } @Override - public CommandBuilder addExperimentalFlag() { - flags.add(STRICT_FLAG); - flags.add(EXPERIMENTAL_FLAG); + public CommandBuilder experimentalFlag() { + experimentalFlagSet = true; return this; } @@ -144,16 +143,49 @@ public CommandBuilder setTuneToFast() { @Override public Command build() { - if (!inputWasSet) { - throw new RuntimeException("You must specify input path"); + checkInputPathsAndThrowIfEmpty(); + checkOutputPathAndThrowIfEmpty(); + + final List newFlags = new ArrayList<>(); + + addInputPathsToFlags(newFlags); + copyFlagsToNewDestination(newFlags); + addExperimentalFlagIfNecessary(newFlags); + + newFlags.add(outputPath); + + return new VideoCommand(newFlags, outputPath, videoKit); + } + + private void checkInputPathsAndThrowIfEmpty() { + if (inputPaths.isEmpty()) { + throw new RuntimeException("You must specify at least one input path"); } + } + private void checkOutputPathAndThrowIfEmpty() { if (TextUtils.isEmpty(outputPath)) { throw new RuntimeException("You must specify output path"); } + } - flags.add(outputPath); + private void addInputPathsToFlags(List flags) { + for (String path : inputPaths) { + flags.add(INPUT_FILE_FLAG); + flags.add(path); + } + } - return new VideoCommand(flags, outputPath, videoKit); + private void copyFlagsToNewDestination(List destination) { + for (String flag : flags) { + destination.add(flag); + } + } + + private void addExperimentalFlagIfNecessary(List flags) { + if (experimentalFlagSet) { + flags.add(STRICT_FLAG); + flags.add(EXPERIMENTAL_FLAG); + } } } diff --git a/videokit/src/main/java/processing/ffmpeg/videokit/VideoKit.java b/videokit/src/main/java/processing/ffmpeg/videokit/VideoKit.java index 818d78c..b026678 100644 --- a/videokit/src/main/java/processing/ffmpeg/videokit/VideoKit.java +++ b/videokit/src/main/java/processing/ffmpeg/videokit/VideoKit.java @@ -16,7 +16,7 @@ public class VideoKit { System.loadLibrary("avdevice-56"); System.loadLibrary("videokit"); } catch (UnsatisfiedLinkError e) { - + e.printStackTrace(); } } diff --git a/videokit/src/main/java/processing/ffmpeg/videokit/VideoProcessingResult.java b/videokit/src/main/java/processing/ffmpeg/videokit/VideoProcessingResult.java index db5ed4d..26559da 100644 --- a/videokit/src/main/java/processing/ffmpeg/videokit/VideoProcessingResult.java +++ b/videokit/src/main/java/processing/ffmpeg/videokit/VideoProcessingResult.java @@ -5,18 +5,18 @@ * Copyright by inFullMobile */ public class VideoProcessingResult { - public static final int SUCCESSFUL_RESULT = 0; + static final int SUCCESSFUL_RESULT = 0; private final int returnCode; private final String pathToFile; - public VideoProcessingResult(int code, String path) { + VideoProcessingResult(int code, String path) { returnCode = code; pathToFile = path; } public boolean isSuccessful() { - return returnCode == 0; + return returnCode == SUCCESSFUL_RESULT; } public String getPath() { diff --git a/videokit/src/test/java/processing/ffmpeg/videokit/CommandBuilderTest.java b/videokit/src/test/java/processing/ffmpeg/videokit/CommandBuilderTest.java index 8293408..9023fb6 100644 --- a/videokit/src/test/java/processing/ffmpeg/videokit/CommandBuilderTest.java +++ b/videokit/src/test/java/processing/ffmpeg/videokit/CommandBuilderTest.java @@ -19,7 +19,7 @@ public class CommandBuilderTest { private String testPath; @Mock VideoKit videoKit; - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(String[].class); + private ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(String[].class); @Before public void setUp() { @@ -56,6 +56,19 @@ public void shouldCreateCorrectBuilder() { builder.build(); } + @Test + public void shouldAppendFewInputPaths() { + // given + final CommandBuilder builder = getCorrectCommandBuilder().addInputPath(testPath); + final String[] expectedFlags = { "ffmpeg", "-i", testPath, "-i", testPath, testPath }; + + // when + builder.build().execute(); + + // then + assertTrue(areStringArraysEqual(argumentCaptor.getValue(), expectedFlags)); + } + @Test public void shouldAppendOverwriteFlag() { // given @@ -154,9 +167,9 @@ public void shouldAppendLimitBitrateFlag() { } @Test - public void shouldAppendExperimentalFlag() { + public void shouldAppendExperimentalFlagToTheEnd() { // given - final CommandBuilder builder = getCorrectCommandBuilder().addExperimentalFlag(); + final CommandBuilder builder = getCorrectCommandBuilder().experimentalFlag(); final String[] expectedFlags = { "ffmpeg", "-i", testPath, "-strict", "-2", testPath }; @@ -198,7 +211,7 @@ public void shouldAppendFastTuneFlag() { private CommandBuilder getCorrectCommandBuilder() { return new VideoCommandBuilder(videoKit) .addInputPath(testPath) - .addOutputPath(testPath); + .outputPath(testPath); } private String getTestFilePath() { diff --git a/videokit/src/test/java/processing/ffmpeg/videokit/CommandTest.java b/videokit/src/test/java/processing/ffmpeg/videokit/CommandTest.java index 8d6c996..7efa551 100644 --- a/videokit/src/test/java/processing/ffmpeg/videokit/CommandTest.java +++ b/videokit/src/test/java/processing/ffmpeg/videokit/CommandTest.java @@ -15,7 +15,7 @@ * Copyright by inFullMobile */ public class CommandTest { - VideoKit videoKit; + private VideoKit videoKit; private String testPath; @@ -33,7 +33,7 @@ public void shouldReturnSuccess() { //given final CommandBuilder builder = new VideoCommandBuilder(videoKit); final Command command = builder.addInputPath(testPath) - .addOutputPath(testPath) + .outputPath(testPath) .build(); //when