Do not expose frame rate in ScreenEncoder
The KEY_FRAME_RATE parameter value is necessary for the configuration of the encoder, but its actual value does not impact the frame rate (only resources used by the encoder). Therefore, it's an internal detail and should not be exposed by the ScreenEncoder class.
This commit is contained in:
parent
1b78a77962
commit
fb976816f9
1 changed files with 8 additions and 12 deletions
|
@ -17,32 +17,27 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class ScreenEncoder implements Device.RotationListener {
|
public class ScreenEncoder implements Device.RotationListener {
|
||||||
|
|
||||||
private static final int DEFAULT_FRAME_RATE = 60; // fps
|
|
||||||
private static final int DEFAULT_I_FRAME_INTERVAL = 10; // seconds
|
private static final int DEFAULT_I_FRAME_INTERVAL = 10; // seconds
|
||||||
|
private static final int REPEAT_FRAME_DELAY_US = 100_000; // repeat after 100ms
|
||||||
|
|
||||||
private static final int REPEAT_FRAME_DELAY = 6; // repeat after 6 frames
|
|
||||||
|
|
||||||
private static final int MICROSECONDS_IN_ONE_SECOND = 1_000_000;
|
|
||||||
private static final int NO_PTS = -1;
|
private static final int NO_PTS = -1;
|
||||||
|
|
||||||
private final AtomicBoolean rotationChanged = new AtomicBoolean();
|
private final AtomicBoolean rotationChanged = new AtomicBoolean();
|
||||||
private final ByteBuffer headerBuffer = ByteBuffer.allocate(12);
|
private final ByteBuffer headerBuffer = ByteBuffer.allocate(12);
|
||||||
|
|
||||||
private int bitRate;
|
private int bitRate;
|
||||||
private int frameRate;
|
|
||||||
private int iFrameInterval;
|
private int iFrameInterval;
|
||||||
private boolean sendFrameMeta;
|
private boolean sendFrameMeta;
|
||||||
private long ptsOrigin;
|
private long ptsOrigin;
|
||||||
|
|
||||||
public ScreenEncoder(boolean sendFrameMeta, int bitRate, int frameRate, int iFrameInterval) {
|
public ScreenEncoder(boolean sendFrameMeta, int bitRate, int iFrameInterval) {
|
||||||
this.sendFrameMeta = sendFrameMeta;
|
this.sendFrameMeta = sendFrameMeta;
|
||||||
this.bitRate = bitRate;
|
this.bitRate = bitRate;
|
||||||
this.frameRate = frameRate;
|
|
||||||
this.iFrameInterval = iFrameInterval;
|
this.iFrameInterval = iFrameInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScreenEncoder(boolean sendFrameMeta, int bitRate) {
|
public ScreenEncoder(boolean sendFrameMeta, int bitRate) {
|
||||||
this(sendFrameMeta, bitRate, DEFAULT_FRAME_RATE, DEFAULT_I_FRAME_INTERVAL);
|
this(sendFrameMeta, bitRate, DEFAULT_I_FRAME_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,7 +60,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
// <https://github.com/Genymobile/scrcpy/issues/921>
|
// <https://github.com/Genymobile/scrcpy/issues/921>
|
||||||
Looper.prepareMainLooper();
|
Looper.prepareMainLooper();
|
||||||
|
|
||||||
MediaFormat format = createFormat(bitRate, frameRate, iFrameInterval);
|
MediaFormat format = createFormat(bitRate, iFrameInterval);
|
||||||
device.setRotationListener(this);
|
device.setRotationListener(this);
|
||||||
boolean alive;
|
boolean alive;
|
||||||
try {
|
try {
|
||||||
|
@ -148,15 +143,16 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
return MediaCodec.createEncoderByType("video/avc");
|
return MediaCodec.createEncoderByType("video/avc");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaFormat createFormat(int bitRate, int frameRate, int iFrameInterval) throws IOException {
|
private static MediaFormat createFormat(int bitRate, int iFrameInterval) throws IOException {
|
||||||
MediaFormat format = new MediaFormat();
|
MediaFormat format = new MediaFormat();
|
||||||
format.setString(MediaFormat.KEY_MIME, "video/avc");
|
format.setString(MediaFormat.KEY_MIME, "video/avc");
|
||||||
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
|
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
|
||||||
format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
|
// must be present to configure the encoder, but does not impact the actual frame rate, which is variable
|
||||||
|
format.setInteger(MediaFormat.KEY_FRAME_RATE, 60);
|
||||||
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
|
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
|
||||||
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
|
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
|
||||||
// display the very first frame, and recover from bad quality when no new frames
|
// display the very first frame, and recover from bad quality when no new frames
|
||||||
format.setLong(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, MICROSECONDS_IN_ONE_SECOND * REPEAT_FRAME_DELAY / frameRate); // µs
|
format.setLong(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, REPEAT_FRAME_DELAY_US); // µs
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue