Skip to content

Commit 3e43e13

Browse files
committed
feat: Implement AbstractFFmepgInputBuilder
1 parent 2ce21da commit 3e43e13

10 files changed

+178
-20
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package net.bramp.ffmpeg.builder;
2+
3+
import com.google.common.collect.ImmutableList;
4+
import net.bramp.ffmpeg.options.EncodingOptions;
5+
import net.bramp.ffmpeg.probe.FFmpegProbeResult;
6+
7+
import javax.annotation.CheckReturnValue;
8+
import java.util.List;
9+
10+
public abstract class AbstractFFmpegInputBuilder<T extends AbstractFFmpegInputBuilder<T>> extends AbstractFFmpegStreamBuilder<T> {
11+
private final FFmpegProbeResult probeResult;
12+
13+
public AbstractFFmpegInputBuilder() {
14+
this(null, null);
15+
}
16+
17+
public AbstractFFmpegInputBuilder(FFmpegBuilder parent) {
18+
this(parent, null);
19+
}
20+
21+
public AbstractFFmpegInputBuilder(FFmpegBuilder parent, FFmpegProbeResult probeResult) {
22+
// TODO
23+
24+
super(parent, "ignored");
25+
this.probeResult = probeResult;
26+
}
27+
28+
public FFmpegProbeResult getProbeResult() {
29+
return probeResult;
30+
}
31+
32+
@Override
33+
@CheckReturnValue
34+
@SuppressWarnings("unchecked")
35+
protected T getThis() {
36+
return (T) this;
37+
}
38+
39+
@Override
40+
public EncodingOptions buildOptions() {
41+
return null;
42+
}
43+
44+
@Override
45+
protected List<String> build(FFmpegBuilder parent, int pass) {
46+
ImmutableList.Builder<String> args = new ImmutableList.Builder<>();
47+
48+
addGlobalFlags(parent, args);
49+
50+
// TODO: Handle input options
51+
52+
args.addAll(buildInputString());
53+
54+
return args.build();
55+
}
56+
57+
protected abstract List<String> buildInputString();
58+
}

