mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-04-21 01:33:36 +00:00
Respect encoder maximum size constraint
Encoders cannot encode at any resolution. Use video capabilities to constrain a given size by the limits of the selected encoder. These video capabilities describe the range of supported widths and heights, as well as the supported heights for a given width (and vice-versa). Use this information to compute the maximum portrait size and the maximum landscape size. PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
This commit is contained in:
parent
809718ed25
commit
33b1bc6209
4 changed files with 83 additions and 13 deletions
|
|
@ -39,24 +39,38 @@ public final class Size {
|
|||
assert alignment > 0 : "Alignment must be positive";
|
||||
assert (alignment & (alignment - 1)) == 0 : "Alignment must be a power-of-two";
|
||||
|
||||
int alignedMaxSize = maxSize / alignment * alignment; // round to a multiple of alignment
|
||||
int w, h;
|
||||
boolean portrait = width < height;
|
||||
Size maxCodecSize = portrait ? constraints.getMaxCodecPortraitSize() : constraints.getMaxCodecLandscapeSize();
|
||||
|
||||
if (maxSize > 0 && (width > alignedMaxSize || height > alignedMaxSize)) {
|
||||
if (width > height) {
|
||||
w = alignedMaxSize;
|
||||
h = round(height * alignedMaxSize / width, alignment);
|
||||
int maxWidth = maxCodecSize.width;
|
||||
int maxHeight = maxCodecSize.height;
|
||||
if (maxSize > 0) {
|
||||
if (maxSize < maxWidth) {
|
||||
maxWidth = maxSize;
|
||||
}
|
||||
if (maxSize < maxHeight) {
|
||||
maxHeight = maxSize;
|
||||
}
|
||||
}
|
||||
maxWidth = maxWidth / alignment * alignment;
|
||||
maxHeight = maxHeight / alignment * alignment;
|
||||
|
||||
int w, h;
|
||||
if (width > maxWidth || height > maxHeight) {
|
||||
if (width * maxHeight > height * maxWidth) {
|
||||
w = maxWidth;
|
||||
h = round(height * maxWidth / width, alignment);
|
||||
} else {
|
||||
w = round(width * alignedMaxSize / height, alignment);
|
||||
h = alignedMaxSize;
|
||||
w = round(width * maxHeight / height, alignment);
|
||||
h = maxHeight;
|
||||
}
|
||||
} else {
|
||||
w = round(width, alignment);
|
||||
h = round(height, alignment);
|
||||
}
|
||||
|
||||
assert maxSize == 0 || w <= maxSize : "The width cannot exceed maxSize if maxSize is aligned";
|
||||
assert maxSize == 0 || h <= maxSize : "The height cannot exceed maxSize if maxSize is aligned";
|
||||
assert w <= maxWidth : "The width cannot exceed maxWidth";
|
||||
assert h <= maxHeight : "The height cannot exceed maxHeight";
|
||||
|
||||
return new Size(w, h);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,15 @@ public class SurfaceEncoder implements AsyncProcessor {
|
|||
Ln.d("Actual video size alignment: " + alignment + "px");
|
||||
}
|
||||
|
||||
return new VideoConstraints(maxSize, alignment);
|
||||
int maxLandscapeWidth = caps.getSupportedWidths().getUpper();
|
||||
int maxLandscapeHeight = caps.getSupportedHeightsFor(maxLandscapeWidth).getUpper();
|
||||
Size maxLandscapeSize = new Size(maxLandscapeWidth, maxLandscapeHeight);
|
||||
|
||||
int maxPortraitHeight = caps.getSupportedHeights().getUpper();
|
||||
int maxPortraitWidth = caps.getSupportedWidthsFor(maxPortraitHeight).getUpper();
|
||||
Size maxPortraitSize = new Size(maxPortraitWidth, maxPortraitHeight);
|
||||
|
||||
return new VideoConstraints(maxSize, alignment, maxLandscapeSize, maxPortraitSize);
|
||||
}
|
||||
|
||||
private void streamCapture() throws IOException, ConfigurationException {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,26 @@
|
|||
package com.genymobile.scrcpy.video;
|
||||
|
||||
import com.genymobile.scrcpy.device.Size;
|
||||
|
||||
public class VideoConstraints {
|
||||
private final int maxSize;
|
||||
private final int alignment;
|
||||
private final Size maxCodecLandscapeSize;
|
||||
private final Size maxCodecPortraitSize;
|
||||
|
||||
public VideoConstraints(int maxSize, int alignment) {
|
||||
public VideoConstraints(int maxSize, int alignment, Size maxCodecLandscapeSize, Size maxCodecPortraitSize) {
|
||||
assert maxSize >= 0 : "Max size must not be negative";
|
||||
this.maxSize = maxSize;
|
||||
|
||||
assert alignment > 0 : "Alignment must be positive";
|
||||
assert (alignment & (alignment - 1)) == 0 : "Alignment must be a power-of-two";
|
||||
this.alignment = alignment;
|
||||
|
||||
assert maxCodecLandscapeSize != null;
|
||||
this.maxCodecLandscapeSize = maxCodecLandscapeSize;
|
||||
|
||||
assert maxCodecPortraitSize != null;
|
||||
this.maxCodecPortraitSize = maxCodecPortraitSize;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -32,4 +42,22 @@ public class VideoConstraints {
|
|||
public int getAlignment() {
|
||||
return alignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max landscape size supported by the codec.
|
||||
*
|
||||
* @return the max landscape size
|
||||
*/
|
||||
public Size getMaxCodecLandscapeSize() {
|
||||
return maxCodecLandscapeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max portrait size supported by the codec.
|
||||
*
|
||||
* @return the max portrait size
|
||||
*/
|
||||
public Size getMaxCodecPortraitSize() {
|
||||
return maxCodecPortraitSize;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@ import org.junit.Test;
|
|||
public class SizeTest {
|
||||
|
||||
private VideoConstraints createVideoConstraints(int maxSize, int alignment) {
|
||||
return new VideoConstraints(maxSize, alignment);
|
||||
Size maxCodecSize = new Size(4096, 4096);
|
||||
return createVideoConstraints(maxSize, alignment, maxCodecSize);
|
||||
}
|
||||
|
||||
private VideoConstraints createVideoConstraints(int maxSize, int alignment, Size maxCodecSize) {
|
||||
return new VideoConstraints(maxSize, alignment, maxCodecSize, maxCodecSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -39,4 +44,19 @@ public class SizeTest {
|
|||
Assert.assertEquals(size, size.constrain(createVideoConstraints(0, 16)));
|
||||
Assert.assertEquals(size, size.constrain(createVideoConstraints(4096, 16)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstrainMaxCodecSize() {
|
||||
Size maxCodecSize = new Size(400, 600);
|
||||
|
||||
Size size = new Size(314, 617);
|
||||
Assert.assertEquals(new Size(314 * 600 / 617, 600), size.constrain(createVideoConstraints(0, 1, maxCodecSize)));
|
||||
Assert.assertEquals(new Size(314 * 550 / 617, 550), size.constrain(createVideoConstraints(550, 1, maxCodecSize)));
|
||||
|
||||
size = new Size(512, 536);
|
||||
Assert.assertEquals(new Size(400, 536 * 400 / 512), size.constrain(createVideoConstraints(0, 1, maxCodecSize)));
|
||||
Assert.assertEquals(new Size(400, 536 * 400 / 512), size.constrain(createVideoConstraints(550, 1, maxCodecSize)));
|
||||
Assert.assertEquals(new Size(400, 536 * 400 / 512), size.constrain(createVideoConstraints(500, 1, maxCodecSize)));
|
||||
Assert.assertEquals(new Size(512 * 410 / 536, 410), size.constrain(createVideoConstraints(410, 1, maxCodecSize)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue