diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java
index b36a53be89..2b6c4c4b18 100644
--- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java
+++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java
@@ -67,7 +67,11 @@ public final class ConfigurationActivity extends AppCompatActivity {
public static final String PERIODIC_VIGNETTE_CENTER_Y = "periodic_vignette_center_y";
public static final String PERIODIC_VIGNETTE_INNER_RADIUS = "periodic_vignette_inner_radius";
public static final String PERIODIC_VIGNETTE_OUTER_RADIUS = "periodic_vignette_outer_radius";
+ public static final String COLOR_FILTER_SELECTION = "color_filter_selection";
public static final String CONTRAST_VALUE = "contrast_value";
+ public static final int COLOR_FILTER_GRAYSCALE = 0;
+ public static final int COLOR_FILTER_INVERTED = 1;
+ public static final int COLOR_FILTER_SEPIA = 2;
private static final String[] INPUT_URIS = {
"https://storage.googleapis.com/exoplayer-test-media-1/mp4/android-screens-10s.mp4",
"https://storage.googleapis.com/exoplayer-test-media-0/android-block-1080-hevc.mp4",
@@ -101,14 +105,16 @@ public final class ConfigurationActivity extends AppCompatActivity {
private static final String[] DEMO_EFFECTS = {
"Dizzy crop",
"Edge detector (Media Pipe)",
+ "Color filters",
"Contrast",
"Periodic vignette",
"3D spin",
"Overlay logo & timer",
"Zoom in start",
};
- private static final int CONTRAST_INDEX = 2;
- private static final int PERIODIC_VIGNETTE_INDEX = 3;
+ private static final int COLOR_FILTERS_INDEX = 2;
+ private static final int CONTRAST_INDEX = 3;
+ private static final int PERIODIC_VIGNETTE_INDEX = 4;
private static final String SAME_AS_INPUT_OPTION = "same as input";
private static final float HALF_DIAGONAL = 1f / (float) Math.sqrt(2);
@@ -132,6 +138,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
private int inputUriPosition;
private long trimStartMs;
private long trimEndMs;
+ private int colorFilterSelection;
private float contrastValue;
private float periodicVignetteCenterX;
private float periodicVignetteCenterY;
@@ -288,6 +295,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
ENABLE_REQUEST_SDR_TONE_MAPPING, enableRequestSdrToneMappingCheckBox.isChecked());
bundle.putBoolean(ENABLE_HDR_EDITING, enableHdrEditingCheckBox.isChecked());
bundle.putBooleanArray(DEMO_EFFECTS_SELECTIONS, demoEffectsSelections);
+ bundle.putInt(COLOR_FILTER_SELECTION, colorFilterSelection);
bundle.putFloat(CONTRAST_VALUE, contrastValue);
bundle.putFloat(PERIODIC_VIGNETTE_CENTER_X, periodicVignetteCenterX);
bundle.putFloat(PERIODIC_VIGNETTE_CENTER_Y, periodicVignetteCenterY);
@@ -356,6 +364,9 @@ public final class ConfigurationActivity extends AppCompatActivity {
}
switch (which) {
+ case COLOR_FILTERS_INDEX:
+ controlColorFiltersSettings();
+ break;
case CONTRAST_INDEX:
controlContrastSettings();
break;
@@ -365,6 +376,24 @@ public final class ConfigurationActivity extends AppCompatActivity {
}
}
+ private void controlColorFiltersSettings() {
+ new AlertDialog.Builder(/* context= */ this)
+ .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> dialogInterface.dismiss())
+ .setSingleChoiceItems(
+ this.getResources().getStringArray(R.array.color_filter_options),
+ colorFilterSelection,
+ (DialogInterface dialogInterface, int i) -> {
+ checkState(
+ i == COLOR_FILTER_GRAYSCALE
+ || i == COLOR_FILTER_INVERTED
+ || i == COLOR_FILTER_SEPIA);
+ colorFilterSelection = i;
+ dialogInterface.dismiss();
+ })
+ .create()
+ .show();
+ }
+
private void controlContrastSettings() {
View dialogView = getLayoutInflater().inflate(R.layout.contrast_options, /* root= */ null);
Slider contrastSlider = checkNotNull(dialogView.findViewById(R.id.contrast_slider));
@@ -372,9 +401,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
.setView(dialogView)
.setPositiveButton(
android.R.string.ok,
- (DialogInterface dialogInterface, int i) -> {
- contrastValue = contrastSlider.getValue();
- })
+ (DialogInterface dialogInterface, int i) -> contrastValue = contrastSlider.getValue())
.create()
.show();
}
diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java
index 32744a2580..049984ee94 100644
--- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java
+++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java
@@ -40,6 +40,8 @@ import androidx.media3.common.Effect;
import androidx.media3.effect.Contrast;
import androidx.media3.effect.GlEffect;
import androidx.media3.effect.GlTextureProcessor;
+import androidx.media3.effect.RgbFilter;
+import androidx.media3.effect.RgbMatrix;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
@@ -308,9 +310,35 @@ public final class TransformerActivity extends AppCompatActivity {
}
}
if (selectedEffects[2]) {
- effects.add(new Contrast(bundle.getFloat(ConfigurationActivity.CONTRAST_VALUE)));
+ switch (bundle.getInt(ConfigurationActivity.COLOR_FILTER_SELECTION)) {
+ case ConfigurationActivity.COLOR_FILTER_GRAYSCALE:
+ effects.add(RgbFilter.createGrayscaleFilter());
+ break;
+ case ConfigurationActivity.COLOR_FILTER_INVERTED:
+ effects.add(RgbFilter.createInvertedFilter());
+ break;
+ case ConfigurationActivity.COLOR_FILTER_SEPIA:
+ // W3C Sepia RGBA matrix with sRGB as a target color space:
+ // https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
+ // The matrix is defined for the sRGB color space and the Transformer library
+ // uses a linear RGB color space internally. Meaning this is only for demonstration
+ // purposes and it does not display a correct sepia frame.
+ float[] sepiaMatrix = {
+ 0.393f, 0.349f, 0.272f, 0, 0.769f, 0.686f, 0.534f, 0, 0.189f, 0.168f, 0.131f, 0, 0,
+ 0, 0, 1
+ };
+ effects.add((RgbMatrix) (presentationTimeUs, useHdr) -> sepiaMatrix);
+ break;
+ default:
+ throw new IllegalStateException(
+ "Unexpected color filter "
+ + bundle.getInt(ConfigurationActivity.COLOR_FILTER_SELECTION));
+ }
}
if (selectedEffects[3]) {
+ effects.add(new Contrast(bundle.getFloat(ConfigurationActivity.CONTRAST_VALUE)));
+ }
+ if (selectedEffects[4]) {
effects.add(
(GlEffect)
(Context context, boolean useHdr) ->
@@ -325,13 +353,13 @@ public final class TransformerActivity extends AppCompatActivity {
ConfigurationActivity.PERIODIC_VIGNETTE_OUTER_RADIUS),
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_OUTER_RADIUS)));
}
- if (selectedEffects[4]) {
+ if (selectedEffects[5]) {
effects.add(MatrixTransformationFactory.createSpin3dEffect());
}
- if (selectedEffects[5]) {
+ if (selectedEffects[6]) {
effects.add((GlEffect) BitmapOverlayProcessor::new);
}
- if (selectedEffects[6]) {
+ if (selectedEffects[7]) {
effects.add(MatrixTransformationFactory.createZoomInTransition());
}
transformerBuilder.setVideoEffects(effects.build());
diff --git a/demos/transformer/src/main/res/values/strings.xml b/demos/transformer/src/main/res/values/strings.xml
index a1d40b5c0b..32eba87a73 100644
--- a/demos/transformer/src/main/res/values/strings.xml
+++ b/demos/transformer/src/main/res/values/strings.xml
@@ -42,6 +42,11 @@
Transformation completed in %d seconds.
Transformation error
Bounds in seconds
+
+ - Grayscale
+ - Inverted
+ - Sepia
+
Contrast value
Center X
Center Y