Skip to content

Commit

Permalink
Do not expose frame rate in ScreenEncoder
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rom1v committed Nov 17, 2019
1 parent 1b78a77 commit fb97681
Showing 1 changed file with 8 additions and 12 deletions.
20 changes: 8 additions & 12 deletions server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,27 @@

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 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 final AtomicBoolean rotationChanged = new AtomicBoolean();
private final ByteBuffer headerBuffer = ByteBuffer.allocate(12);

private int bitRate;
private int frameRate;
private int iFrameInterval;
private boolean sendFrameMeta;
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.bitRate = bitRate;
this.frameRate = frameRate;
this.iFrameInterval = iFrameInterval;
}

public ScreenEncoder(boolean sendFrameMeta, int bitRate) {
this(sendFrameMeta, bitRate, DEFAULT_FRAME_RATE, DEFAULT_I_FRAME_INTERVAL);
this(sendFrameMeta, bitRate, DEFAULT_I_FRAME_INTERVAL);
}

@Override
Expand All @@ -65,7 +60,7 @@ public void streamScreen(Device device, FileDescriptor fd) throws IOException {
// <https://github.com/Genymobile/scrcpy/issues/921>
Looper.prepareMainLooper();

MediaFormat format = createFormat(bitRate, frameRate, iFrameInterval);
MediaFormat format = createFormat(bitRate, iFrameInterval);
device.setRotationListener(this);
boolean alive;
try {
Expand Down Expand Up @@ -148,15 +143,16 @@ private static MediaCodec createCodec() throws IOException {
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();
format.setString(MediaFormat.KEY_MIME, "video/avc");
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_I_FRAME_INTERVAL, iFrameInterval);
// 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;
}

Expand Down

0 comments on commit fb97681

Please sign in to comment.