mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-03 06:39:39 +00:00
feature: support dynamic bitrate
Change-Id: I362859b52a9d71152ca894ea2ec8aaa2f1f970d1
This commit is contained in:
parent
64a09513ae
commit
a86653b0c0
6 changed files with 129 additions and 1 deletions
|
@ -179,4 +179,20 @@ public final class ControlMessage {
|
||||||
public long getSequence() {
|
public long getSequence() {
|
||||||
return sequence;
|
return sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final int TYPE_REQ_IDR = 100;
|
||||||
|
public static final int TYPE_SET_BITRATE = 101;
|
||||||
|
|
||||||
|
private int bitRate;
|
||||||
|
|
||||||
|
public int getBitRate() {
|
||||||
|
return bitRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ControlMessage createSetBitrate(int bitRate) {
|
||||||
|
ControlMessage msg = new ControlMessage();
|
||||||
|
msg.type = TYPE_SET_BITRATE;
|
||||||
|
msg.bitRate = bitRate;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,13 @@ public class ControlMessageReader {
|
||||||
|
|
||||||
int type = buffer.get();
|
int type = buffer.get();
|
||||||
ControlMessage msg;
|
ControlMessage msg;
|
||||||
|
|
||||||
|
msg = preParseMsg(type);
|
||||||
|
if (msg != null) {
|
||||||
|
Ln.i("pre parsed msg: " + msg.getType());
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ControlMessage.TYPE_INJECT_KEYCODE:
|
case ControlMessage.TYPE_INJECT_KEYCODE:
|
||||||
msg = parseInjectKeycode();
|
msg = parseInjectKeycode();
|
||||||
|
@ -210,4 +217,27 @@ public class ControlMessageReader {
|
||||||
private static int toUnsigned(byte value) {
|
private static int toUnsigned(byte value) {
|
||||||
return value & 0xff;
|
return value & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final int SET_BITRATE_LENGTH = 4;
|
||||||
|
|
||||||
|
private ControlMessage preParseMsg(int type) {
|
||||||
|
switch(type) {
|
||||||
|
case ControlMessage.TYPE_REQ_IDR:
|
||||||
|
Ln.v("pre get msg TYPE_REQ_IDR event");
|
||||||
|
return ControlMessage.createEmpty(type);
|
||||||
|
case ControlMessage.TYPE_SET_BITRATE:
|
||||||
|
Ln.v("pre get msg TYPE_SET_BITRATE event" );
|
||||||
|
return parseSetBitrate();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ControlMessage parseSetBitrate() {
|
||||||
|
if (buffer.remaining() < SET_BITRATE_LENGTH) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int bitRate = buffer.getInt();
|
||||||
|
return ControlMessage.createSetBitrate(bitRate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,10 @@ public class Controller {
|
||||||
|
|
||||||
private void handleEvent() throws IOException {
|
private void handleEvent() throws IOException {
|
||||||
ControlMessage msg = connection.receiveControlMessage();
|
ControlMessage msg = connection.receiveControlMessage();
|
||||||
|
if (preHandlerEvent(msg)) {
|
||||||
|
Ln.i("pre handled event: " + msg.getType());
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (msg.getType()) {
|
switch (msg.getType()) {
|
||||||
case ControlMessage.TYPE_INJECT_KEYCODE:
|
case ControlMessage.TYPE_INJECT_KEYCODE:
|
||||||
if (device.supportsInputEvents()) {
|
if (device.supportsInputEvents()) {
|
||||||
|
@ -312,4 +316,23 @@ public class Controller {
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean preHandlerEvent(ControlMessage msg) {
|
||||||
|
boolean handled = true;
|
||||||
|
switch(msg.getType()) {
|
||||||
|
case ControlMessage.TYPE_REQ_IDR:
|
||||||
|
Ln.i("Device ControlMessage.TYPE_REQ_IDR ");
|
||||||
|
device.reqIDRFrame();
|
||||||
|
break;
|
||||||
|
case ControlMessage.TYPE_SET_BITRATE:
|
||||||
|
int bitrate = msg.getBitRate();
|
||||||
|
Ln.i("Device ControlMessage.TYPE_SET_BITRATE ");
|
||||||
|
device.setBitRate(bitrate);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handled = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,4 +319,29 @@ public final class Device {
|
||||||
public static Settings getSettings() {
|
public static Settings getSettings() {
|
||||||
return SETTINGS;
|
return SETTINGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface CodecChangeLister {
|
||||||
|
void onBitrateChanged(int bitrate);
|
||||||
|
void onReqIDRFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodecChangeLister codecChangeLister;
|
||||||
|
|
||||||
|
public void setCodecChangeLister(CodecChangeLister listener) {
|
||||||
|
codecChangeLister = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reqIDRFrame() {
|
||||||
|
Ln.i("do reqIDRFrame: " + codecChangeLister);
|
||||||
|
if (codecChangeLister != null) {
|
||||||
|
codecChangeLister.onReqIDRFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBitRate(int bitrate) {
|
||||||
|
Ln.i("do setBitRate: " + bitrate + codecChangeLister);
|
||||||
|
if (codecChangeLister != null) {
|
||||||
|
codecChangeLister.onBitrateChanged(bitrate);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
|
|
||||||
private final String encoderName;
|
private final String encoderName;
|
||||||
private final List<CodecOption> codecOptions;
|
private final List<CodecOption> codecOptions;
|
||||||
private final int bitRate;
|
private int bitRate;
|
||||||
private final int maxFps;
|
private final int maxFps;
|
||||||
private final boolean sendFrameMeta;
|
private final boolean sendFrameMeta;
|
||||||
private final boolean downsizeOnError;
|
private final boolean downsizeOnError;
|
||||||
|
@ -80,6 +80,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
try {
|
try {
|
||||||
do {
|
do {
|
||||||
MediaCodec codec = createCodec(encoderName);
|
MediaCodec codec = createCodec(encoderName);
|
||||||
|
initCodec(codec);
|
||||||
IBinder display = createDisplay();
|
IBinder display = createDisplay();
|
||||||
ScreenInfo screenInfo = device.getScreenInfo();
|
ScreenInfo screenInfo = device.getScreenInfo();
|
||||||
Rect contentRect = screenInfo.getContentRect();
|
Rect contentRect = screenInfo.getContentRect();
|
||||||
|
@ -293,4 +294,35 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
private static void destroyDisplay(IBinder display) {
|
private static void destroyDisplay(IBinder display) {
|
||||||
SurfaceControl.destroyDisplay(display);
|
SurfaceControl.destroyDisplay(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MediaCodec codec;
|
||||||
|
private Device.CodecChangeLister codecChangeLister;
|
||||||
|
|
||||||
|
private void initCodec(MediaCodec codec) {
|
||||||
|
this.codec = codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Device.CodecChangeLister getCodecChangeLister() {
|
||||||
|
if (codecChangeLister == null) {
|
||||||
|
codecChangeLister = new Device.CodecChangeLister() {
|
||||||
|
public void onBitrateChanged(int bitrate) {
|
||||||
|
bitRate = bitrate;
|
||||||
|
try {
|
||||||
|
Ln.i("do onBitrateChanged: " + bitrate);
|
||||||
|
android.os.Bundle b = new android.os.Bundle();
|
||||||
|
b.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bitRate);
|
||||||
|
codec.setParameters(b);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
Ln.e("onBitrateChanged failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onReqIDRFrame() {
|
||||||
|
Ln.i("do reqIDRFrame: " + rotationChanged);
|
||||||
|
rotationChanged.set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return codecChangeLister;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,8 @@ public final class Server {
|
||||||
controller.getSender().pushClipboardText(text);
|
controller.getSender().pushClipboardText(text);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
device.setCodecChangeLister(screenEncoder.getCodecChangeLister());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue