fix: send the encoded stream size on the wire, desktop size separately - #64
Merged
tranvuongquocdat merged 1 commit intoSep 5, 2026
Conversation
displayConfig is not only what the client's overlay renders. It is what
the client sizes and selects its decoder from:
val supported = videoCaps.isSizeSupported(width, height)
val rateSupported = videoCaps.areSizeAndRateSupported(width, height, rate)
MediaFormat.createVideoFormat(mime, currentWidth, currentHeight)
With HiDPI on, the host deliberately sent the logical resolution so the
overlay would match the Mac's dropdown, while streaming the doubled
frame. Observed on 0.11.2 with HiDPI at 2560x1600:
Sent display config: 2560x1600 <- client sized its decoder from this
Stream configured: 5120x3200 <- client was actually fed this
So the client asked "can you decode 2560x1600 at 90fps", was told yes,
picked a decoder on that basis, and got 5120x3200. The only throughput
check on the client ran against a resolution that was never the stream.
MediaCodec does adapt from the SPS afterwards, but selection and the
capability check have already happened.
displayConfig now always carries the encoded size. The logical desktop
travels in a new message so the overlay can still show it:
type 12 client -> server, payload-free: "I read displayConfig as the
encoded size and understand type 13"
type 13 server -> client, 8-byte payload: logical desktop size
Type 13 is sent only to clients that sent type 12, because older clients
disconnect on unknown message types. Older hosts consume type 12 as one
unknown byte and carry on, so both directions stay compatible.
The overlay shows the stream size, appending the desktop size only when
the two differ, so a scaled HiDPI desktop is visible rather than quietly
standing in for the resolution being sent.
Verified on device with HiDPI at 1920x1080:
Mac -> display config: 3840x2160
Mac -> desktop geometry: 1920x1080
Tablet -> setupDecoder: 3840x2160, decoder=c2.exynos.hevc.decoder
The decoder is now configured for the frame it will receive. Before this
it was configured for 1920x1080.
|
@meta-boy is attempting to deploy a commit to the tranvuongquocdat2-7001's projects Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
displayConfigis not only what the client's overlay renders. It is what the client sizes and selects its decoder from:With HiDPI on,
AppDelegatesends the logical resolution so the overlay matches the Mac's resolution dropdown, while the stream is the doubled frame. Observed on 0.11.2 with HiDPI at 2560x1600:The client asks "can you decode 2560x1600 at 90fps", is told yes, picks a decoder on that basis, and is handed 5120x3200. The only throughput check that exists on the client runs against a resolution that is never the stream. MediaCodec does adapt from the SPS afterwards, but decoder selection and the capability check have already happened by then.
The intent behind sending the logical size is good and worth keeping: an overlay reading "5120x3200" when the user picked 2560x1600 is confusing. The mistake is carrying it in the field the decoder reads.
Fix
displayConfigalways carries the encoded size now. The logical desktop moves to its own message.Type 13 goes only to clients that sent type 12, because older clients disconnect on unknown message types (the same constraint that governs
codecSelected). Older hosts consume type 12 as a single unknown byte and carry on. Both directions stay compatible.The overlay shows the stream size, appending the desktop size only when the two differ:
so a scaled HiDPI desktop is visible rather than quietly standing in for the resolution being sent.
Verification
On device, HiDPI at 1920x1080:
The decoder is configured for the frame it will actually receive. Before this change it was configured for 1920x1080 and fed 3840x2160.
Handshake ordering is unchanged: type 12 is advertised alongside types 9 and 11, before type 8, so it lands before
finishProtocolStartupruns and the firstdisplayConfiggoes out.macOS builds clean, 35/35 tests pass. Android compiles clean, unit tests pass, ktlint clean.
Note on scope
This removes the
unclampedHevcbranch inAppDelegate, which existed to keep the logical resolution for unclamped HEVC. With the encoded size always on the wire, that special case has nothing left to do.Independent of the decode-ceiling work in #62: no shared files, and either can land first. #62 makes the clamp engage more often, which happens to route around this bug in those cases. This PR fixes it outright, including the case #62 does not reach, where the client genuinely can decode the doubled frame and no clamping occurs.