src/main/java/net/bramp/ffmpeg/builder/AbstractFFmpegOutputBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ protected List<String> build(FFmpegBuilder parent, int pass) {
272272
checkArgument(
273273
constantRateFactor == null, "Target size can not be used with constantRateFactor");
274274

275-
String firstInput = parent.inputs.iterator().next();
276-
FFmpegProbeResult input = parent.inputProbes.get(firstInput);
275+
AbstractFFmpegInputBuilder<?> firstInput = parent.inputs.iterator().next();
276+
FFmpegProbeResult input = firstInput.getProbeResult();
277277

278278
checkState(input != null, "Target size must be used with setInput(FFmpegProbeResult)");
279279

src/main/java/net/bramp/ffmpeg/builder/FFmpegBuilder.java

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public String toString() {
7373
String format;
7474
Long startOffset; // in millis
7575
boolean read_at_native_frame_rate = false;
76-
final List<String> inputs = new ArrayList<>();
76+
final List<AbstractFFmpegInputBuilder<?>> inputs = new ArrayList<>();
7777
final Map<String, FFmpegProbeResult> inputProbes = new TreeMap<>();
7878

7979
final List<String> extra_args = new ArrayList<>();
@@ -126,34 +126,54 @@ public FFmpegBuilder readAtNativeFrameRate() {
126126
return this;
127127
}
128128

129-
public FFmpegBuilder addInput(FFmpegProbeResult result) {
129+
public FFmpegFileInputBuilder addInput(FFmpegProbeResult result) {
130130
checkNotNull(result);
131131
String filename = checkNotNull(result.getFormat()).getFilename();
132-
inputProbes.put(filename, result);
133-
return addInput(filename);
132+
133+
return this.doAddInput(new FFmpegFileInputBuilder(this, filename, result));
134134
}
135135

136-
public FFmpegBuilder addInput(String filename) {
136+
public FFmpegFileInputBuilder addInput(String filename) {
137137
checkNotNull(filename);
138-
inputs.add(filename);
139-
return this;
138+
139+
return this.doAddInput(new FFmpegFileInputBuilder(this, filename));
140+
}
141+
142+
public <T extends AbstractFFmpegInputBuilder<T>> FFmpegBuilder addInput(T input) {
143+
return this.doAddInput(input).done();
144+
}
145+
146+
protected <T extends AbstractFFmpegInputBuilder<T>> T doAddInput(T input) {
147+
checkNotNull(input);
148+
149+
inputs.add(input);
150+
return input;
140151
}
141152

142153
protected void clearInputs() {
143154
inputs.clear();
144155
inputProbes.clear();
145156
}
146157

147-
public FFmpegBuilder setInput(FFmpegProbeResult result) {
158+
public FFmpegFileInputBuilder setInput(FFmpegProbeResult result) {
148159
clearInputs();
149160
return addInput(result);
150161
}
151162

152-
public FFmpegBuilder setInput(String filename) {
163+
public FFmpegFileInputBuilder setInput(String filename) {
153164
clearInputs();
154165
return addInput(filename);
155166
}
156167

168+
public <T extends AbstractFFmpegInputBuilder<T>> FFmpegBuilder setInput(T input) {
169+
checkNotNull(input);
170+
171+
clearInputs();
172+
inputs.add(input);
173+
174+
return this;
175+
}
176+
157177
public FFmpegBuilder setThreads(int threads) {
158178
checkArgument(threads > 0, "threads must be greater than zero");
159179
this.threads = threads;
@@ -348,8 +368,8 @@ public List<String> build() {
348368

349369
args.addAll(extra_args);
350370

351-
for (String input : inputs) {
352-
args.add("-i", input);
371+
for (AbstractFFmpegInputBuilder<?> input : this.inputs) {
372+
args.addAll(input.build(this, pass));
353373
}
354374

355375
if (pass > 0) {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package net.bramp.ffmpeg.builder;
2+
3+
import net.bramp.ffmpeg.options.EncodingOptions;
4+
import net.bramp.ffmpeg.probe.FFmpegProbeResult;
5+
6+
import java.util.Arrays;
7+
import java.util.Collections;
8+
import java.util.List;
9+
10+
public class FFmpegFileInputBuilder extends AbstractFFmpegInputBuilder<FFmpegFileInputBuilder> {
11+
private final String filename;
12+
13+
public FFmpegFileInputBuilder(String filename) {
14+
this.filename = filename;
15+
}
16+
17+
public FFmpegFileInputBuilder(FFmpegBuilder parent, String filename) {
18+
super(parent);
19+
this.filename = filename;
20+
}
21+
22+
public FFmpegFileInputBuilder(FFmpegBuilder parent, String filename, FFmpegProbeResult result) {
23+
super(parent, result);
24+
this.filename = filename;
25+
26+
}
27+
28+
@Override
29+
protected List<String> buildInputString() {
30+
return Arrays.asList("-i", filename);
31+
}
32+
}

src/test/java/net/bramp/ffmpeg/ExamplesTest.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public void testExample1() throws IOException {
4848
.setFormat("dshow")
4949
.setInput(
5050
"video=\"Microsoft Camera Rear\":audio=\"Microphone Array (Realtek High Definition Audio(SST))\"")
51+
.done()
5152
.addOutput("rtmp://a.rtmp.youtube.com/live2/1234-5678")
5253
.setFormat("flv")
5354
.addExtraArgs("-bufsize", "4000k")
@@ -86,6 +87,7 @@ public void testExample2() throws IOException {
8687
FFmpegBuilder builder =
8788
new FFmpegBuilder()
8889
.setInput("input.mkv")
90+
.done()
8991
.addOutput("output.ogv")
9092
.setVideoCodec("libtheora")
9193
.addExtraArgs("-qscale:v", "7")
@@ -111,6 +113,7 @@ public void testExample3() throws IOException {
111113
FFmpegBuilder builder =
112114
new FFmpegBuilder()
113115
.setInput("sample.avi")
116+
.done()
114117
.addOutput("thumbnail.png")
115118
.setFrames(1)
116119
.setVideoFilter("select='gte(n\\,10)',scale=200:-1")
@@ -132,6 +135,7 @@ public void testExample4() throws IOException {
132135
FFmpegBuilder builder =
133136
new FFmpegBuilder()
134137
.setInput("rtsp://192.168.1.1:1234/")
138+
.done()
135139
.addOutput("img%03d.jpg")
136140
.setFormat("image2")
137141
.done();
@@ -152,7 +156,7 @@ public void testExample5() throws IOException {
152156
FFmpeg ffmpeg = new FFmpeg("/path/to/ffmpeg", func);
153157
FFprobe ffprobe = new FFprobe("/path/to/ffprobe", func);
154158

155-
FFmpegBuilder builder = new FFmpegBuilder().setInput("input").addOutput("output.mp4").done();
159+
FFmpegBuilder builder = new FFmpegBuilder().setInput("input").done().addOutput("output.mp4").done();
156160

157161
FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
158162

@@ -166,6 +170,7 @@ public void testExample6() throws IOException {
166170
FFmpegBuilder builder =
167171
new FFmpegBuilder()
168172
.addInput("image%03d.png")
173+
.done()
169174
.addOutput("output.mp4")
170175
.setVideoFrameRate(FFmpeg.FPS_24)
171176
.done();
@@ -181,7 +186,9 @@ public void testExample7() throws IOException {
181186
FFmpegBuilder builder =
182187
new FFmpegBuilder()
183188
.addInput("original.mp4")
189+
.done()
184190
.addInput("spot.mp4")
191+
.done()
185192
.setComplexFilter(
186193
"[1:v]scale=368:207,setpts=PTS-STARTPTS+5/TB [ov]; "
187194
+ "[0:v][ov] overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2:enable='between(t,5,15)' [v]")
@@ -219,6 +226,7 @@ public void testExample8() throws IOException {
219226
FFmpegBuilder builder =
220227
new FFmpegBuilder()
221228
.addInput("original.mp4")
229+
.done()
222230
.setVideoFilter("select='gte(n\\,10)',scale=200:-1")
223231
.addOutput("hevc-video.mp4")
224232
.addExtraArgs("-tag:v", "hvc1")
@@ -244,6 +252,7 @@ public void testExample9() throws IOException {
244252
new FFmpegBuilder()
245253
.setVerbosity(FFmpegBuilder.Verbosity.DEBUG)
246254
.setInput("input.mp3")
255+
.done()
247256
.overrideOutputFiles(true) // Override the output if it exists
248257
.addOutput("left.mp3")
249258
.addExtraArgs("-map_channel", "0.0.0")
@@ -269,8 +278,11 @@ public void testExample10() throws IOException {
269278
"ffmpeg -y -v error"
270279
+ " -f webm_dash_manifest"
271280
+ " -i audio.webm"
281+
+ " -f webm_dash_manifest"
272282
+ " -i video_1.webm"
283+
+ " -f webm_dash_manifest"
273284
+ " -i video_2.webm"
285+
+ " -f webm_dash_manifest"
274286
+ " -i video_3.webm"
275287
+ " -vcodec copy -acodec copy"
276288
+ " -map 0 -map 1 -map 2 -map 3"
@@ -311,7 +323,7 @@ public void testExample10() throws IOException {
311323
@Test
312324
@Ignore("because this test will invoke /path/to/ffmpeg.")
313325
public void testExample11() throws IOException, InterruptedException {
314-
FFmpegBuilder builder = new FFmpegBuilder().setInput("input").addOutput("output.mp4").done();
326+
FFmpegBuilder builder = new FFmpegBuilder().setInput("input").done().addOutput("output.mp4").done();
315327

316328
List<String> args = new ArrayList<>();
317329
args.add("/path/to/ffmpeg");
@@ -333,6 +345,7 @@ public void testExampleExample() throws IOException {
333345
new FFmpegBuilder()
334346
.setInput("input.mp4")
335347
.setStartOffset(1, TimeUnit.MINUTES)
348+
.done()
336349
.addOutput("output.mp4")
337350
.setDuration(1, TimeUnit.MINUTES)
338351
.setVideoCodec("copy")

src/test/java/net/bramp/ffmpeg/FFmpegExecutorTest.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public void testNormal() throws InterruptedException, ExecutionException, IOExce
8686
.setInput(getWebserverRoot() + Samples.base_big_buck_bunny_720p_1mb)
8787
.addExtraArgs("-probesize", "1000000")
8888
// .setStartOffset(1500, TimeUnit.MILLISECONDS)
89+
.done()
8990
.overrideOutputFiles(true)
9091
.addOutput(Samples.output_mp4)
9192
.setFrames(100)
@@ -121,6 +122,7 @@ public void testTwoPass() throws InterruptedException, ExecutionException, IOExc
121122
FFmpegBuilder builder =
122123
new FFmpegBuilder()
123124
.setInput(in)
125+
.done()
124126
.overrideOutputFiles(true)
125127
.addOutput(Samples.output_mp4)
126128
.setFormat("mp4")
@@ -143,6 +145,7 @@ public void testFilter() throws InterruptedException, ExecutionException, IOExce
143145
FFmpegBuilder builder =
144146
new FFmpegBuilder()
145147
.setInput(Samples.big_buck_bunny_720p_1mb)
148+
.done()
146149
.overrideOutputFiles(true)
147150
.addOutput(Samples.output_mp4)
148151
.setFormat("mp4")
@@ -163,6 +166,7 @@ public void testMetaTags() throws InterruptedException, ExecutionException, IOEx
163166
FFmpegBuilder builder =
164167
new FFmpegBuilder()
165168
.setInput(Samples.big_buck_bunny_720p_1mb)
169+
.done()
166170
.overrideOutputFiles(true)
167171
.addOutput(Samples.output_mp4)
168172
.setFormat("mp4")
@@ -187,6 +191,7 @@ public void testStdout() throws InterruptedException, ExecutionException, IOExce
187191
FFmpegBuilder builder =
188192
new FFmpegBuilder()
189193
.setInput(Samples.big_buck_bunny_720p_1mb)
194+
.done()
190195
.addStdoutOutput()
191196
.setFormat("s8")
192197
.setAudioChannels(1)
@@ -217,6 +222,7 @@ public void testProgress() throws InterruptedException, ExecutionException, IOEx
217222
new FFmpegBuilder()
218223
.readAtNativeFrameRate() // Slows the test down
219224
.setInput(in)
225+
.done()
220226
.overrideOutputFiles(true)
221227
.addOutput(Samples.output_mp4)
222228
.done();
@@ -240,9 +246,11 @@ public void testProgress() throws InterruptedException, ExecutionException, IOEx
240246
public void testIssue112() {
241247
FFmpegBuilder builder =
242248
new FFmpegBuilder()
243-
.setInput(Samples.testscreen_jpg)
244-
.addInput(Samples.test_mp3)
249+
.addInput(Samples.testscreen_jpg)
245250
.addExtraArgs("-loop", "1")
251+
.done()
252+
.addInput(Samples.test_mp3)
253+
.done()
246254
.overrideOutputFiles(true)
247255
.addOutput(Samples.output_mp4)
248256
.setFormat("mp4")

src/test/java/net/bramp/ffmpeg/ReadmeTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ public void testVideoEncoding() throws IOException {
4444
FFmpegBuilder builder =
4545
new FFmpegBuilder()
4646
.setInput(inFilename) // Filename, or a FFmpegProbeResult
47+
.done()
4748
.setInput(in)
49+
.done()
4850
.overrideOutputFiles(true) // Override the output if it exists
4951
.addOutput("output.mp4") // Filename for the destination
5052
.setFormat("mp4") // Format is inferred from filename, or can be set
@@ -109,6 +111,7 @@ public void testProgress() throws IOException {
109111
FFmpegBuilder builder =
110112
new FFmpegBuilder()
111113
.setInput(in) // Or filename
114+
.done()
112115
.addOutput("output.mp4")
113116
.done();
114117

0 commit comments

Comments
 (0)