Repository navigation
Stream screens with an odd width or height - #180
Merged
Merged
Conversation
libx264 refuses an odd width or height (4:2:0 needs even dimensions), so a 1680x945 screen with no usable hardware encoder never streamed: the encoder failed to open on every restart until the pipeline gave up. The encoder now opens at the even size below the capture and drops the odd last column or row, on every input path (swscale to YUV420P/NV12, Accelerate on macOS, the BGRA copy NVENC reads). The crop reads the capture's top-left region in place, so no pixel is resampled. The size check compares encoded sizes, so an odd capture does not reopen the encoder every frame. The stream config, GUI and stats report the encoded size; one info line per open names both sizes. Input still maps onto the whole capture: each pixel of the cropped picture lands on itself and the picture's far edge reaches the row or column left out.
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.
What
The Windows host now encodes a screen with an odd width or height at the even size below it, leaving out the odd last column or row. It crops and doesn't scale, so every other pixel stays exact.
Why
A user's PC with a 1680×945 display couldn't stream. The iPad connected, but no picture arrived and the PC showed "Streaming is off". Their graphics card has no encoder EternalMonitor can use, so the host fell back to libx264, which refuses odd sizes:
At 1366×768 it streamed. 4:2:0 needs even dimensions. Before this change, nothing made the encoder's size even.
How
encoder::encoded_sizerounds the capture's width and height down to even numbers.EncoderState::newopens at that size and logs one info line when it crops (capture_size=1680x945 encoded_size=1680x944). The two fields are on the redaction allowlist and covered by its test.EncoderState::convertnow does all the conversion the encode loop used to do inline. It reads the top-left region of the capture at the capture's own row stride, on every input path: swscale to YUV420P/NV12 (convert_packed_bgraand its padding-free copy now take the row stride), Accelerate on macOS, and the BGRA copy NVENC reads.accepts_framecompares encoded sizes, so an odd capture doesn't reopen the encoder on every frame.PipelineStats::capture_resolutionstores the encoded size, so the stream config the iPad gets, the GUI and the periodic stats summary all report what is actually streamed.session_summarycarries no size.scripts/e2e_ios.shexpects the even decoded size whenEM_SIZEis odd.Testing
encoder::tests::odd_screen_sizes_encode_at_the_even_size_below: opens libx264 at 1680×945, 1365×768 and 641×361, encodes 10 frames each, then decodes them at the even size and reads back the synthetic frame counter. On the base, libx264 fails to open at 1680×945 ("Generic error in an external library").encoder::tests::cropping_changes_no_pixel_of_the_picture: for 1365×945, 1365×944 and 1366×945, on YUV420P, NV12, BGRA and Accelerate, with and without padding after the last row, converting the odd capture gives byte-identical planes to converting its top-left region on its own. For BGRA it also matches the source pixels directly.input::tests::a_cropped_picture_maps_each_pixel_onto_itself: on a 1365×945 output, every displayed pixel centre maps onto itself, and the edge maps to the column and row left out.e2e_synthetic::an_odd_screen_streams_cropped_and_input_still_reaches_its_edge: the real supervisor with a 641×361 synthetic capture and libx264. Heartbeats report 640×360, decoded pictures are 640×360 with rising counters, a touch on the last displayed pixel lands there, and the far edge reaches pixel (640, 360). On the base it fails: libx264 can't open, and the encoder restarts six times.EM_SIZE=641x361 scripts/e2e_ios.sh(Wi-Fi): 240 frames decoded at 640×360 and 60 fps, with no drops, and the pattern check passed.InputGestureTests/testVideoGesturesAndKeyboardagainst a 641×361 host: all five taps landed within one pixel of their targets on the 641×361 desktop.cargo fmt --check,cargo clippy --workspace --all-targets -D warningsandcargo test --workspacepass on macOS.Release notes: Screens with an odd number of pixels, such as 1680×945, now stream instead of stopping.