Implement isNoOp for LanczosResample
This allows for transmuxing whenever resolutions match, and LanczosResample is in the video effects chain. PiperOrigin-RevId: 645433104
This commit is contained in:
parent
d16004781e
commit
476ec607f2
@ -23,6 +23,7 @@ import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmap;
|
||||
import static androidx.media3.test.utils.TestUtil.PSNR_THRESHOLD;
|
||||
import static androidx.media3.test.utils.TestUtil.assertBitmapsAreSimilar;
|
||||
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
@ -129,6 +130,27 @@ public class LanczosResampleTest {
|
||||
assertBitmapsAreSimilar(expectedBitmap, actualBitmap, PSNR_THRESHOLD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNoOp_whenSizeDoesntChange_returnsTrue() {
|
||||
LanczosResample lanczosResample = LanczosResample.scaleToFit(720, 1280);
|
||||
|
||||
assertThat(lanczosResample.isNoOp(720, 1280)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNoOp_forSmallScalingFactors_returnsTrue() {
|
||||
LanczosResample lanczosResample = LanczosResample.scaleToFit(1920, 1072);
|
||||
|
||||
assertThat(lanczosResample.isNoOp(1920, 1080)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNoOp_forLargeScalingFactors_returnsTrue() {
|
||||
LanczosResample lanczosResample = LanczosResample.scaleToFit(1920, 1068);
|
||||
|
||||
assertThat(lanczosResample.isNoOp(1920, 1080)).isFalse();
|
||||
}
|
||||
|
||||
private static GlTextureInfo setupInputTexture(String path) throws Exception {
|
||||
Bitmap inputBitmap = readBitmap(path);
|
||||
return new GlTextureInfo(
|
||||
|
@ -16,6 +16,7 @@
|
||||
package androidx.media3.effect;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.Math.round;
|
||||
|
||||
@ -37,6 +38,9 @@ public final class LanczosResample implements GlEffect {
|
||||
// Default value for the radius, or alpha parameter used by Lanczos filter. A value of 3 is
|
||||
// used by ffmpeg (https://ffmpeg.org/ffmpeg-scaler.html), libplacebo, or Apple's vImage library.
|
||||
private static final float DEFAULT_RADIUS = 3f;
|
||||
// For scaling factors near 1, this algorithm won't bring a big improvement over bilinear or
|
||||
// nearest sampling using the GPU texture units
|
||||
private static final float NO_OP_THRESHOLD = 0.01f;
|
||||
|
||||
private final float radius;
|
||||
private final int width;
|
||||
@ -68,6 +72,37 @@ public final class LanczosResample implements GlEffect {
|
||||
context, useHdr, new LanczosResampleScaledFunctionProvider(radius, width, height));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>For scaling factors near 1, this effect applies no change because the Lanczos algorithm
|
||||
* won't bring a big improvement over bilinear or nearest sampling using the GPU texture units.
|
||||
*/
|
||||
@Override
|
||||
public boolean isNoOp(int inputWidth, int inputHeight) {
|
||||
return abs(scalingFactorToFit(inputWidth, inputHeight, width, height) - 1f) < NO_OP_THRESHOLD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scaling factor required to fit an input image into a target rectangle.
|
||||
*
|
||||
* @param inputWidth The width of the input image.
|
||||
* @param inputHeight The height of the input image.
|
||||
* @param targetWidth The width of the target rectangle.
|
||||
* @param targetHeight The height of the target rectangle.
|
||||
*/
|
||||
private static float scalingFactorToFit(
|
||||
int inputWidth, int inputHeight, int targetWidth, int targetHeight) {
|
||||
checkArgument(inputWidth > 0);
|
||||
checkArgument(inputHeight > 0);
|
||||
// Scale to fit, preserving aspect ratio.
|
||||
if (inputHeight * targetWidth <= targetHeight * inputWidth) {
|
||||
return (float) targetWidth / inputWidth;
|
||||
} else {
|
||||
return (float) targetHeight / inputHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LanczosResampleScaledFunctionProvider
|
||||
implements ConvolutionFunction1D.Provider {
|
||||
// Note: We deliberately don't use Float.MIN_VALUE because it's positive & very close to zero.
|
||||
@ -101,16 +136,8 @@ public final class LanczosResample implements GlEffect {
|
||||
|
||||
@Override
|
||||
public Size configure(Size inputSize) {
|
||||
checkArgument(inputSize.getWidth() > 0);
|
||||
checkArgument(inputSize.getHeight() > 0);
|
||||
// Scale to fit, preserving aspect ratio.
|
||||
if (inputSize.getHeight() * width <= height * inputSize.getWidth()) {
|
||||
scale = (float) width / inputSize.getWidth();
|
||||
return new Size(width, round(inputSize.getHeight() * scale));
|
||||
} else {
|
||||
scale = (float) height / inputSize.getHeight();
|
||||
return new Size(round(inputSize.getWidth() * scale), height);
|
||||
}
|
||||
scale = scalingFactorToFit(inputSize.getWidth(), inputSize.getHeight(), width, height);
|
||||
return new Size(round(inputSize.getWidth() * scale), round(inputSize.getHeight() * scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user