diff --git a/server/src/main/java/com/genymobile/scrcpy/Options.java b/server/src/main/java/com/genymobile/scrcpy/Options.java index 2a4bba33..9736880c 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Options.java +++ b/server/src/main/java/com/genymobile/scrcpy/Options.java @@ -12,6 +12,7 @@ public class Options { private boolean sendFrameMeta; // send PTS so that the client may record properly private boolean control; private int displayId; + private String codecOptions; public int getMaxSize() { return maxSize; @@ -84,4 +85,12 @@ public class Options { public void setDisplayId(int displayId) { this.displayId = displayId; } + + public String getCodecOptions() { + return codecOptions; + } + + public void setCodecOptions(String codecOptions) { + this.codecOptions = codecOptions; + } } diff --git a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java index fc1a25b1..a994cda0 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java @@ -25,15 +25,17 @@ public class ScreenEncoder implements Device.RotationListener { private final AtomicBoolean rotationChanged = new AtomicBoolean(); private final ByteBuffer headerBuffer = ByteBuffer.allocate(12); + private String codecOptions; private int bitRate; private int maxFps; private boolean sendFrameMeta; private long ptsOrigin; - public ScreenEncoder(boolean sendFrameMeta, int bitRate, int maxFps) { + public ScreenEncoder(boolean sendFrameMeta, int bitRate, int maxFps, String codecOptions) { this.sendFrameMeta = sendFrameMeta; this.bitRate = bitRate; this.maxFps = maxFps; + this.codecOptions = codecOptions; } @Override @@ -49,7 +51,7 @@ public class ScreenEncoder implements Device.RotationListener { Workarounds.prepareMainLooper(); Workarounds.fillAppInfo(); - MediaFormat format = createFormat(bitRate, maxFps, DEFAULT_I_FRAME_INTERVAL); + MediaFormat format = createFormat(bitRate, maxFps, DEFAULT_I_FRAME_INTERVAL, codecOptions); device.setRotationListener(this); boolean alive; try { @@ -139,7 +141,7 @@ public class ScreenEncoder implements Device.RotationListener { return MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC); } - private static MediaFormat createFormat(int bitRate, int maxFps, int iFrameInterval) { + private static MediaFormat createFormat(int bitRate, int maxFps, int iFrameInterval, String codecOptions) { MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); @@ -155,6 +157,33 @@ public class ScreenEncoder implements Device.RotationListener { // format.setFloat(KEY_MAX_FPS_TO_ENCODER, maxFps); } + // Adding additional options specified by the user + if(!"-".equals(codecOptions)) { + for (String pair : codecOptions.split(",")) { + String[] option = pair.split("="); + String key = option[0]; + if(format.containsKey(key)) { + if (option.length < 2) { + Ln.w("No value specified for codec option - " + key); + continue; + } + String[] valueAndType = option[1].split(":"); + String value = valueAndType[0]; + String type = valueAndType.length < 2 ? "" : valueAndType[1].toLowerCase(); + if (type.contains("str")) { + format.setString(key, value); + } else if (type.contains("long")) { + format.setLong(key, Long.parseLong(value)); + } else if (type.contains("float")) { + format.setFloat(key, Float.parseFloat(value)); + } else { + format.setInteger(key, Integer.parseInt(value)); + } + } else { + Ln.w("Codec format doesn't contain the requested codec option - " + key); + } + } + } return format; } diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index a6f7a78c..3a2f718f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -20,7 +20,7 @@ public final class Server { final Device device = new Device(options); boolean tunnelForward = options.isTunnelForward(); try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) { - ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps()); + ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), options.getCodecOptions()); if (options.getControl()) { Controller controller = new Controller(device, connection); @@ -79,8 +79,8 @@ public final class Server { "The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")"); } - if (args.length != 10) { - throw new IllegalArgumentException("Expecting 10 parameters"); + if (args.length != 11) { + throw new IllegalArgumentException("Expecting 11 parameters"); } Options options = new Options(); @@ -113,6 +113,9 @@ public final class Server { int displayId = Integer.parseInt(args[9]); options.setDisplayId(displayId); + String codecOptions = args[10]; + options.setCodecOptions(codecOptions); + return options; }