Add --list-encoders
Add an option to list the device encoders properly. PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
This commit is contained in:
parent
b7e5284adf
commit
9196dc1563
16 changed files with 157 additions and 29 deletions
|
@ -273,12 +273,10 @@ may cause issues or crash. It is possible to select a different encoder:
|
||||||
scrcpy --video-encoder=OMX.qcom.video.encoder.avc
|
scrcpy --video-encoder=OMX.qcom.video.encoder.avc
|
||||||
```
|
```
|
||||||
|
|
||||||
To list the available encoders, you can pass an invalid encoder name; the
|
To list the available encoders:
|
||||||
error will give the available encoders:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
scrcpy --video-encoder=_ # for the default codec
|
scrcpy --list-encoders
|
||||||
scrcpy --video-codec=h265 --video-encoder=_ # for a specific codec
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Capture
|
### Capture
|
||||||
|
|
|
@ -19,6 +19,7 @@ _scrcpy() {
|
||||||
-K --hid-keyboard
|
-K --hid-keyboard
|
||||||
-h --help
|
-h --help
|
||||||
--legacy-paste
|
--legacy-paste
|
||||||
|
--list-encoders
|
||||||
--lock-video-orientation
|
--lock-video-orientation
|
||||||
--lock-video-orientation=
|
--lock-video-orientation=
|
||||||
--max-fps=
|
--max-fps=
|
||||||
|
|
|
@ -26,6 +26,7 @@ arguments=(
|
||||||
{-K,--hid-keyboard}'[Simulate a physical keyboard by using HID over AOAv2]'
|
{-K,--hid-keyboard}'[Simulate a physical keyboard by using HID over AOAv2]'
|
||||||
{-h,--help}'[Print the help]'
|
{-h,--help}'[Print the help]'
|
||||||
'--legacy-paste[Inject computer clipboard text as a sequence of key events on Ctrl+v]'
|
'--legacy-paste[Inject computer clipboard text as a sequence of key events on Ctrl+v]'
|
||||||
|
'--list-encoders[List video and audio encoders available on the device]'
|
||||||
'--lock-video-orientation=[Lock video orientation]:orientation:(unlocked initial 0 1 2 3)'
|
'--lock-video-orientation=[Lock video orientation]:orientation:(unlocked initial 0 1 2 3)'
|
||||||
'--max-fps=[Limit the frame rate of screen capture]'
|
'--max-fps=[Limit the frame rate of screen capture]'
|
||||||
{-M,--hid-mouse}'[Simulate a physical mouse by using HID over AOAv2]'
|
{-M,--hid-mouse}'[Simulate a physical mouse by using HID over AOAv2]'
|
||||||
|
|
|
@ -45,6 +45,8 @@ The list of possible codec options is available in the Android documentation
|
||||||
.BI "\-\-audio\-encoder " name
|
.BI "\-\-audio\-encoder " name
|
||||||
Use a specific MediaCodec audio encoder (depending on the codec provided by \fB\-\-audio\-codec\fR).
|
Use a specific MediaCodec audio encoder (depending on the codec provided by \fB\-\-audio\-codec\fR).
|
||||||
|
|
||||||
|
The available encoders can be listed by \-\-list\-encoders.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-b, \-\-video\-bit\-rate " value
|
.BI "\-b, \-\-video\-bit\-rate " value
|
||||||
Encode the video at the given bit\-rate, expressed in bits/s. Unit suffixes are supported: '\fBK\fR' (x1000) and '\fBM\fR' (x1000000).
|
Encode the video at the given bit\-rate, expressed in bits/s. Unit suffixes are supported: '\fBK\fR' (x1000) and '\fBM\fR' (x1000000).
|
||||||
|
@ -128,6 +130,10 @@ Inject computer clipboard text as a sequence of key events on Ctrl+v (like MOD+S
|
||||||
|
|
||||||
This is a workaround for some devices not behaving as expected when setting the device clipboard programmatically.
|
This is a workaround for some devices not behaving as expected when setting the device clipboard programmatically.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-list\-encoders
|
||||||
|
List video and audio encoders available on the device.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-lock\-video\-orientation\fR[=\fIvalue\fR]
|
\fB\-\-lock\-video\-orientation\fR[=\fIvalue\fR]
|
||||||
Lock video orientation to \fIvalue\fR. Possible values are "unlocked", "initial" (locked to the initial orientation), 0, 1, 2 and 3. Natural device orientation is 0, and each increment adds a 90 degrees rotation counterclockwise.
|
Lock video orientation to \fIvalue\fR. Possible values are "unlocked", "initial" (locked to the initial orientation), 0, 1, 2 and 3. Natural device orientation is 0, and each increment adds a 90 degrees rotation counterclockwise.
|
||||||
|
@ -355,6 +361,8 @@ The list of possible codec options is available in the Android documentation
|
||||||
.BI "\-\-video\-encoder " name
|
.BI "\-\-video\-encoder " name
|
||||||
Use a specific MediaCodec video encoder (depending on the codec provided by \fB\-\-video\-codec\fR).
|
Use a specific MediaCodec video encoder (depending on the codec provided by \fB\-\-video\-codec\fR).
|
||||||
|
|
||||||
|
The available encoders can be listed by \-\-list\-encoders.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-w, \-\-stay-awake
|
.B \-w, \-\-stay-awake
|
||||||
Keep the device on while scrcpy is running, when the device is plugged in.
|
Keep the device on while scrcpy is running, when the device is plugged in.
|
||||||
|
|
|
@ -68,6 +68,7 @@ enum {
|
||||||
OPT_AUDIO_CODEC,
|
OPT_AUDIO_CODEC,
|
||||||
OPT_AUDIO_CODEC_OPTIONS,
|
OPT_AUDIO_CODEC_OPTIONS,
|
||||||
OPT_AUDIO_ENCODER,
|
OPT_AUDIO_ENCODER,
|
||||||
|
OPT_LIST_ENCODERS,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_option {
|
struct sc_option {
|
||||||
|
@ -141,7 +142,8 @@ static const struct sc_option options[] = {
|
||||||
.longopt = "audio-encoder",
|
.longopt = "audio-encoder",
|
||||||
.argdesc = "name",
|
.argdesc = "name",
|
||||||
.text = "Use a specific MediaCodec audio encoder (depending on the "
|
.text = "Use a specific MediaCodec audio encoder (depending on the "
|
||||||
"codec provided by --audio-codec).",
|
"codec provided by --audio-codec).\n"
|
||||||
|
"The available encoders can be listed by --list-encoders.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'b',
|
.shortopt = 'b',
|
||||||
|
@ -270,6 +272,11 @@ static const struct sc_option options[] = {
|
||||||
"This is a workaround for some devices not behaving as "
|
"This is a workaround for some devices not behaving as "
|
||||||
"expected when setting the device clipboard programmatically.",
|
"expected when setting the device clipboard programmatically.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.longopt_id = OPT_LIST_ENCODERS,
|
||||||
|
.longopt = "list-encoders",
|
||||||
|
.text = "List video and audio encoders available on the device.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_LOCK_VIDEO_ORIENTATION,
|
.longopt_id = OPT_LOCK_VIDEO_ORIENTATION,
|
||||||
.longopt = "lock-video-orientation",
|
.longopt = "lock-video-orientation",
|
||||||
|
@ -586,7 +593,8 @@ static const struct sc_option options[] = {
|
||||||
.longopt = "video-encoder",
|
.longopt = "video-encoder",
|
||||||
.argdesc = "name",
|
.argdesc = "name",
|
||||||
.text = "Use a specific MediaCodec video encoder (depending on the "
|
.text = "Use a specific MediaCodec video encoder (depending on the "
|
||||||
"codec provided by --video-codec).",
|
"codec provided by --video-codec).\n"
|
||||||
|
"The available encoders can be listed by --list-encoders.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'w',
|
.shortopt = 'w',
|
||||||
|
@ -1792,6 +1800,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
LOGE("V4L2 (--v4l2-buffer) is only available on Linux.");
|
LOGE("V4L2 (--v4l2-buffer) is only available on Linux.");
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
case OPT_LIST_ENCODERS:
|
||||||
|
opts->list_encoders = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// getopt prints the error message on stderr
|
// getopt prints the error message on stderr
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -72,4 +72,5 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||||
.start_fps_counter = false,
|
.start_fps_counter = false,
|
||||||
.power_on = true,
|
.power_on = true,
|
||||||
.audio = true,
|
.audio = true,
|
||||||
|
.list_encoders = false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -154,6 +154,7 @@ struct scrcpy_options {
|
||||||
bool start_fps_counter;
|
bool start_fps_counter;
|
||||||
bool power_on;
|
bool power_on;
|
||||||
bool audio;
|
bool audio;
|
||||||
|
bool list_encoders;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct scrcpy_options scrcpy_options_default;
|
extern const struct scrcpy_options scrcpy_options_default;
|
||||||
|
|
|
@ -183,12 +183,16 @@ await_for_server(bool *connected) {
|
||||||
while (SDL_WaitEvent(&event)) {
|
while (SDL_WaitEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
|
if (connected) {
|
||||||
*connected = false;
|
*connected = false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
case SC_EVENT_SERVER_CONNECTION_FAILED:
|
case SC_EVENT_SERVER_CONNECTION_FAILED:
|
||||||
return false;
|
return false;
|
||||||
case SC_EVENT_SERVER_CONNECTED:
|
case SC_EVENT_SERVER_CONNECTED:
|
||||||
|
if (connected) {
|
||||||
*connected = true;
|
*connected = true;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -339,6 +343,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
.tcpip_dst = options->tcpip_dst,
|
.tcpip_dst = options->tcpip_dst,
|
||||||
.cleanup = options->cleanup,
|
.cleanup = options->cleanup,
|
||||||
.power_on = options->power_on,
|
.power_on = options->power_on,
|
||||||
|
.list_encoders = options->list_encoders,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct sc_server_callbacks cbs = {
|
static const struct sc_server_callbacks cbs = {
|
||||||
|
@ -356,6 +361,12 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
|
|
||||||
server_started = true;
|
server_started = true;
|
||||||
|
|
||||||
|
if (options->list_encoders) {
|
||||||
|
bool ok = await_for_server(NULL);
|
||||||
|
ret = ok ? SCRCPY_EXIT_SUCCESS : SCRCPY_EXIT_FAILURE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
if (options->display) {
|
if (options->display) {
|
||||||
sdl_set_hints(options->render_driver);
|
sdl_set_hints(options->render_driver);
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,9 @@ execute_server(struct sc_server *server,
|
||||||
// By default, power_on is true
|
// By default, power_on is true
|
||||||
ADD_PARAM("power_on=false");
|
ADD_PARAM("power_on=false");
|
||||||
}
|
}
|
||||||
|
if (params->list_encoders) {
|
||||||
|
ADD_PARAM("list_encoders=true");
|
||||||
|
}
|
||||||
|
|
||||||
#undef ADD_PARAM
|
#undef ADD_PARAM
|
||||||
|
|
||||||
|
@ -848,6 +851,25 @@ run_server(void *data) {
|
||||||
assert(serial);
|
assert(serial);
|
||||||
LOGD("Device serial: %s", serial);
|
LOGD("Device serial: %s", serial);
|
||||||
|
|
||||||
|
ok = push_server(&server->intr, serial);
|
||||||
|
if (!ok) {
|
||||||
|
goto error_connection_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If --list-encoders is passed, then the server just prints the encoders
|
||||||
|
// then exits.
|
||||||
|
if (params->list_encoders) {
|
||||||
|
sc_pid pid = execute_server(server, params);
|
||||||
|
if (pid == SC_PROCESS_NONE) {
|
||||||
|
goto error_connection_failed;
|
||||||
|
}
|
||||||
|
sc_process_wait(pid, NULL); // ignore exit code
|
||||||
|
sc_process_close(pid);
|
||||||
|
// Wake up await_for_server()
|
||||||
|
server->cbs->on_connected(server, server->cbs_userdata);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int r = asprintf(&server->device_socket_name, SC_SOCKET_NAME_PREFIX "%08x",
|
int r = asprintf(&server->device_socket_name, SC_SOCKET_NAME_PREFIX "%08x",
|
||||||
params->scid);
|
params->scid);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
|
@ -857,11 +879,6 @@ run_server(void *data) {
|
||||||
assert(r == sizeof(SC_SOCKET_NAME_PREFIX) - 1 + 8);
|
assert(r == sizeof(SC_SOCKET_NAME_PREFIX) - 1 + 8);
|
||||||
assert(server->device_socket_name);
|
assert(server->device_socket_name);
|
||||||
|
|
||||||
ok = push_server(&server->intr, serial);
|
|
||||||
if (!ok) {
|
|
||||||
goto error_connection_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, serial,
|
ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, serial,
|
||||||
server->device_socket_name, params->port_range,
|
server->device_socket_name, params->port_range,
|
||||||
params->force_adb_forward);
|
params->force_adb_forward);
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct sc_server_params {
|
||||||
bool select_tcpip;
|
bool select_tcpip;
|
||||||
bool cleanup;
|
bool cleanup;
|
||||||
bool power_on;
|
bool power_on;
|
||||||
|
bool list_encoders;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_server {
|
struct sc_server {
|
||||||
|
|
|
@ -334,7 +334,7 @@ public final class AudioEncoder {
|
||||||
try {
|
try {
|
||||||
return MediaCodec.createByCodecName(encoderName);
|
return MediaCodec.createByCodecName(encoderName);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Ln.e(CodecUtils.buildUnknownEncoderMessage(codec, encoderName));
|
Ln.e("Encoder '" + encoderName + "' for " + codec.getName() + " not found\n" + CodecUtils.buildAudioEncoderListMessage());
|
||||||
throw new ConfigurationException("Unknown encoder: " + encoderName);
|
throw new ConfigurationException("Unknown encoder: " + encoderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ public final class CleanUp {
|
||||||
builder.start();
|
builder.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void unlinkSelf() {
|
public static void unlinkSelf() {
|
||||||
try {
|
try {
|
||||||
new File(SERVER_PATH).delete();
|
new File(SERVER_PATH).delete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -10,6 +10,24 @@ import java.util.List;
|
||||||
|
|
||||||
public final class CodecUtils {
|
public final class CodecUtils {
|
||||||
|
|
||||||
|
public static final class DeviceEncoder {
|
||||||
|
private final Codec codec;
|
||||||
|
private final MediaCodecInfo info;
|
||||||
|
|
||||||
|
DeviceEncoder(Codec codec, MediaCodecInfo info) {
|
||||||
|
this.codec = codec;
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Codec getCodec() {
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaCodecInfo getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CodecUtils() {
|
private CodecUtils() {
|
||||||
// not instantiable
|
// not instantiable
|
||||||
}
|
}
|
||||||
|
@ -26,28 +44,63 @@ public final class CodecUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String buildUnknownEncoderMessage(Codec codec, String encoderName) {
|
public static String buildVideoEncoderListMessage() {
|
||||||
StringBuilder msg = new StringBuilder("Encoder '").append(encoderName).append("' for ").append(codec.getName()).append(" not found");
|
StringBuilder builder = new StringBuilder("List of video encoders:");
|
||||||
MediaCodecInfo[] encoders = listEncoders(codec.getMimeType());
|
List<CodecUtils.DeviceEncoder> videoEncoders = CodecUtils.listVideoEncoders();
|
||||||
if (encoders != null && encoders.length > 0) {
|
if (videoEncoders.isEmpty()) {
|
||||||
msg.append("\nTry to use one of the available encoders:");
|
builder.append("\n (none)");
|
||||||
String codecOption = codec.getType() == Codec.Type.VIDEO ? "video-codec" : "audio-codec";
|
} else {
|
||||||
for (MediaCodecInfo encoder : encoders) {
|
for (CodecUtils.DeviceEncoder encoder : videoEncoders) {
|
||||||
msg.append("\n scrcpy --").append(codecOption).append("=").append(codec.getName());
|
builder.append("\n --video-codec=").append(encoder.getCodec().getName());
|
||||||
msg.append(" --encoder='").append(encoder.getName()).append("'");
|
builder.append(" --video-encoder='").append(encoder.getInfo().getName()).append("'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return msg.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaCodecInfo[] listEncoders(String mimeType) {
|
public static String buildAudioEncoderListMessage() {
|
||||||
|
StringBuilder builder = new StringBuilder("List of audio encoders:");
|
||||||
|
List<CodecUtils.DeviceEncoder> audioEncoders = CodecUtils.listAudioEncoders();
|
||||||
|
if (audioEncoders.isEmpty()) {
|
||||||
|
builder.append("\n (none)");
|
||||||
|
} else {
|
||||||
|
for (CodecUtils.DeviceEncoder encoder : audioEncoders) {
|
||||||
|
builder.append("\n --audio-codec=").append(encoder.getCodec().getName());
|
||||||
|
builder.append(" --audio-encoder='").append(encoder.getInfo().getName()).append("'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MediaCodecInfo[] getEncoders(MediaCodecList codecs, String mimeType) {
|
||||||
List<MediaCodecInfo> result = new ArrayList<>();
|
List<MediaCodecInfo> result = new ArrayList<>();
|
||||||
MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
for (MediaCodecInfo codecInfo : codecs.getCodecInfos()) {
|
||||||
for (MediaCodecInfo codecInfo : list.getCodecInfos()) {
|
|
||||||
if (codecInfo.isEncoder() && Arrays.asList(codecInfo.getSupportedTypes()).contains(mimeType)) {
|
if (codecInfo.isEncoder() && Arrays.asList(codecInfo.getSupportedTypes()).contains(mimeType)) {
|
||||||
result.add(codecInfo);
|
result.add(codecInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toArray(new MediaCodecInfo[result.size()]);
|
return result.toArray(new MediaCodecInfo[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<DeviceEncoder> listVideoEncoders() {
|
||||||
|
List<DeviceEncoder> encoders = new ArrayList<>();
|
||||||
|
MediaCodecList codecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
||||||
|
for (VideoCodec codec : VideoCodec.values()) {
|
||||||
|
for (MediaCodecInfo info : getEncoders(codecs, codec.getMimeType())) {
|
||||||
|
encoders.add(new DeviceEncoder(codec, info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encoders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<DeviceEncoder> listAudioEncoders() {
|
||||||
|
List<DeviceEncoder> encoders = new ArrayList<>();
|
||||||
|
MediaCodecList codecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
||||||
|
for (AudioCodec codec : AudioCodec.values()) {
|
||||||
|
for (MediaCodecInfo info : getEncoders(codecs, codec.getMimeType())) {
|
||||||
|
encoders.add(new DeviceEncoder(codec, info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encoders;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ public class Options {
|
||||||
private boolean cleanup = true;
|
private boolean cleanup = true;
|
||||||
private boolean powerOn = true;
|
private boolean powerOn = true;
|
||||||
|
|
||||||
|
private boolean listEncoders;
|
||||||
|
|
||||||
// Options not used by the scrcpy client, but useful to use scrcpy-server directly
|
// Options not used by the scrcpy client, but useful to use scrcpy-server directly
|
||||||
private boolean sendDeviceMeta = true; // send device name and size
|
private boolean sendDeviceMeta = true; // send device name and size
|
||||||
private boolean sendFrameMeta = true; // send PTS so that the client may record properly
|
private boolean sendFrameMeta = true; // send PTS so that the client may record properly
|
||||||
|
@ -239,6 +241,14 @@ public class Options {
|
||||||
this.powerOn = powerOn;
|
this.powerOn = powerOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getListEncoders() {
|
||||||
|
return listEncoders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListEncoders(boolean listEncoders) {
|
||||||
|
this.listEncoders = listEncoders;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getSendDeviceMeta() {
|
public boolean getSendDeviceMeta() {
|
||||||
return sendDeviceMeta;
|
return sendDeviceMeta;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
try {
|
try {
|
||||||
return MediaCodec.createByCodecName(encoderName);
|
return MediaCodec.createByCodecName(encoderName);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Ln.e(CodecUtils.buildUnknownEncoderMessage(codec, encoderName));
|
Ln.e("Encoder '" + encoderName + "' for " + codec.getName() + " not found\n" + CodecUtils.buildVideoEncoderListMessage());
|
||||||
throw new ConfigurationException("Unknown encoder: " + encoderName);
|
throw new ConfigurationException("Unknown encoder: " + encoderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,6 +291,10 @@ public final class Server {
|
||||||
boolean powerOn = Boolean.parseBoolean(value);
|
boolean powerOn = Boolean.parseBoolean(value);
|
||||||
options.setPowerOn(powerOn);
|
options.setPowerOn(powerOn);
|
||||||
break;
|
break;
|
||||||
|
case "list_encoders":
|
||||||
|
boolean listEncoders = Boolean.parseBoolean(value);
|
||||||
|
options.setListEncoders(listEncoders);
|
||||||
|
break;
|
||||||
case "send_device_meta":
|
case "send_device_meta":
|
||||||
boolean sendDeviceMeta = Boolean.parseBoolean(value);
|
boolean sendDeviceMeta = Boolean.parseBoolean(value);
|
||||||
options.setSendDeviceMeta(sendDeviceMeta);
|
options.setSendDeviceMeta(sendDeviceMeta);
|
||||||
|
@ -350,6 +354,17 @@ public final class Server {
|
||||||
|
|
||||||
Ln.initLogLevel(options.getLogLevel());
|
Ln.initLogLevel(options.getLogLevel());
|
||||||
|
|
||||||
|
if (options.getListEncoders()) {
|
||||||
|
if (options.getCleanup()) {
|
||||||
|
CleanUp.unlinkSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ln.i(CodecUtils.buildVideoEncoderListMessage());
|
||||||
|
Ln.i(CodecUtils.buildAudioEncoderListMessage());
|
||||||
|
// Just print the available encoders, do not mirror
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
scrcpy(options);
|
scrcpy(options);
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
Loading…
Reference in a new issue