Add --list-encoders

Add an option to list the device encoders properly.
This commit is contained in:
Romain Vimont 2023-02-22 23:15:15 +01:00
commit 55f4c42f19
16 changed files with 157 additions and 29 deletions

View file

@ -334,7 +334,7 @@ public final class AudioEncoder {
try {
return MediaCodec.createByCodecName(encoderName);
} 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);
}
}

View file

@ -139,7 +139,7 @@ public final class CleanUp {
builder.start();
}
private static void unlinkSelf() {
public static void unlinkSelf() {
try {
new File(SERVER_PATH).delete();
} catch (Exception e) {

View file

@ -10,6 +10,24 @@ import java.util.List;
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() {
// not instantiable
}
@ -26,28 +44,63 @@ public final class CodecUtils {
}
}
public static String buildUnknownEncoderMessage(Codec codec, String encoderName) {
StringBuilder msg = new StringBuilder("Encoder '").append(encoderName).append("' for ").append(codec.getName()).append(" not found");
MediaCodecInfo[] encoders = listEncoders(codec.getMimeType());
if (encoders != null && encoders.length > 0) {
msg.append("\nTry to use one of the available encoders:");
String codecOption = codec.getType() == Codec.Type.VIDEO ? "video-codec" : "audio-codec";
for (MediaCodecInfo encoder : encoders) {
msg.append("\n scrcpy --").append(codecOption).append("=").append(codec.getName());
msg.append(" --encoder='").append(encoder.getName()).append("'");
public static String buildVideoEncoderListMessage() {
StringBuilder builder = new StringBuilder("List of video encoders:");
List<CodecUtils.DeviceEncoder> videoEncoders = CodecUtils.listVideoEncoders();
if (videoEncoders.isEmpty()) {
builder.append("\n (none)");
} else {
for (CodecUtils.DeviceEncoder encoder : videoEncoders) {
builder.append("\n --video-codec=").append(encoder.getCodec().getName());
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<>();
MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
for (MediaCodecInfo codecInfo : list.getCodecInfos()) {
for (MediaCodecInfo codecInfo : codecs.getCodecInfos()) {
if (codecInfo.isEncoder() && Arrays.asList(codecInfo.getSupportedTypes()).contains(mimeType)) {
result.add(codecInfo);
}
}
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;
}
}

View file

@ -33,6 +33,8 @@ public class Options {
private boolean cleanup = true;
private boolean powerOn = true;
private boolean listEncoders;
// 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 sendFrameMeta = true; // send PTS so that the client may record properly
@ -239,6 +241,14 @@ public class Options {
this.powerOn = powerOn;
}
public boolean getListEncoders() {
return listEncoders;
}
public void setListEncoders(boolean listEncoders) {
this.listEncoders = listEncoders;
}
public boolean getSendDeviceMeta() {
return sendDeviceMeta;
}

View file

@ -202,7 +202,7 @@ public class ScreenEncoder implements Device.RotationListener {
try {
return MediaCodec.createByCodecName(encoderName);
} 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);
}
}

View file

@ -291,6 +291,10 @@ public final class Server {
boolean powerOn = Boolean.parseBoolean(value);
options.setPowerOn(powerOn);
break;
case "list_encoders":
boolean listEncoders = Boolean.parseBoolean(value);
options.setListEncoders(listEncoders);
break;
case "send_device_meta":
boolean sendDeviceMeta = Boolean.parseBoolean(value);
options.setSendDeviceMeta(sendDeviceMeta);
@ -350,6 +354,17 @@ public final class Server {
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 {
scrcpy(options);
} catch (ConfigurationException e) {