diff --git a/app/src/demuxer.c b/app/src/demuxer.c index bebdb6d6..c2f4a636 100644 --- a/app/src/demuxer.c +++ b/app/src/demuxer.c @@ -13,7 +13,10 @@ #define BUFSIZE 0x10000 #define HEADER_SIZE 12 -#define NO_PTS UINT64_C(-1) + +#define SC_PACKET_FLAG_CONFIG (UINT64_C(1) << 63) + +#define SC_PACKET_PTS_MASK (SC_PACKET_FLAG_CONFIG - 1) static bool sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { @@ -28,6 +31,14 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { // size // // It is followed by bytes containing the packet/frame. + // + // 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 uint8_t header[HEADER_SIZE]; ssize_t r = net_recv_all(demuxer->socket, header, HEADER_SIZE); @@ -35,9 +46,8 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { return false; } - uint64_t pts = buffer_read64be(header); + uint64_t pts_flags = buffer_read64be(header); uint32_t len = buffer_read32be(&header[8]); - assert(pts == NO_PTS || (pts & 0x8000000000000000) == 0); assert(len); if (av_new_packet(packet, len)) { @@ -51,7 +61,11 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) { return false; } - packet->pts = pts != NO_PTS ? (int64_t) pts : AV_NOPTS_VALUE; + if (pts_flags & SC_PACKET_FLAG_CONFIG) { + packet->pts = AV_NOPTS_VALUE; + } else { + packet->pts = pts_flags & SC_PACKET_PTS_MASK; + } 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 79efc17c..a51a8a32 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java @@ -28,7 +28,7 @@ public class ScreenEncoder implements Device.RotationListener { // Keep the values in descending order private static final int[] MAX_SIZE_FALLBACK = {2560, 1920, 1600, 1280, 1024, 800}; - private static final int NO_PTS = -1; + private static final long PACKET_FLAG_CONFIG = 1L << 63; private final AtomicBoolean rotationChanged = new AtomicBoolean(); private final ByteBuffer headerBuffer = ByteBuffer.allocate(12); @@ -183,7 +183,7 @@ public class ScreenEncoder implements Device.RotationListener { long pts; if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) { - pts = NO_PTS; // non-media data packet + pts = PACKET_FLAG_CONFIG; // non-media data packet } else { if (ptsOrigin == 0) { ptsOrigin = bufferInfo.presentationTimeUs;