No flags found
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
b9e203b
... +2 ...
6f7a235
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
5 | 5 | import java.io.IOException; |
|
6 | 6 | import java.io.InputStreamReader; |
|
7 | 7 | import java.nio.charset.StandardCharsets; |
|
8 | + | import java.util.ArrayList; |
|
8 | 9 | import java.util.Arrays; |
|
9 | 10 | import java.util.List; |
|
10 | 11 | ||
11 | 12 | import org.slf4j.Logger; |
|
12 | - | import org.slf4j.LoggerFactory; |
|
13 | 13 | ||
14 | 14 | import com.google.common.base.Joiner; |
|
15 | 15 | import com.google.common.collect.Lists; |
|
16 | 16 | import com.google.common.io.Files; |
|
17 | 17 | ||
18 | 18 | import nl.weeaboo.common.Checks; |
|
19 | + | import nl.weeaboo.common.StringUtil; |
|
19 | 20 | import nl.weeaboo.vn.buildtools.file.EncodedResource; |
|
20 | 21 | import nl.weeaboo.vn.buildtools.file.IEncodedResource; |
|
21 | 22 | import nl.weeaboo.vn.buildtools.file.ITempFileProvider; |
|
22 | - | import nl.weeaboo.vn.buildtools.optimizer.video.encoder.FfmpegVideoEncoder; |
|
23 | 23 | ||
24 | 24 | /** |
|
25 | 25 | * Resource encoder using ffmpeg. |
|
26 | 26 | */ |
|
27 | 27 | public abstract class FfmpegEncoder { |
|
28 | 28 | ||
29 | - | private static final Logger LOG = LoggerFactory.getLogger(FfmpegVideoEncoder.class); |
|
30 | - | ||
29 | + | private final Logger logger; |
|
31 | 30 | private final ITempFileProvider tempFileProvider; |
|
32 | 31 | ||
33 | - | protected FfmpegEncoder(ITempFileProvider tempFileProvider) { |
|
32 | + | private String program = "ffmpeg"; |
|
33 | + | ||
34 | + | protected FfmpegEncoder(Logger logger, ITempFileProvider tempFileProvider) { |
|
35 | + | this.logger = Checks.checkNotNull(logger); |
|
34 | 36 | this.tempFileProvider = Checks.checkNotNull(tempFileProvider); |
|
35 | 37 | } |
|
36 | 38 | ||
37 | 39 | /** |
|
38 | 40 | * @return {@code true} if a usable ffmpeg executable was found, allowing this encoder to be used. |
|
39 | 41 | */ |
|
40 | - | public static boolean isAvailable() { |
|
42 | + | public boolean isAvailable() { |
|
41 | 43 | try { |
|
42 | - | doRunProcess(Arrays.asList("ffmpeg", "-h")); |
|
43 | - | LOG.debug("ffmpeg is available"); |
|
44 | + | doRunProcess(program, Arrays.asList("-h")); |
|
45 | + | logger.debug("ffmpeg is available"); |
|
44 | 46 | return true; |
|
45 | 47 | } catch (IOException e) { |
|
46 | - | LOG.info("ffmpeg not available: {}", e.toString()); |
|
48 | + | logger.info("ffmpeg not available: {}", e.toString()); |
|
47 | 49 | return false; |
|
48 | 50 | } |
|
49 | 51 | } |
57 | 59 | // Copy sound to temp file (input) |
|
58 | 60 | Files.write(resource.readBytes(), inputFile); |
|
59 | 61 | ||
60 | - | runProcess(getCommandLineArgs(inputFile, outputFile)); |
|
62 | + | runProcess(program, getCommandLineArgs(inputFile, outputFile)); |
|
61 | 63 | resultAudioData = EncodedResource.fromTempFile(outputFile); |
|
62 | 64 | } finally { |
|
63 | 65 | inputFile.delete(); |
66 | 68 | return resultAudioData; |
|
67 | 69 | } |
|
68 | 70 | ||
69 | - | protected void runProcess(List<String> command) throws IOException { |
|
70 | - | doRunProcess(command); |
|
71 | + | protected void runProcess(String program, List<String> args) throws IOException { |
|
72 | + | doRunProcess(program, args); |
|
71 | 73 | } |
|
72 | 74 | ||
73 | - | private static void doRunProcess(List<String> command) throws IOException { |
|
75 | + | private void doRunProcess(String program, List<String> args) throws IOException { |
|
76 | + | List<String> command = new ArrayList<>(); |
|
77 | + | command.add(program); |
|
78 | + | command.addAll(args); |
|
74 | 79 | String commandString = Joiner.on(' ').join(command); |
|
75 | 80 | ||
81 | + | logger.trace("Starting process: {}", command); |
|
82 | + | ||
76 | 83 | Process process = new ProcessBuilder() |
|
77 | 84 | .command(command) |
|
78 | 85 | .redirectErrorStream(true) |
85 | 92 | while (process.isAlive()) { |
|
86 | 93 | String line = in.readLine(); |
|
87 | 94 | ||
88 | - | LOG.trace(line); |
|
95 | + | logger.trace(line); |
|
89 | 96 | ||
90 | 97 | output.append(line); |
|
91 | 98 | output.append('\n'); |
|
92 | 99 | } |
|
93 | 100 | ||
94 | 101 | int exitCode = process.waitFor(); |
|
95 | 102 | if (exitCode != 0) { |
|
96 | - | throw new IOException("Process terminated with an error: " + exitCode |
|
97 | - | + "\ncommand: " + commandString |
|
98 | - | + "\noutput: " + output); |
|
103 | + | throw new IOException(StringUtil.formatRoot( |
|
104 | + | "Process terminated with an error: %s\ncommand: %s\noutput: %s", |
|
105 | + | exitCode, commandString, output)); |
|
99 | 106 | } |
|
100 | 107 | } catch (InterruptedException e) { |
|
101 | 108 | throw new IOException("Process interrupted", e); |
|
102 | 109 | } |
|
103 | 110 | } |
|
104 | 111 | ||
105 | 112 | private List<String> getCommandLineArgs(File inputFile, File outputFile) { |
|
106 | - | List<String> command = Lists.newArrayList(); |
|
107 | - | command.add("ffmpeg"); |
|
113 | + | List<String> args = Lists.newArrayList(); |
|
108 | 114 | ||
109 | 115 | // Input file |
|
110 | - | command.add("-i"); |
|
111 | - | command.add(inputFile.getAbsolutePath()); |
|
116 | + | args.add("-i"); |
|
117 | + | args.add(inputFile.getAbsolutePath()); |
|
112 | 118 | ||
113 | 119 | // File format (container) |
|
114 | - | command.add("-f"); |
|
115 | - | command.add(getFileFormat()); |
|
120 | + | args.add("-f"); |
|
121 | + | args.add(getFileFormat()); |
|
116 | 122 | ||
117 | 123 | // Codec |
|
118 | - | command.addAll(getCodecArgs()); |
|
124 | + | args.addAll(getCodecArgs()); |
|
119 | 125 | ||
120 | 126 | // Output file |
|
121 | - | command.add("-y"); // Overwrite output file (is usually an empty temp file) |
|
122 | - | command.add(outputFile.getAbsolutePath()); |
|
123 | - | return command; |
|
127 | + | args.add("-y"); // Overwrite output file (is usually an empty temp file) |
|
128 | + | args.add(outputFile.getAbsolutePath()); |
|
129 | + | return args; |
|
130 | + | } |
|
131 | + | ||
132 | + | public void setProgram(String program) { |
|
133 | + | this.program = program; |
|
124 | 134 | } |
|
125 | 135 | ||
126 | 136 | protected abstract List<String> getCodecArgs(); |
54 | 54 | // --- State during optimization --- |
|
55 | 55 | /** Definition per (optimized) sound file */ |
|
56 | 56 | private final Map<FilePath, SoundDefinition> optimizedDefs = Maps.newHashMap(); |
|
57 | - | private boolean ffmpegAvailable; |
|
58 | - | ||
57 | + | private EAvailable ffmpegAvailable; |
|
59 | 58 | ||
60 | 59 | public SoundOptimizer(IOptimizerContext context) { |
|
61 | 60 | executor = context.getExecutor(); |
66 | 65 | NvlistProjectConnection project = context.getProject(); |
|
67 | 66 | resFileSystem = project.getResFileSystem(); |
|
68 | 67 | soundDefCache = new SoundDefinitionCache(resFileSystem); |
|
68 | + | ||
69 | + | resetState(); |
|
69 | 70 | } |
|
70 | 71 | ||
71 | 72 | private void resetState() { |
|
72 | 73 | optimizedDefs.clear(); |
|
73 | 74 | ||
74 | - | ffmpegAvailable = FfmpegSoundEncoder.isAvailable(); |
|
75 | + | ffmpegAvailable = EAvailable.UNKNOWN; |
|
75 | 76 | } |
|
76 | 77 | ||
77 | 78 | /** |
162 | 163 | } |
|
163 | 164 | ||
164 | 165 | private ISoundEncoder createEncoder() { |
|
165 | - | if (ffmpegAvailable) { |
|
166 | - | return new FfmpegSoundEncoder(tempFileProvider); |
|
167 | - | } else { |
|
168 | - | return new NoOpSoundEncoder(); |
|
166 | + | if (ffmpegAvailable != EAvailable.NO) { |
|
167 | + | FfmpegSoundEncoder encoder = new FfmpegSoundEncoder(tempFileProvider); |
|
168 | + | if (ffmpegAvailable == EAvailable.YES || encoder.isAvailable()) { |
|
169 | + | ffmpegAvailable = EAvailable.YES; |
|
170 | + | return encoder; |
|
171 | + | } |
|
169 | 172 | } |
|
173 | + | ffmpegAvailable = EAvailable.NO; |
|
174 | + | return new NoOpSoundEncoder(); |
|
170 | 175 | } |
|
171 | 176 | ||
172 | 177 | private FilePath getOutputPath(FilePath inputPath, String outputFilename) { |
|
173 | 178 | FilePath folder = inputPath.getParent(); |
|
174 | 179 | return folder.resolve(outputFilename); |
|
175 | 180 | } |
|
176 | 181 | ||
182 | + | private enum EAvailable { |
|
183 | + | YES, NO, UNKNOWN |
|
184 | + | } |
|
177 | 185 | } |
4 | 4 | import java.util.Arrays; |
|
5 | 5 | import java.util.List; |
|
6 | 6 | ||
7 | + | import org.slf4j.Logger; |
|
8 | + | import org.slf4j.LoggerFactory; |
|
9 | + | ||
10 | + | import com.google.common.annotations.VisibleForTesting; |
|
11 | + | ||
7 | 12 | import nl.weeaboo.io.Filenames; |
|
8 | 13 | import nl.weeaboo.vn.buildtools.file.IEncodedResource; |
|
9 | 14 | import nl.weeaboo.vn.buildtools.file.ITempFileProvider; |
15 | 20 | */ |
|
16 | 21 | public final class FfmpegVideoEncoder extends FfmpegEncoder implements IVideoEncoder { |
|
17 | 22 | ||
23 | + | private static final Logger LOG = LoggerFactory.getLogger(FfmpegVideoEncoder.class); |
|
24 | + | ||
18 | 25 | private static final String OUTPUT_EXT = "webm"; |
|
19 | 26 | private static final String VIDEO_CODEC = "libvpx"; |
|
20 | 27 | private static final String VIDEO_QUALITY = "3"; |
|
21 | 28 | private static final String AUDIO_CODEC = "libvorbis"; |
|
22 | 29 | private static final String AUDIO_QUALITY = "3"; |
|
23 | 30 | ||
24 | 31 | public FfmpegVideoEncoder(ITempFileProvider tempFileProvider) { |
|
25 | - | super(tempFileProvider); |
|
32 | + | this(LOG, tempFileProvider); |
|
33 | + | } |
|
34 | + | ||
35 | + | @VisibleForTesting |
|
36 | + | FfmpegVideoEncoder(Logger logger, ITempFileProvider tempFileProvider) { |
|
37 | + | super(logger, tempFileProvider); |
|
26 | 38 | } |
|
27 | 39 | ||
28 | 40 | @Override |
4 | 4 | import java.util.Arrays; |
|
5 | 5 | import java.util.List; |
|
6 | 6 | ||
7 | + | import org.slf4j.Logger; |
|
8 | + | import org.slf4j.LoggerFactory; |
|
9 | + | ||
10 | + | import com.google.common.annotations.VisibleForTesting; |
|
11 | + | ||
7 | 12 | import nl.weeaboo.io.Filenames; |
|
8 | 13 | import nl.weeaboo.vn.buildtools.file.IEncodedResource; |
|
9 | 14 | import nl.weeaboo.vn.buildtools.file.ITempFileProvider; |
17 | 22 | */ |
|
18 | 23 | public final class FfmpegSoundEncoder extends FfmpegEncoder implements ISoundEncoder { |
|
19 | 24 | ||
25 | + | private static final Logger LOG = LoggerFactory.getLogger(FfmpegSoundEncoder.class); |
|
26 | + | ||
20 | 27 | private static final String OUTPUT_EXT = "ogg"; |
|
21 | 28 | private static final String AUDIO_CODEC = "libvorbis"; |
|
22 | 29 | private static final String AUDIO_QUALITY = "3"; |
|
23 | 30 | ||
24 | 31 | public FfmpegSoundEncoder(ITempFileProvider tempFileProvider) { |
|
25 | - | super(tempFileProvider); |
|
32 | + | this(LOG, tempFileProvider); |
|
33 | + | } |
|
34 | + | ||
35 | + | @VisibleForTesting |
|
36 | + | FfmpegSoundEncoder(Logger logger, ITempFileProvider tempFileProvider) { |
|
37 | + | super(logger, tempFileProvider); |
|
26 | 38 | } |
|
27 | 39 | ||
28 | 40 | @Override |
19 | 19 | import nl.weeaboo.vn.buildtools.optimizer.IOptimizerFileSet; |
|
20 | 20 | import nl.weeaboo.vn.buildtools.optimizer.IParallelExecutor; |
|
21 | 21 | import nl.weeaboo.vn.buildtools.optimizer.MainOptimizerConfig; |
|
22 | - | import nl.weeaboo.vn.buildtools.optimizer.sound.encoder.FfmpegSoundEncoder; |
|
23 | 22 | import nl.weeaboo.vn.buildtools.optimizer.video.encoder.FfmpegVideoEncoder; |
|
24 | 23 | import nl.weeaboo.vn.buildtools.optimizer.video.encoder.IVideoEncoder; |
|
25 | 24 | import nl.weeaboo.vn.buildtools.optimizer.video.encoder.NoOpVideoEncoder; |
41 | 40 | private final IFileSystem resFileSystem; |
|
42 | 41 | ||
43 | 42 | // --- State during optimization --- |
|
44 | - | private boolean ffmpegAvailable; |
|
45 | - | ||
43 | + | private EAvailable ffmpegAvailable; |
|
46 | 44 | ||
47 | 45 | public VideoOptimizer(IOptimizerContext context) { |
|
48 | 46 | executor = context.getExecutor(); |
52 | 50 | ||
53 | 51 | NvlistProjectConnection project = context.getProject(); |
|
54 | 52 | resFileSystem = project.getResFileSystem(); |
|
53 | + | ||
54 | + | resetState(); |
|
55 | 55 | } |
|
56 | 56 | ||
57 | 57 | private void resetState() { |
|
58 | - | ffmpegAvailable = FfmpegSoundEncoder.isAvailable(); |
|
58 | + | ffmpegAvailable = EAvailable.UNKNOWN; |
|
59 | 59 | } |
|
60 | 60 | ||
61 | 61 | /** |
118 | 118 | } |
|
119 | 119 | ||
120 | 120 | private IVideoEncoder createEncoder() { |
|
121 | - | if (ffmpegAvailable) { |
|
122 | - | return new FfmpegVideoEncoder(tempFileProvider); |
|
123 | - | } else { |
|
124 | - | return new NoOpVideoEncoder(); |
|
121 | + | if (ffmpegAvailable != EAvailable.NO) { |
|
122 | + | FfmpegVideoEncoder encoder = new FfmpegVideoEncoder(tempFileProvider); |
|
123 | + | if (ffmpegAvailable == EAvailable.YES || encoder.isAvailable()) { |
|
124 | + | ffmpegAvailable = EAvailable.YES; |
|
125 | + | return encoder; |
|
126 | + | } |
|
125 | 127 | } |
|
128 | + | ffmpegAvailable = EAvailable.NO; |
|
129 | + | return new NoOpVideoEncoder(); |
|
126 | 130 | } |
|
127 | 131 | ||
128 | 132 | private FilePath getOutputPath(FilePath inputPath, String outputFilename) { |
|
129 | 133 | FilePath folder = inputPath.getParent(); |
|
130 | 134 | return folder.resolve(outputFilename); |
|
131 | 135 | } |
|
132 | 136 | ||
137 | + | private enum EAvailable { |
|
138 | + | YES, NO, UNKNOWN |
|
139 | + | } |
|
133 | 140 | } |
Learn more Showing 7 files with coverage changes found.
core/src/main/java/nl/weeaboo/vn/gdx/res/NativeMemoryTracker.java
core/src/main/java/nl/weeaboo/vn/impl/image/GdxTextureStore.java
core/src/main/java/nl/weeaboo/vn/impl/debug/PerformanceMetrics.java
buildtools/src/main/java/nl/weeaboo/vn/buildtools/optimizer/FfmpegEncoder.java
buildtools/src/main/java/nl/weeaboo/vn/buildtools/file/EncodedResource.java
buildtools/src/main/java/nl/weeaboo/vn/buildtools/optimizer/video/encoder/FfmpegVideoEncoder.java
buildtools/src/main/java/nl/weeaboo/vn/buildtools/optimizer/sound/encoder/FfmpegSoundEncoder.java
Files | Complexity | Coverage |
---|---|---|
api/src/main/java/nl/weeaboo/vn | 91.53% | 96.76% |
buildtools/src/main/java/nl/weeaboo/vn/buildtools | +8.00% 66.34% | +4.37% 74.43% |
core/src/main/java/nl/weeaboo/vn | 81.94% | -0.16% 86.14% |
Project Totals (369 files) | 81.78% | 86.16% |
6f7a235
5b9d826
2a923f6
b9e203b