mirror of
https://github.com/androidx/media.git
synced 2025-05-11 09:39:52 +08:00
Improve encoder resolution capability checking.
Whilst testing fallback functionality, I found that we were aggressively reducing the resolution if it was not supported. A quick test found that we could reduce by a much smaller increments. Performance wise it appears these checks are incredibly quick. The code for checking supported sizes was duplicated, with one case having a bug because of this duplication (2/3 case). This CL abstracts this into a loop. PiperOrigin-RevId: 499497646
This commit is contained in:
parent
2eb255431f
commit
37f8a0bb6b
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package androidx.media3.transformer;
|
package androidx.media3.transformer;
|
||||||
|
|
||||||
|
import static java.lang.Math.floor;
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
import static java.lang.Math.round;
|
import static java.lang.Math.round;
|
||||||
|
|
||||||
@ -226,49 +227,33 @@ public final class EncoderUtil {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public static Size getSupportedResolution(
|
public static Size getSupportedResolution(
|
||||||
MediaCodecInfo encoderInfo, String mimeType, int width, int height) {
|
MediaCodecInfo encoderInfo, String mimeType, int width, int height) {
|
||||||
MediaCodecInfo.VideoCapabilities videoEncoderCapabilities =
|
MediaCodecInfo.VideoCapabilities videoCapabilities =
|
||||||
encoderInfo.getCapabilitiesForType(mimeType).getVideoCapabilities();
|
encoderInfo.getCapabilitiesForType(mimeType).getVideoCapabilities();
|
||||||
int widthAlignment = videoEncoderCapabilities.getWidthAlignment();
|
int widthAlignment = videoCapabilities.getWidthAlignment();
|
||||||
int heightAlignment = videoEncoderCapabilities.getHeightAlignment();
|
int heightAlignment = videoCapabilities.getHeightAlignment();
|
||||||
|
|
||||||
// Fix size alignment.
|
// Fix size alignment.
|
||||||
width = alignResolution(width, widthAlignment);
|
int newWidth = alignResolution(width, widthAlignment);
|
||||||
height = alignResolution(height, heightAlignment);
|
int newHeight = alignResolution(height, heightAlignment);
|
||||||
if (isSizeSupported(encoderInfo, mimeType, width, height)) {
|
|
||||||
return new Size(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try three-fourths (e.g. 1440 -> 1080).
|
|
||||||
int newWidth = alignResolution(width * 3 / 4, widthAlignment);
|
|
||||||
int newHeight = alignResolution(height * 3 / 4, heightAlignment);
|
|
||||||
if (isSizeSupported(encoderInfo, mimeType, newWidth, newHeight)) {
|
if (isSizeSupported(encoderInfo, mimeType, newWidth, newHeight)) {
|
||||||
return new Size(newWidth, newHeight);
|
return new Size(newWidth, newHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try two-thirds (e.g. 4k -> 1440).
|
float[] reductionFactors =
|
||||||
newWidth = alignResolution(width * 2 / 3, widthAlignment);
|
new float[] {
|
||||||
newHeight = alignResolution(height * 2 / 3, heightAlignment);
|
0.95f, 0.9f, 0.85f, 0.8f, 0.75f, 0.7f, 2f / 3f, 0.6f, 0.55f, 0.5f, 0.4f, 1f / 3f
|
||||||
if (isSizeSupported(encoderInfo, mimeType, width, height)) {
|
};
|
||||||
return new Size(newWidth, newHeight);
|
for (float reductionFactor : reductionFactors) {
|
||||||
}
|
newWidth = alignResolution(round(width * reductionFactor), widthAlignment);
|
||||||
|
newHeight = alignResolution(round(height * reductionFactor), heightAlignment);
|
||||||
// Try half (e.g. 4k -> 1080).
|
if (isSizeSupported(encoderInfo, mimeType, newWidth, newHeight)) {
|
||||||
newWidth = alignResolution(width / 2, widthAlignment);
|
return new Size(newWidth, newHeight);
|
||||||
newHeight = alignResolution(height / 2, heightAlignment);
|
}
|
||||||
if (isSizeSupported(encoderInfo, mimeType, newWidth, newHeight)) {
|
|
||||||
return new Size(newWidth, newHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try one-third (e.g. 4k -> 720).
|
|
||||||
newWidth = alignResolution(width / 3, widthAlignment);
|
|
||||||
newHeight = alignResolution(height / 3, heightAlignment);
|
|
||||||
if (isSizeSupported(encoderInfo, mimeType, newWidth, newHeight)) {
|
|
||||||
return new Size(newWidth, newHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix frame being too wide or too tall.
|
// Fix frame being too wide or too tall.
|
||||||
width = videoEncoderCapabilities.getSupportedWidths().clamp(width);
|
width = videoCapabilities.getSupportedWidths().clamp(width);
|
||||||
int adjustedHeight = videoEncoderCapabilities.getSupportedHeightsFor(width).clamp(height);
|
int adjustedHeight = videoCapabilities.getSupportedHeightsFor(width).clamp(height);
|
||||||
if (adjustedHeight != height) {
|
if (adjustedHeight != height) {
|
||||||
width =
|
width =
|
||||||
alignResolution((int) round((double) width * adjustedHeight / height), widthAlignment);
|
alignResolution((int) round((double) width * adjustedHeight / height), widthAlignment);
|
||||||
@ -437,8 +422,8 @@ public final class EncoderUtil {
|
|||||||
shouldRoundDown = true;
|
shouldRoundDown = true;
|
||||||
}
|
}
|
||||||
return shouldRoundDown
|
return shouldRoundDown
|
||||||
? (int) (alignment * Math.floor((float) size / alignment))
|
? (int) (alignment * floor((float) size / alignment))
|
||||||
: alignment * Math.round((float) size / alignment);
|
: alignment * round((float) size / alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static synchronized void maybePopulateEncoderInfo() {
|
private static synchronized void maybePopulateEncoderInfo() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user