Adding new option --encoder

Some devices have more than one encoder, and some encoders may cause
issues or crash. With this option we can specify which encoder we want
the device to use.

PR #1827 <https://github.com/Genymobile/scrcpy/pull/1827>
Fixes #1810 <https://github.com/Genymobile/scrcpy/issues/1810>

Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
Tzah Mazuz 2020-10-12 12:23:06 +03:00 committed by Romain Vimont
parent d5f059c7cb
commit 76c2c6e69d
8 changed files with 37 additions and 5 deletions

View file

@ -53,6 +53,9 @@ scrcpy_print_usage(const char *arg0) {
"\n"
" Default is 0.\n"
"\n"
" --encoder name\n"
" Use a specific MediaCodec encoder (must be a H.264 encoder).\n"
"\n"
" --force-adb-forward\n"
" Do not attempt to use \"adb reverse\" to connect to the\n"
" the device.\n"
@ -664,6 +667,7 @@ guess_record_format(const char *filename) {
#define OPT_NO_KEY_REPEAT 1022
#define OPT_FORWARD_ALL_CLICKS 1023
#define OPT_LEGACY_PASTE 1024
#define OPT_ENCODER_NAME 1025
bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
@ -675,6 +679,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
{"disable-screensaver", no_argument, NULL,
OPT_DISABLE_SCREENSAVER},
{"display", required_argument, NULL, OPT_DISPLAY_ID},
{"encoder", required_argument, NULL, OPT_ENCODER_NAME},
{"force-adb-forward", no_argument, NULL,
OPT_FORCE_ADB_FORWARD},
{"forward-all-clicks", no_argument, NULL,
@ -861,6 +866,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
case OPT_CODEC_OPTIONS:
opts->codec_options = optarg;
break;
case OPT_ENCODER_NAME:
opts->encoder_name = optarg;
break;
case OPT_FORCE_ADB_FORWARD:
opts->force_adb_forward = true;
break;

View file

@ -318,6 +318,7 @@ scrcpy(const struct scrcpy_options *options) {
.show_touches = options->show_touches,
.stay_awake = options->stay_awake,
.codec_options = options->codec_options,
.encoder_name = options->encoder_name,
.force_adb_forward = options->force_adb_forward,
};
if (!server_start(&server, options->serial, &params)) {

View file

@ -51,6 +51,7 @@ struct scrcpy_options {
const char *push_target;
const char *render_driver;
const char *codec_options;
const char *encoder_name;
enum sc_log_level log_level;
enum sc_record_format record_format;
struct sc_port_range port_range;
@ -91,6 +92,7 @@ struct scrcpy_options {
.push_target = NULL, \
.render_driver = NULL, \
.codec_options = NULL, \
.encoder_name = NULL, \
.log_level = SC_LOG_LEVEL_INFO, \
.record_format = SC_RECORD_FORMAT_AUTO, \
.port_range = { \

View file

@ -294,6 +294,7 @@ execute_server(struct server *server, const struct server_params *params) {
params->show_touches ? "true" : "false",
params->stay_awake ? "true" : "false",
params->codec_options ? params->codec_options : "-",
params->encoder_name ? params->encoder_name : "-",
};
#ifdef SERVER_DEBUGGER
LOGI("Server debugger waiting for a client on device port "

View file

@ -48,6 +48,7 @@ struct server_params {
enum sc_log_level log_level;
const char *crop;
const char *codec_options;
const char *encoder_name;
struct sc_port_range port_range;
uint16_t max_size;
uint32_t bit_rate;

View file

@ -16,6 +16,7 @@ public class Options {
private boolean showTouches;
private boolean stayAwake;
private String codecOptions;
private String encoderName;
public Ln.Level getLogLevel() {
return logLevel;
@ -120,4 +121,12 @@ public class Options {
public void setCodecOptions(String codecOptions) {
this.codecOptions = codecOptions;
}
public String getEncoderName() {
return encoderName;
}
public void setEncoderName(String encoderName) {
this.encoderName = encoderName;
}
}

View file

@ -26,17 +26,19 @@ public class ScreenEncoder implements Device.RotationListener {
private final AtomicBoolean rotationChanged = new AtomicBoolean();
private final ByteBuffer headerBuffer = ByteBuffer.allocate(12);
private String encoderName;
private List<CodecOption> codecOptions;
private int bitRate;
private int maxFps;
private boolean sendFrameMeta;
private long ptsOrigin;
public ScreenEncoder(boolean sendFrameMeta, int bitRate, int maxFps, List<CodecOption> codecOptions) {
public ScreenEncoder(boolean sendFrameMeta, int bitRate, int maxFps, List<CodecOption> codecOptions, String encoderName) {
this.sendFrameMeta = sendFrameMeta;
this.bitRate = bitRate;
this.maxFps = maxFps;
this.codecOptions = codecOptions;
this.encoderName = encoderName;
}
@Override
@ -69,7 +71,7 @@ public class ScreenEncoder implements Device.RotationListener {
boolean alive;
try {
do {
MediaCodec codec = createCodec();
MediaCodec codec = createCodec(encoderName);
IBinder display = createDisplay();
ScreenInfo screenInfo = device.getScreenInfo();
Rect contentRect = screenInfo.getContentRect();
@ -150,7 +152,11 @@ public class ScreenEncoder implements Device.RotationListener {
IO.writeFully(fd, headerBuffer);
}
private static MediaCodec createCodec() throws IOException {
private static MediaCodec createCodec(String encoderName) throws IOException {
if (encoderName != null) {
Ln.d("Creating encoder by name: '" + encoderName + "'");
return MediaCodec.createByCodecName(encoderName);
}
return MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
}

View file

@ -54,7 +54,8 @@ public final class Server {
boolean tunnelForward = options.isTunnelForward();
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions);
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions,
options.getEncoderName());
if (options.getControl()) {
final Controller controller = new Controller(device, connection);
@ -120,7 +121,7 @@ public final class Server {
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
}
final int expectedParameters = 14;
final int expectedParameters = 15;
if (args.length != expectedParameters) {
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
}
@ -167,6 +168,9 @@ public final class Server {
String codecOptions = args[13];
options.setCodecOptions(codecOptions);
String encoderName = "-".equals(args[14]) ? null : args[14];
options.setEncoderName(encoderName);
return options;
}