Skip to content

Commit

Permalink
Local Filters implemented. First demo: Black&White
Browse files Browse the repository at this point in the history
  • Loading branch information
olir committed Mar 18, 2018
1 parent 34f3534 commit f34f408
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 28 deletions.
63 changes: 59 additions & 4 deletions src/main/java/de/screenflow/frankenstein/MovieProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@
import de.screenflow.frankenstein.task.Task;
import de.screenflow.frankenstein.task.TaskHandler;
import de.screenflow.frankenstein.task.TimeTaskHandler;
import de.screenflow.frankenstein.vf.FilterElement;
import de.screenflow.frankenstein.vf.VideoFilter;
import de.screenflow.frankenstein.vf.VideoStreamSource;
import de.screenflow.frankenstein.vf.input.VideoInput;
import javafx.collections.ObservableList;

public class MovieProcessor {

private final String ffmpegPath;
private final File tempPath;
private final List<VideoFilter> filters;
private final Configuration configuration;
private final List<VideoFilter> filters;
private List<FilterElement> localFilters;

// private final VideoCapture movie = null;
private VideoWriter outputVideo;
Expand Down Expand Up @@ -111,6 +114,17 @@ public void init(ProcessingListener l) {
currentPos = 1;
}

public void applyLocalFilters(List<FilterElement> filterListData) {
localFilters = filterListData;
if (localFilters != null && !localFilters.isEmpty()) {
for (FilterElement element : localFilters) {
if (element.filter != null) {
element.filter.configure(frame);
}
}
}
}

public void processStreamFrame(ProcessingListener l) {
currentPos = 1;

Expand All @@ -120,7 +134,20 @@ public void processStreamFrame(ProcessingListener l) {
for (VideoFilter filter : filters) {
// System.out.println("MovieProcessor processStreamFrame " +
// filter.getClass().getName());
newFrame = filter.process(newFrame, 1);
newFrame = filter.process(newFrame, currentPos);
}
if (localFilters != null && !localFilters.isEmpty()) {
for (FilterElement element : localFilters) {
if (element.filter != null) {
if (element.r.start <= currentPos && currentPos < element.r.end) {
// System.out.println("MovieProcessor
// processStreamFrame
// " +
// element.filter);
newFrame = element.filter.process(newFrame, currentPos);
}
}
}
}
if (l != null)
l.nextFrameProcessed(newFrame, currentPos);
Expand Down Expand Up @@ -195,6 +222,19 @@ public boolean process(ProcessingListener l) {
} else {
newFrame = frame;
}
if (localFilters != null && !localFilters.isEmpty()) {
for (FilterElement element : localFilters) {
if (element.filter != null) {
if (element.r.start <= i && i < element.r.end) {
// System.out.println("MovieProcessor
// processStreamFrame
// " +
// element.filter);
newFrame = element.filter.process(newFrame, i);
}
}
}
}

if (configuration.doOutput) {
if (movie_w != newFrame.cols() || movie_h != newFrame.rows())
Expand Down Expand Up @@ -342,10 +382,13 @@ public boolean openOutput(ProcessingListener l) {
// Store temp Video next to output to avoid SSD must be used for
// large files.
File tempFile = File.createTempFile("video", "." + tempOutputFormat, tempPath);
tempVideoFile = new File(new File(configuration.outputVideo).getParentFile(), tempFile.getName());
tempFile.deleteOnExit();
tempVideoFile = new File(new File(configuration.outputVideo).getParentFile(), tempFile.getName());
tempVideoFile.deleteOnExit();
tempAudioFile = File.createTempFile("sound", ".mp3", tempPath);
tempAudioFile.deleteOnExit();
tempMetadataFile = File.createTempFile("metadata", ".properties", tempPath);
tempMetadataFile.deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
return false;
Expand Down Expand Up @@ -402,6 +445,19 @@ public void seek(final ProcessingListener l, int frameId) {
// "+filter.getClass().getName());
newFrame = filter.process(newFrame, frameId);
}
if (localFilters != null && !localFilters.isEmpty()) {
for (FilterElement element : localFilters) {
if (element.filter != null) {
if (element.r.start <= currentPos && currentPos < element.r.end) {
// System.out.println("MovieProcessor
// processStreamFrame
// " +
// element.filter);
newFrame = element.filter.process(newFrame, currentPos);
}
}
}
}
if (l != null)
l.nextFrameProcessed(newFrame, currentPos);
} else {
Expand Down Expand Up @@ -481,5 +537,4 @@ public void handleLine(String line) {
return devices;
return devices;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,47 @@
package de.screenflow.frankenstein.fxml;

import de.screenflow.frankenstein.vf.LocalVideoFilter;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.stage.Stage;

public class FilterSetupController {

@FXML ComboBox<LocalVideoFilter> cbFilter;

private ProcessingSceneController parent;

private Stage stage;

private LocalVideoFilter selectedFilter = null;

public void configure(ProcessingSceneController parent, Stage stage) {
this.parent = parent;
this.stage = stage;

cbFilter.getItems().setAll(parent.getLocalFilters());

cbFilter.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<LocalVideoFilter>() {
@Override public void changed(ObservableValue<? extends LocalVideoFilter> selected, LocalVideoFilter oldFilter, LocalVideoFilter newFilter) {
if (oldFilter != null) {
selectedFilter = null;
}
if (newFilter != null) {
selectedFilter = newFilter;
}
}
});
}

public void ok() {
System.out.println("ok");
stage.close();
}

public LocalVideoFilter getSelectedFilterType() {
return selectedFilter;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@
import de.screenflow.frankenstein.Configuration;
import de.screenflow.frankenstein.MovieProcessor;
import de.screenflow.frankenstein.ProcessingListener;
import de.screenflow.frankenstein.vf.FilterElement;
import de.screenflow.frankenstein.vf.LocalVideoFilter;
import de.screenflow.frankenstein.vf.VideoFilter;
import de.screenflow.frankenstein.vf.VideoStreamSource;
import de.screenflow.frankenstein.vf.local.BWFilter;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
Expand Down Expand Up @@ -76,7 +79,7 @@ public class ProcessingSceneController implements ProcessingListener {
private int markPosition = -1;
private int seekPos;

private double fps;
public double fps;
private int frames;

private FilterElement selectedFilter;
Expand All @@ -91,6 +94,11 @@ public class ProcessingSceneController implements ProcessingListener {

public final ObservableList<FilterElement> filterListData = FXCollections.observableArrayList();

boolean streamRunning = false;

private List<LocalVideoFilter> localFilters;


@FXML
BorderPane rootBorder;

Expand Down Expand Up @@ -208,6 +216,9 @@ public void changed(ObservableValue<? extends FilterElement> observable, FilterE
}
});

localFilters = new ArrayList<LocalVideoFilter>();
localFilters.add(new BWFilter());

updateDuration();

Platform.runLater(() -> {
Expand Down Expand Up @@ -525,7 +536,7 @@ private void adjustVideoLengthDisplay() {
}
}

private String time(double t) {
public String time(double t) {
try {
LocalTime lt = LocalTime.ofNanoOfDay((long) (t * 1000000000.0));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SS");
Expand Down Expand Up @@ -674,8 +685,6 @@ public void processingDone() {
});
}

boolean streamRunning = false;

@FXML
public void startButtonPressed() {
if (streamRunning) {
Expand Down Expand Up @@ -815,7 +824,7 @@ private void updateDuration() {

@FXML
public void filterAdd() {
FilterElement val = new FilterElement(currentRange());
FilterElement val = new FilterElement(currentRange(), this);
filterListData.add(val);
Platform.runLater(() -> {
drawEditCanvas();
Expand All @@ -825,18 +834,23 @@ public void filterAdd() {
@FXML
public void filterSetup() {

FilterSetupController controller = new FilterSetupController();
PropertyResourceBundle bundleConfiguration = (PropertyResourceBundle) ResourceBundle
.getBundle("de/screenflow/frankenstein/bundles/filtersetup", FxMain.getLocale());
FXMLLoader loader = new FXMLLoader(getClass().getResource("FilterSetupPopup.fxml"), bundleConfiguration);
Stage stage = new Stage();
try {
stage.setScene(new Scene(loader.load()));
FilterSetupController controller = (FilterSetupController) loader.getController();
controller.configure(this, stage);
stage.setTitle("Edit filter " + selectedFilter.toStringRange());
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(btnListFilter.getScene().getWindow());
stage.showAndWait();
LocalVideoFilter f = controller.getSelectedFilterType().getInstance();
selectedFilter.setType(f);
processor.applyLocalFilters(filterListData);
Platform.runLater(() -> {
listViewFilter.refresh();
drawEditCanvas();
});
} catch (IOException e) {
Expand All @@ -853,23 +867,6 @@ public void filterDelete() {
});
}

class FilterElement {
Range r;
VideoFilter filter = null;

FilterElement(Range r) {
FilterElement.this.r = r;
}

public String toString() {
return toStringRange() + " " + (filter != null ? filter : "<none>");
}

public String toStringRange() {
return "" + time((r.start - 1.0) / fps) + "-" + time((r.end - 1.0) / fps) + " " + r.toString();
}
}

@FXML
public void tfActionTime(ActionEvent event) {
try {
Expand Down Expand Up @@ -927,4 +924,8 @@ public void run() {
new Thread(r).start();
}

public List<LocalVideoFilter> getLocalFilters() {
return localFilters;
}

}
28 changes: 28 additions & 0 deletions src/main/java/de/screenflow/frankenstein/vf/FilterElement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package de.screenflow.frankenstein.vf;

import org.opencv.core.Range;

import de.screenflow.frankenstein.fxml.ProcessingSceneController;

public class FilterElement {
public Range r;
public LocalVideoFilter filter = null;
ProcessingSceneController psc;

public FilterElement(Range r, ProcessingSceneController psc) {
FilterElement.this.r = r;
this.psc = psc;
}

public void setType(LocalVideoFilter selectedFilterType) {
filter = selectedFilterType;
}

public String toString() {
return toStringRange() + " " + (filter != null ? filter : "<none>");
}

public String toStringRange() {
return "" + psc.time((r.start - 1.0) / psc.fps) + "-" + psc.time((r.end - 1.0) / psc.fps) + " " + r.toString();
}
}
20 changes: 20 additions & 0 deletions src/main/java/de/screenflow/frankenstein/vf/LocalVideoFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2017 Oliver Rode, https://github.com/olir/Frankenstein
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.screenflow.frankenstein.vf;

public interface LocalVideoFilter extends VideoFilter {
LocalVideoFilter getInstance();
}

0 comments on commit f34f408

Please sign in to comment.