Skip to content

Commit

Permalink
Encoding with repeated GOPs
Browse files Browse the repository at this point in the history
  • Loading branch information
igorzep committed Apr 8, 2018
1 parent 911ba73 commit da13041
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 176 deletions.
4 changes: 4 additions & 0 deletions src/main/java/band/full/video/encoder/MuxerMP4.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,8 @@ public String mux() throws IOException, InterruptedException {

return name + MP4_SUFFIX;
}

public void deleteInputs() {
inputs.forEach(in -> new File(dir, in).delete());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@

import band.full.test.video.executor.GenerateVideo;
import band.full.test.video.generator.CalibrationBase;
import band.full.test.video.generator.PatchesGenerator;

import org.junit.jupiter.api.Test;

/**
* Calibration box fills.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.util.Random;

/**
Expand All @@ -24,16 +26,17 @@
@Disabled("Requires lossless encode and reducing bitrate to at least 100Mb/s")
public class Gradients1080pHEVC {
@Test
public void gradients() {
public void gradients() throws IOException, InterruptedException {
gradients("Gradients1080p06"); // 6 bit demo
}

public void gradients(String name) {
HEVC.generate("Gradients", name, FULLHD_MAIN8,
e -> {
FrameBuffer fb = e.newFrameBuffer();
e.render(ofSeconds(30), () -> gradients(fb));
}, d -> {});
public void gradients(String name)
throws IOException, InterruptedException {
File dir = HEVC.greet("Gradients", name);
HEVC.encode(dir, name, FULLHD_MAIN8, e -> {
FrameBuffer fb = e.newFrameBuffer();
e.render(ofSeconds(30), () -> gradients(fb));
});
}

/** Render with new dither per frame */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.util.Random;

/**
Expand All @@ -24,16 +26,17 @@
@Disabled("Requires lossless encode and reducing bitrate to at least 100Mb/s")
public class Gradients2160pBT709 {
@Test
public void gradients() {
public void gradients() throws IOException, InterruptedException {
gradients("Gradients-06"); // 6 bit demo
}

public void gradients(String name) {
HEVC.generate("Gradients", name, UHD4K_MAIN8,
e -> {
FrameBuffer fb = e.newFrameBuffer();
e.render(ofSeconds(30), () -> gradients(fb));
}, d -> {});
public void gradients(String name)
throws IOException, InterruptedException {
File dir = HEVC.greet("Gradients", name);
HEVC.encode(dir, name, UHD4K_MAIN8, e -> {
FrameBuffer fb = e.newFrameBuffer();
e.render(ofSeconds(30), () -> gradients(fb));
});
}

/** Render with new dither per frame */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* @author Igor Malinin
*/
// TODO output file type and test.full.band branding
public class BT2111Generator extends GeneratorBase {
public class BT2111Generator extends GeneratorBase<Void> {
private final double alpha;
private final Matrix3x3 bt709conv;

Expand All @@ -37,8 +37,7 @@ public class BT2111Generator extends GeneratorBase {

public BT2111Generator(GeneratorFactory factory,
EncoderParameters params, String folder, String suffix) {
super(factory, params.withEncoderOptions("--qpmax", "6"),
folder, "BT2111" + suffix);
super(factory, params, folder, "BT2111" + suffix);

if (width % STD_1080p.width != 0)
throw new IllegalArgumentException(
Expand Down Expand Up @@ -75,13 +74,13 @@ public BT2111Generator(GeneratorFactory factory,
}

@Override
protected void encode(EncoderY4M e) {
protected void encode(EncoderY4M e, Void args, String phase) {
var fb = draw(e.newFrameBuffer());
e.render(DURATION_STATIC, () -> fb);
e.render(gop, () -> fb);
}

@Override
protected void verify(DecoderY4M d) {
protected void verify(DecoderY4M d, Void args) {
var expected = draw(d.newFrameBuffer());
d.read(fb -> FrameVerifier.verify(expected, fb, 4, 0.001));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ protected BasicSetupBase(GeneratorFactory factory,
@Test
@Disabled("TODO")
public void blackLevel() {
new BlackLevelGenerator(factory, params, folder, pattern).generate();
new BlackLevelGenerator(factory, params, folder, pattern)
.generate(null);
}

@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ protected BasicSetupHDRBase(GeneratorFactory factory,

@Test
public void bt2111() {
new BT2111Generator(factory, params, folder, pattern).generate();
new BT2111Generator(factory, params, folder, pattern).generate(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
*
* @author Igor Malinin
*/
public class BlackLevelGenerator extends GeneratorBase {
public class BlackLevelGenerator extends GeneratorBase<Void> {
protected static final int COLS = 16;

public BlackLevelGenerator(GeneratorFactory factory,
Expand All @@ -37,13 +37,13 @@ public BlackLevelGenerator(GeneratorFactory factory,
}

@Override
protected void encode(EncoderY4M e) {
protected void encode(EncoderY4M e, Void args, String phase) {
var fb = e.newFrameBuffer();

patches(fb);
marks(fb);

e.render(DURATION_STATIC, () -> fb);
e.render(gop, () -> fb);
}

/**
Expand All @@ -63,7 +63,7 @@ private void patches(FrameBuffer fb) {
}

@Override
protected void verify(DecoderY4M d) {
protected void verify(DecoderY4M d, Void args) {
d.read(fb -> verify(fb));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static java.lang.String.format;
import static java.util.stream.Stream.concat;

import band.full.test.video.generator.CheckerboardGenerator.Args;
import band.full.video.encoder.DecoderY4M;
import band.full.video.encoder.EncoderParameters;
import band.full.video.encoder.EncoderY4M;
Expand All @@ -16,8 +17,7 @@
*
* @author Igor Malinin
*/
public class CheckerboardGenerator
extends ParameterizedGeneratorBase<CheckerboardGenerator.Args> {
public class CheckerboardGenerator extends GeneratorBase<Args> {
public static class Args {
public final String suffix;
public final int yMin, yMax;
Expand Down Expand Up @@ -68,13 +68,13 @@ protected String getPattern(Args args) {
}

@Override
protected void encode(EncoderY4M e, Args args) {
protected void encode(EncoderY4M e, Args args, String phase) {
var fb = e.newFrameBuffer();

fb.Y.calculate(
(x, y) -> (x + y) % 2 == 0 ? args.yMin : args.yMax);

e.render(DURATION_STATIC, () -> fb);
e.render(gop, () -> fb);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import static java.util.Arrays.fill;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;

import band.full.test.video.generator.ChromaSubsamplingBase.Args;
import band.full.video.encoder.DecoderY4M;
import band.full.video.encoder.EncoderParameters;
import band.full.video.encoder.EncoderY4M;
Expand All @@ -29,8 +30,7 @@
* @author Igor Malinin
*/
@TestInstance(PER_CLASS)
public class ChromaSubsamplingBase
extends ParameterizedGeneratorBase<ChromaSubsamplingBase.Args> {
public class ChromaSubsamplingBase extends GeneratorBase<Args> {
private static final int CENTER_X = STD_2160p.width / 2;
private static final int CENTER_Y = STD_2160p.height / 2;
private static final double MAX_DISTANCE = CENTER_Y;
Expand Down Expand Up @@ -74,7 +74,7 @@ public Stream<Args> args() {
}

@Override
protected void encode(EncoderY4M e, Args args) {
protected void encode(EncoderY4M e, Args args, String phase) {
args.generator.accept(e);
}

Expand Down Expand Up @@ -108,7 +108,7 @@ public void concentricBlackWhiteSineE(EncoderY4M e) {
fill(fb.U.pixels, c0);
fill(fb.V.pixels, c0);

e.render(DURATION_STATIC, () -> fb);
e.render(gop, () -> fb);
}

public void concentricBlackWhiteSineO(EncoderY4M e) {
Expand All @@ -130,7 +130,7 @@ public void concentricBlackWhiteSineO(EncoderY4M e) {
fill(fb.U.pixels, c0);
fill(fb.V.pixels, c0);

e.render(DURATION_STATIC, () -> fb);
e.render(gop, () -> fb);
}

/**
Expand Down Expand Up @@ -185,7 +185,7 @@ public void concentricRedBlueSineE(EncoderY4M e) {
}
}

e.render(DURATION_STATIC, () -> fb);
e.render(gop, () -> fb);
}

/** luma log sine sweep */
Expand Down
62 changes: 51 additions & 11 deletions src/test/java/band/full/test/video/generator/GeneratorBase.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
package band.full.test.video.generator;

import static java.time.Duration.ofSeconds;
import static java.lang.Math.round;
import static java.util.Collections.emptyList;
import static java.util.stream.IntStream.range;

import band.full.core.Resolution;
import band.full.video.buffer.Framerate;
import band.full.video.encoder.DecoderY4M;
import band.full.video.encoder.EncoderParameters;
import band.full.video.encoder.EncoderY4M;
import band.full.video.encoder.MuxerMP4;
import band.full.video.itu.ColorMatrix;
import band.full.video.itu.TransferCharacteristics;

import java.time.Duration;
import java.io.File;
import java.io.IOException;

/**
* @author Igor Malinin
*/
public abstract class GeneratorBase {
protected static final Duration DURATION_STATIC = ofSeconds(30);
public abstract class GeneratorBase<A> {
protected static final int PATTERN_SECONDS = 30;
protected static final int INTRO_SECONDS = 5;
protected static final int BODY_SECONDS = PATTERN_SECONDS - INTRO_SECONDS;

public final GeneratorFactory factory;
public final EncoderParameters params;
Expand All @@ -27,7 +33,7 @@ public abstract class GeneratorBase {
public final ColorMatrix matrix;
public final Framerate framerate;
public final TransferCharacteristics transfer;
public final int width, height;
public final int width, height, gop;

public GeneratorBase(GeneratorFactory factory,
EncoderParameters params, String folder, String pattern) {
Expand All @@ -44,18 +50,52 @@ public GeneratorBase(GeneratorFactory factory,

width = resolution.width;
height = resolution.height;

gop = round(framerate.rate);
}

public void generate(A args) {
String pattern = getPattern(args);
File dir = factory.greet(getFolder(args), pattern);
try {
MuxerMP4 muxer = new MuxerMP4(dir,
pattern, factory.brand, emptyList());

generate(muxer, dir, args);
String mp4 = muxer.mux();
muxer.deleteInputs();
DecoderY4M.decode(dir, mp4, params, d -> verify(d, args));
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}

public void generate(MuxerMP4 muxer, File dir, A args)
throws IOException, InterruptedException {
encode(muxer, dir, args, null, PATTERN_SECONDS);
}

public void generate() {
factory.generate(getFolder(), pattern,
params, this::encode, this::verify);
public void encode(MuxerMP4 muxer, File dir,
A args, String phase, int repeat)
throws IOException, InterruptedException {
String pattern = getPattern(args);
String name = phase == null ? pattern : pattern + "-" + phase;

String out = factory.encode(dir, name, params,
e -> encode(e, args, phase));

range(0, repeat).forEach(i -> muxer.addInput(out));
}

protected String getFolder() {
protected String getFolder(A args) {
return factory.folder + '/' + folder;
}

protected abstract void encode(EncoderY4M e);
protected String getPattern(A args) {
return pattern;
}

protected abstract void encode(EncoderY4M e, A args, String phase);

protected abstract void verify(DecoderY4M d);
protected abstract void verify(DecoderY4M d, A args);
}
Loading

0 comments on commit da13041

Please sign in to comment.