Skip to content

Commit

Permalink
Merge pull request #142 from kokorin/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
kokorin authored Apr 20, 2021
2 parents 5547dc8 + 3604f4d commit cefd58f
Show file tree
Hide file tree
Showing 37 changed files with 430 additions and 293 deletions.
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ See whole example [here](/src/test/java/examples/ReEncodeExample.java).
final AtomicLong duration = new AtomicLong();
FFmpeg.atPath()
.addInput(UrlInput.fromUrl(pathToSrc))
.addOutput(new NullOutput())
.setOverwriteOutput(true)
.addOutput(new NullOutput())
.setProgressListener(new ProgressListener() {
@Override
public void onProgress(FFmpegProgress progress) {
Expand All @@ -100,6 +100,8 @@ FFmpeg.atPath()

FFmpeg.atPath()
.addInput(UrlInput.fromUrl(pathToSrc))
.setOverwriteOutput(true)
.addArguments("-movflags", "faststart")
.addOutput(UrlOutput.toUrl(pathToDst))
.setProgressListener(new ProgressListener() {
@Override
Expand All @@ -108,7 +110,6 @@ FFmpeg.atPath()
System.out.println("Progress: " + percents + "%");
}
})
.setOverwriteOutput(true)
.execute();
```

Expand All @@ -121,16 +122,17 @@ See whole example [here](/src/test/java/examples/CutAndScaleExample.java).
```java
FFmpeg.atPath()
.addInput(
UrlInput.fromUrl(pathToSrc)
.setPosition(10, TimeUnit.SECONDS)
.setDuration(42, TimeUnit.SECONDS)
)
.addOutput(
UrlOutput.toUrl(pathToDst)
.setPosition(10, TimeUnit.SECONDS)
UrlInput.fromUrl(pathToSrc)
.setPosition(10, TimeUnit.SECONDS)
.setDuration(42, TimeUnit.SECONDS)
)
.setFilter(StreamType.VIDEO, "scale=160:-2")
.setOverwriteOutput(true)
.addArguments("-movflags", "faststart")
.addOutput(
UrlOutput.toUrl(pathToDst)
.setPosition(10, TimeUnit.SECONDS)
)
.execute();
```

Expand Down Expand Up @@ -265,7 +267,7 @@ FrameProducer producer = new FrameProducer() {
graphics.setPaint(new Color(frameCounter * 1.0f / 30, 0, 0));
graphics.fillRect(0, 0, 320, 240);
long pts = frameCounter * 1000 / 10; // Frame PTS in Stream Timebase
Frame videoFrame = new Frame(0, pts, image);
Frame videoFrame = Frame.createVideoFrame(0, pts, image);
frameCounter++;

return videoFrame;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ public CaptureInput<T> setCaptureVideoSize(String size) {
*/
public abstract CaptureInput<T> setCaptureCursor(boolean captureCursor);

// TODO check static method references
public static CaptureInput<?> captureDesktop() {
CaptureInput<?> result = null;
if (OS.IS_LINUX) {
Expand Down
79 changes: 42 additions & 37 deletions src/main/java/com/github/kokorin/jaffree/ffmpeg/FFmpeg.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,18 @@
* {@link FFmpeg} provides an ability to start &amp; stop ffmpeg process and keep track of
* encoding progress.
*/
//TODO add debug statements for all methods
public class FFmpeg {
private final List<Input> inputs = new ArrayList<>();
private final List<Output> outputs = new ArrayList<>();
private final List<String> additionalArguments = new ArrayList<>();
//TODO make it Boolean (non-primitive)
private boolean overwriteOutput;
private ProgressListener progressListener;
private OutputListener outputListener;
private String progress;
//-filter_threads nb_threads (global)
//-debug_ts (global)
private FilterGraph complexFilter;

/**
* A map with 0 or 1 filter per stream type. Type can be "a" (audio), "v" (video) or "" (plain 'filter')
*/
private String complexFilter;
private final Map<String, Object> filters = new HashMap<>();

private LogLevel logLevel = LogLevel.INFO;
Expand Down Expand Up @@ -149,55 +144,74 @@ public FFmpeg addArguments(final String key, final String value) {
* applied to one stream. This is the case, for example, when the graph has more than one input
* and/or output, or when output stream type is different from input.
*
* @param graph complex filter graph
* @param complexFilter complex filter graph
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#toc-Filtergraph-syntax-1">
* Filtergraph syntax</a>
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Complex-filtergraphs">
* Complex filtergraph</a>
*/
// TODO overload with String parameter
public FFmpeg setComplexFilter(final FilterGraph graph) {
this.complexFilter = graph;
public FFmpeg setComplexFilter(final FilterGraph complexFilter) {
return setComplexFilter(complexFilter.getValue());
}

/**
* Adds complex filter graph to ffmpeg arguments list.
* <p>
* Complex filtergraphs are those which cannot be described as simply a linear processing chain
* applied to one stream. This is the case, for example, when the graph has more than one input
* and/or output, or when output stream type is different from input.
*
* @param complexFilter complex filter graph
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#toc-Filtergraph-syntax-1">
* Filtergraph syntax</a>
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Complex-filtergraphs">
* Complex filtergraph</a>
*/
public FFmpeg setComplexFilter(final String complexFilter) {
this.complexFilter = complexFilter;
return this;
}

/**
* Sets the 'generic' filter value (equivalent to the "-filter" command-line parameter).
*
* @param filter a String describing the filter to apply
* @param filter a FilterGraph describing the filter to apply
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Simple-filtergraphs">Simple filtergraphs</a>
*/
public FFmpeg setFilter(String filter) {
return setFilter("", filter);
public FFmpeg setFilter(FilterGraph filter) {
return setFilter(filter.getValue());
}

/**
* Sets the 'generic' filter value (equivalent to the "-filter" command-line parameter).
*
* @param filter a FilterGraph describing the filter to apply
* @param filter a String describing the filter to apply
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Simple-filtergraphs">Simple filtergraphs</a>
*/
public FFmpeg setFilter(FilterGraph filter) {
return setFilter("", filter.getValue());
public FFmpeg setFilter(String filter) {
return setFilter((String) null, filter);
}

/**
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v" command-line parameters).
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v"
* command-line parameters).
*
* @param streamType the stream type to apply this filter to (StreamType.AUDIO or StreamType.VIDEO)
* @param filterGraph a graph describing the filters to apply
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Simple-filtergraphs">Simple filtergraphs</a>
*/
public FFmpeg setFilter(StreamType streamType, FilterGraph filterGraph) {
return setFilter(streamType.code(), filterGraph.getValue());
return setFilter(streamType, filterGraph.getValue());
}

/**
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v" command-line parameters).
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v"
* command-line parameters).
*
* @param streamType the stream type to apply this filter to (StreamType.AUDIO or StreamType.VIDEO)
* @param filter a String describing the filter to apply
Expand All @@ -209,9 +223,11 @@ public FFmpeg setFilter(StreamType streamType, String filter) {
}

/**
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v" / "-filter" command-line parameters).
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v" / "-filter"
* command-line parameters).
*
* @param streamSpecifier a String specifying to which stream this filter must be applied ("a" for audio, "v" "for video, or "" for generic 'filter')
* @param streamSpecifier a String specifying to which stream this filter must be applied ("a" for audio,
* "v" "for video, or "" for generic 'filter')
* @param filterGraph a graph describing the filters to apply
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Simple-filtergraphs">Simple filtergraphs</a>
Expand All @@ -221,29 +237,20 @@ public FFmpeg setFilter(String streamSpecifier, FilterGraph filterGraph) {
}

/**
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v" / "-filter" command-line parameters).
* Sets a 'stream specific' filter value (equivalent to the "-av" / "-filter:a" or "-fv" / "-filter:v" / "-filter"
* command-line parameters).
*
* @param streamSpecifier a String specifying to which stream this filter must be applied ("a" for audio, "v" "for video, or "" for generic 'filter')
* @param streamSpecifier a String specifying to which stream this filter must be applied ("a" for audio,
* "v" "for video, or "" for generic 'filter')
* @param filter a String describing the filter to apply
* @return this
* @see <a href="https://ffmpeg.org/ffmpeg-all.html#Simple-filtergraphs">Simple filtergraphs</a>
*/
public FFmpeg setFilter(String streamSpecifier, String filter) {
// If a previous filter was set, warn that it is replaced by the new one
final String previousFilter = (String) filters.get(streamSpecifier);
if (previousFilter != null) {
if (streamSpecifier.isEmpty()) {
LOGGER.warn("Only one generic filter is supported. Ignoring previous filter '" + previousFilter + "'.");
} else {
LOGGER.error("Only one filter per stream is supported. Ignoring previous filter '" + previousFilter + "' for stream '" + streamSpecifier + "'.");
}
}
// Store the new filter
filters.put(streamSpecifier, filter);
return this;
}


/**
* Whether to overwrite output. False by default.
* <p>
Expand Down Expand Up @@ -404,8 +411,6 @@ protected StdReader<FFmpegResult> createStdErrReader(OutputListener outputListen
* @return this
*/
protected StdReader<FFmpegResult> createStdOutReader() {
// TODO ffmpeg normally doesn't write to Std OUT, stdOutReader should throw an error
// if it reads any byte
return new LoggingStdReader<>();
}

Expand Down Expand Up @@ -467,7 +472,7 @@ protected List<String> buildArguments() {
}

if (complexFilter != null) {
result.addAll(Arrays.asList("-filter_complex", complexFilter.getValue()));
result.addAll(Arrays.asList("-filter_complex", complexFilter));
}

result.addAll(BaseInOut.toArguments("-filter", filters));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,10 @@ public FFmpegResult get(long timeout, TimeUnit unit) throws InterruptedException
return resultFuture.get(timeout, unit);
}

// TODO check if required or replace with more suitable method
public boolean isCancelled() {
return resultFuture.isCancelled();
}

// TODO check if required or replace with more suitable method
public boolean isDone() {
return resultFuture.isDone();
}
Expand Down
53 changes: 26 additions & 27 deletions src/main/java/com/github/kokorin/jaffree/ffmpeg/Frame.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,6 @@ public class Frame {
private final BufferedImage image;
private final int[] samples;

/**
* Creates video {@link Frame}, samples are set to null.
*
* @param streamId stream id (starting with 0)
* @param pts pts in {@link Stream} timebase
* @param image video frame image
* @see Stream#getTimebase()
*/
// TODO make static method
public Frame(final int streamId, final long pts, final BufferedImage image) {
this(streamId, pts, image, null);
}

/**
* Creates audio {@link Frame}, image is set to null.
*
* @param streamId streamId
* @param pts pts in {@link Stream} timebase
* @param samples audio samples in PCM S32BE format
* @see Stream#getTimebase()
*/
// TODO make static method
public Frame(final int streamId, final long pts, final int[] samples) {
this(streamId, pts, null, samples);
}

/**
* Creates {@link Frame}.
*
Expand All @@ -67,7 +41,7 @@ public Frame(final int streamId, final long pts, final int[] samples) {
* @param samples audio samples in PCM S32BE format
* @see Stream#getTimebase()
*/
public Frame(final int streamId, final long pts, final BufferedImage image,
protected Frame(final int streamId, final long pts, final BufferedImage image,
final int[] samples) {
if (image != null && samples != null) {
throw new IllegalArgumentException(
Expand Down Expand Up @@ -133,4 +107,29 @@ public String toString() {
+ ", samples?=" + (samples != null)
+ '}';
}

/**
* Creates video {@link Frame}, samples are set to null.
*
* @param streamId stream id (starting with 0)
* @param pts pts in {@link Stream} timebase
* @param image video frame image
* @see Stream#getTimebase()
*/
public static Frame createVideoFrame(final int streamId, final long pts, final BufferedImage image) {
return new Frame(streamId, pts, image, null);
}

/**
* Creates audio {@link Frame}, image is set to null.
*
* @param streamId streamId
* @param pts pts in {@link Stream} timebase
* @param samples audio samples in PCM S32BE format
* @see Stream#getTimebase()
*/
public static Frame createAudioFrame(final int streamId, final long pts, final int[] samples) {
return new Frame(streamId, pts, null, samples);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ private void write(final NutWriter writer) throws IOException {

case AUDIO:
data = new byte[frame.getSamples().length * 4];
// TODO check number of samples provided
ByteBuffer.wrap(data).asIntBuffer().put(frame.getSamples());
break;

Expand Down
21 changes: 5 additions & 16 deletions src/main/java/com/github/kokorin/jaffree/ffmpeg/PipeInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,18 @@
* @see ChannelInput
*/
public class PipeInput extends TcpInput<PipeInput> implements Input {
private final PipeInputNegotiator negotiator;
private static final int DEFAULT_BUFFER_SIZE = 1_000_000;

public PipeInput(InputStream source) {
this(new PipeInputNegotiator(source));
}

public PipeInput(PipeInputNegotiator negotiator) {
super(negotiator);
this.negotiator = negotiator;
}

public PipeInput setBufferSize(int bufferSize) {
negotiator.setBufferSize(bufferSize);
return this;
protected PipeInput(final InputStream source, final int bufferSize) {
super(new PipeInputNegotiator(source, bufferSize));
}

public static PipeInput pumpFrom(InputStream source) {
return new PipeInput(source);
return pumpFrom(source, DEFAULT_BUFFER_SIZE);
}

public static PipeInput pumpFrom(InputStream source, int bufferSize) {
return pumpFrom(source)
.setBufferSize(bufferSize);
return new PipeInput(source, bufferSize);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public class Stream {
private Long timebase;
private Integer width;
private Integer height;
//TODO check if sampleRate can have Integer type
private Long sampleRate;
private Integer channels;

Expand Down
Loading

0 comments on commit cefd58f

Please sign in to comment.