Commit eea1868d by tofunmi Committed by christosts

Add sRGB eotf to overlay fragment shader.

The eotf is needed so that overlay (image) colors are correctly interpreted and mixed the linear video colors.

Also replaces the 100winners.png with "homemade" image file.

Added GlEffectsFrameProcessor test to justify that the color looks correct at the end of frame processing.

PiperOrigin-RevId: 506290309
parent eb8fffba
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.effect;
import static com.google.android.exoplayer2.effect.OverlayTextureProcessorPixelTest.OVERLAY_PNG_ASSET_PATH;
import static com.google.android.exoplayer2.testutil.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
import static com.google.android.exoplayer2.testutil.BitmapPixelTestUtil.getBitmapAveragePixelAbsoluteDifferenceArgb8888;
import static com.google.android.exoplayer2.testutil.BitmapPixelTestUtil.readBitmap;
......@@ -34,6 +35,7 @@ import com.google.android.exoplayer2.util.Size;
import com.google.common.collect.ImmutableList;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -52,6 +54,9 @@ import org.junit.runner.RunWith;
public final class GlEffectsFrameProcessorPixelTest {
public static final String ORIGINAL_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png";
// This file is generated on a Pixel 7, because the emulator isn't able to generate this file.
public static final String BITMAP_OVERLAY_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_FrameProcessor.png";
public static final String SCALE_WIDE_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/scale_wide.png";
public static final String TRANSLATE_RIGHT_PNG_ASSET_PATH =
......@@ -170,6 +175,26 @@ public final class GlEffectsFrameProcessorPixelTest {
}
@Test
@Ignore("b/267031388 Test can only run on physical devices because emulator cannot produce image")
public void bitmapOverlay_matchesGoldenFile() throws Exception {
String testId = "bitmapOverlay_matchesGoldenFile";
Bitmap overlayBitmap = readBitmap(OVERLAY_PNG_ASSET_PATH);
BitmapOverlay bitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(overlayBitmap);
frameProcessorTestRunner =
getDefaultFrameProcessorTestRunnerBuilder(testId)
.setEffects(new OverlayEffect(ImmutableList.of(bitmapOverlay)))
.build();
Bitmap expectedBitmap = readBitmap(BITMAP_OVERLAY_PNG_ASSET_PATH);
Bitmap actualBitmap = frameProcessorTestRunner.processFirstFrameAndEnd();
// TODO(b/207848601): switch to using proper tooling for testing against golden data.
float averagePixelAbsoluteDifference =
getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, testId);
assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
}
@Test
public void scaleToFitAndMatrixTransformation_matchesGoldenFile() throws Exception {
String testId = "scaleToFitAndMatrixTransformation_matchesGoldenFile";
Matrix translateRightMatrix = new Matrix();
......
......@@ -58,7 +58,7 @@ import org.junit.runner.RunWith;
*/
@RunWith(AndroidJUnit4.class)
public class OverlayTextureProcessorPixelTest {
public static final String OVERLAY_PNG_ASSET_PATH = "media/bitmap/overlay/100winners.png";
public static final String OVERLAY_PNG_ASSET_PATH = "media/bitmap/overlay/media3test.png";
public static final String ORIGINAL_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png";
public static final String OVERLAY_BITMAP_DEFAULT =
......@@ -132,9 +132,9 @@ public class OverlayTextureProcessorPixelTest {
public void drawFrame_bitmapOverlay_blendsBitmapIntoFrame() throws Exception {
String testId = "drawFrame_bitmapOverlay";
Bitmap overlayBitmap = readBitmap(OVERLAY_PNG_ASSET_PATH);
BitmapOverlay scaledBitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(overlayBitmap);
BitmapOverlay bitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(overlayBitmap);
overlayTextureProcessor =
new OverlayEffect(ImmutableList.of(scaledBitmapOverlay))
new OverlayEffect(ImmutableList.of(bitmapOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
......
......@@ -234,6 +234,21 @@ import com.google.common.collect.ImmutableList;
.append(" } else {\n")
.append(" return clamp(overlayAlpha/videoAlpha, 0.0, 1.0);\n")
.append(" }\n")
.append("}\n")
.append("")
.append("float srgbEotfSingleChannel(float srgb) {\n")
.append(" return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);\n")
.append("}\n")
.append("// sRGB EOTF.\n")
.append("vec3 applyEotf(const vec3 srgb) {\n")
.append("// Reference implementation:\n")
.append(
"// https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/renderengine/gl/ProgramCache.cpp;drc=de09f10aa504fd8066370591a00c9ff1cafbb7fa;l=235\n")
.append(" return vec3(\n")
.append(" srgbEotfSingleChannel(srgb.r),\n")
.append(" srgbEotfSingleChannel(srgb.g),\n")
.append(" srgbEotfSingleChannel(srgb.b)\n")
.append(" );\n")
.append("}\n");
for (int texUnitIndex = 1; texUnitIndex <= numOverlays; texUnitIndex++) {
......@@ -253,15 +268,22 @@ import com.google.common.collect.ImmutableList;
shader
.append(
Util.formatInvariant(
" vec4 overlayColor%d = getClampToBorderOverlayColor(\n", texUnitIndex))
" vec4 electricalOverlayColor%d = getClampToBorderOverlayColor(\n",
texUnitIndex))
.append(
Util.formatInvariant(
" uOverlayTexSampler%d, vOverlayTexSamplingCoord%d, uOverlayAlpha%d);\n",
texUnitIndex, texUnitIndex, texUnitIndex))
.append(Util.formatInvariant(" vec4 opticalOverlayColor%d = vec4(\n", texUnitIndex))
.append(
Util.formatInvariant(
" applyEotf(electricalOverlayColor%d.rgb), electricalOverlayColor%d.a);\n",
texUnitIndex, texUnitIndex))
.append(" fragColor = mix(\n")
.append(
Util.formatInvariant(
" fragColor, overlayColor%d, getMixAlpha(videoColor.a, overlayColor%d.a));\n",
" fragColor, opticalOverlayColor%d, getMixAlpha(videoColor.a,"
+ " opticalOverlayColor%d.a));\n",
texUnitIndex, texUnitIndex));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment