From 67068e4e3d7ab17de425651848eecea530ac8b88 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 11 Feb 2022 19:33:35 +0100 Subject: [PATCH] Pass key frame flag from the device MediaCodec indicates when a packet is a key frame. Transmit it to the client. --- app/src/demuxer.c | 16 +++++++++++----- .../com/genymobile/scrcpy/ScreenEncoder.java | 4 ++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/src/demuxer.c b/app/src/demuxer.c index c2f4a636..417abd27 100644 --- a/app/src/demuxer.c +++ b/app/src/demuxer.c @@ -15,8 +15,9 @@ #define HEADER_SIZE 12 #define SC_PACKET_FLAG_CONFIG (UINT64_C(1) << 63) +#define SC_PACKET_FLAG_KEY_FRAME (UINT64_C(1) << 62) -#define SC_PACKET_PTS_MASK (SC_PACKET_FLAG_CONFIG - 1) +#define SC_PACKET_PTS_MASK (SC_PACKET_FLAG_KEY_FRAME - 1) static bool sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { @@ -35,10 +36,11 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { // The most significant bits of the PTS are used for packet flags: // // byte 7 byte 6 byte 5 byte 4 byte 3 byte 2 byte 1 byte 0 - // C....... ........ ........ ........ ........ ........ ........ ........ - // ^<--------------------------------------------------------------------> - // | PTS - // `- config packet + // CK...... ........ ........ ........ ........ ........ ........ ........ + // ^^<-------------------------------------------------------------------> + // || PTS + // | `- config packet + // `-- key frame uint8_t header[HEADER_SIZE]; ssize_t r = net_recv_all(demuxer->socket, header, HEADER_SIZE); @@ -67,6 +69,10 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { packet->pts = pts_flags & SC_PACKET_PTS_MASK; } + if (pts_flags & SC_PACKET_FLAG_KEY_FRAME) { + packet->flags |= AV_PKT_FLAG_KEY; + } + return true; } diff --git a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java index a51a8a32..f97206ec 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java @@ -29,6 +29,7 @@ public class ScreenEncoder implements Device.RotationListener { private static final int[] MAX_SIZE_FALLBACK = {2560, 1920, 1600, 1280, 1024, 800}; private static final long PACKET_FLAG_CONFIG = 1L << 63; + private static final long PACKET_FLAG_KEY_FRAME = 1L << 62; private final AtomicBoolean rotationChanged = new AtomicBoolean(); private final ByteBuffer headerBuffer = ByteBuffer.allocate(12); @@ -189,6 +190,9 @@ public class ScreenEncoder implements Device.RotationListener { ptsOrigin = bufferInfo.presentationTimeUs; } pts = bufferInfo.presentationTimeUs - ptsOrigin; + if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) { + pts |= PACKET_FLAG_KEY_FRAME; + } } headerBuffer.putLong(pts);