From d20c11442a21ebfe3154f8eea034577179b3d837 Mon Sep 17 00:00:00 2001 From: tofunmi Date: Fri, 17 Feb 2023 09:57:09 +0000 Subject: [PATCH] Update demo app with image input Adds a new option to the preset file list to show an image for 5secs at 30fps. Also adds an ImageView to show the input image PiperOrigin-RevId: 510372035 --- .../transformer/ConfigurationActivity.java | 2 + .../demo/transformer/TransformerActivity.java | 64 ++++++++++++++++--- .../main/res/layout/transformer_activity.xml | 6 ++ .../src/main/res/values/strings.xml | 1 + 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java index dfe34f8766..96dc951cd9 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java @@ -132,6 +132,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "https://storage.googleapis.com/exoplayer-test-media-0/BigBuckBunny_320x180.mp4", "https://storage.googleapis.com/exoplayer-test-media-1/mp4/portrait_avc_aac.mp4", "https://storage.googleapis.com/exoplayer-test-media-1/mp4/portrait_rotated_avc_aac.mp4", + "https://storage.googleapis.com/exoplayer-test-media-1/jpg/london.jpg", "https://storage.googleapis.com/exoplayer-test-media-1/mp4/slow-motion/slowMotion_stopwatch_240fps_long.mp4", "https://storage.googleapis.com/exoplayer-test-media-1/gen/screens/dash-vod-single-segment/manifest-baseline.mpd", "https://storage.googleapis.com/exoplayer-test-media-1/mp4/samsung-s21-hdr-hdr10.mp4", @@ -149,6 +150,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "Long 180p H264 video and AAC audio", "H264 video and AAC audio (portrait, H > W, 0\u00B0)", "H264 video and AAC audio (portrait, H < W, 90\u00B0)", + "JPG image (Plays for 5secs at 30fps)", "SEF slow motion with 240 fps", "480p DASH (non-square pixels)", "HDR (HDR10) H265 limited range video (encoding may fail)", diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index bf5586f690..27e8b8e59a 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -27,6 +27,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -41,6 +42,7 @@ import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; @@ -53,6 +55,7 @@ import androidx.media3.common.Effect; import androidx.media3.common.MediaItem; import androidx.media3.common.audio.AudioProcessor; import androidx.media3.common.audio.SonicAudioProcessor; +import androidx.media3.common.util.BitmapLoader; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.Log; import androidx.media3.effect.BitmapOverlay; @@ -68,6 +71,7 @@ import androidx.media3.effect.RgbAdjustment; import androidx.media3.effect.RgbFilter; import androidx.media3.effect.RgbMatrix; import androidx.media3.effect.ScaleToFitTransformation; +import androidx.media3.effect.SimpleBitmapLoader; import androidx.media3.effect.SingleColorLut; import androidx.media3.effect.TextOverlay; import androidx.media3.effect.TextureOverlay; @@ -91,10 +95,12 @@ import com.google.android.material.progressindicator.LinearProgressIndicator; import com.google.common.base.Stopwatch; import com.google.common.base.Ticker; import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.ListenableFuture; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; @@ -105,6 +111,8 @@ public final class TransformerActivity extends AppCompatActivity { private @MonotonicNonNull Button displayInputButton; private @MonotonicNonNull MaterialCardView inputCardView; + private @MonotonicNonNull TextView inputTextView; + private @MonotonicNonNull ImageView inputImageView; private @MonotonicNonNull PlayerView inputPlayerView; private @MonotonicNonNull PlayerView outputPlayerView; private @MonotonicNonNull TextView debugTextView; @@ -126,6 +134,8 @@ public final class TransformerActivity extends AppCompatActivity { setContentView(R.layout.transformer_activity); inputCardView = findViewById(R.id.input_card_view); + inputTextView = findViewById(R.id.input_text_view); + inputImageView = findViewById(R.id.input_image_view); inputPlayerView = findViewById(R.id.input_player_view); outputPlayerView = findViewById(R.id.output_player_view); debugTextView = findViewById(R.id.debug_text_view); @@ -154,6 +164,8 @@ public final class TransformerActivity extends AppCompatActivity { checkNotNull(informationTextView); checkNotNull(transformationStopwatch); checkNotNull(inputCardView); + checkNotNull(inputTextView); + checkNotNull(inputImageView); checkNotNull(inputPlayerView); checkNotNull(outputPlayerView); checkNotNull(debugTextView); @@ -187,6 +199,8 @@ public final class TransformerActivity extends AppCompatActivity { @RequiresNonNull({ "inputCardView", + "inputTextView", + "inputImageView", "inputPlayerView", "outputPlayerView", "displayInputButton", @@ -262,6 +276,8 @@ public final class TransformerActivity extends AppCompatActivity { @RequiresNonNull({ "inputCardView", + "inputTextView", + "inputImageView", "inputPlayerView", "outputPlayerView", "displayInputButton", @@ -349,6 +365,8 @@ public final class TransformerActivity extends AppCompatActivity { if (bundle == null) { return editedMediaItemBuilder.build(); } + // For image inputs. Automatically ignored if input is audio/video. + editedMediaItemBuilder.setDurationUs(5_000_000).setFrameRate(30); ImmutableList audioProcessors = createAudioProcessorsFromBundle(bundle); ImmutableList videoEffects = createVideoEffectsFromBundle(bundle); return editedMediaItemBuilder @@ -616,6 +634,8 @@ public final class TransformerActivity extends AppCompatActivity { @RequiresNonNull({ "inputCardView", + "inputTextView", + "inputImageView", "inputPlayerView", "outputPlayerView", "displayInputButton", @@ -641,6 +661,8 @@ public final class TransformerActivity extends AppCompatActivity { @RequiresNonNull({ "inputCardView", + "inputTextView", + "inputImageView", "inputPlayerView", "outputPlayerView", "debugTextView", @@ -649,14 +671,7 @@ public final class TransformerActivity extends AppCompatActivity { inputPlayerView.setPlayer(null); outputPlayerView.setPlayer(null); releasePlayer(); - - ExoPlayer inputPlayer = new ExoPlayer.Builder(/* context= */ this).build(); - inputPlayerView.setPlayer(inputPlayer); - inputPlayerView.setControllerAutoShow(false); - inputPlayer.setMediaItem(inputMediaItem); - inputPlayer.prepare(); - this.inputPlayer = inputPlayer; - inputPlayer.setVolume(0f); + Uri uri = checkNotNull(inputMediaItem.localConfiguration).uri; ExoPlayer outputPlayer = new ExoPlayer.Builder(/* context= */ this).build(); outputPlayerView.setPlayer(outputPlayer); @@ -665,7 +680,34 @@ public final class TransformerActivity extends AppCompatActivity { outputPlayer.prepare(); this.outputPlayer = outputPlayer; - inputPlayer.play(); + // Only support showing jpg images. + if (uri.toString().endsWith("jpg")) { + inputPlayerView.setVisibility(View.GONE); + inputImageView.setVisibility(View.VISIBLE); + inputTextView.setText(getString(R.string.input_image)); + + BitmapLoader bitmapLoader = new SimpleBitmapLoader(); + ListenableFuture future = bitmapLoader.loadBitmap(uri); + try { + Bitmap bitmap = future.get(); + inputImageView.setImageBitmap(bitmap); + } catch (ExecutionException | InterruptedException e) { + throw new IllegalArgumentException("Failed to load bitmap.", e); + } + } else { + inputPlayerView.setVisibility(View.VISIBLE); + inputImageView.setVisibility(View.GONE); + inputTextView.setText(getString(R.string.input_video)); + + ExoPlayer inputPlayer = new ExoPlayer.Builder(/* context= */ this).build(); + inputPlayerView.setPlayer(inputPlayer); + inputPlayerView.setControllerAutoShow(false); + inputPlayer.setMediaItem(inputMediaItem); + inputPlayer.prepare(); + this.inputPlayer = inputPlayer; + inputPlayer.setVolume(0f); + inputPlayer.play(); + } outputPlayer.play(); debugTextViewHelper = new DebugTextViewHelper(outputPlayer, debugTextView); @@ -708,7 +750,9 @@ public final class TransformerActivity extends AppCompatActivity { inputCardView.setVisibility(View.VISIBLE); displayInputButton.setText(getString(R.string.hide_input_video)); } else if (inputCardView.getVisibility() == View.VISIBLE) { - checkNotNull(inputPlayer).pause(); + if (inputPlayer != null) { + inputPlayer.pause(); + } inputCardView.setVisibility(View.GONE); displayInputButton.setText(getString(R.string.show_input_video)); } diff --git a/demos/transformer/src/main/res/layout/transformer_activity.xml b/demos/transformer/src/main/res/layout/transformer_activity.xml index 05e2e4892f..c0749f5f77 100644 --- a/demos/transformer/src/main/res/layout/transformer_activity.xml +++ b/demos/transformer/src/main/res/layout/transformer_activity.xml @@ -69,6 +69,7 @@ android:layout_height="wrap_content" > + + Hue adjustment Saturation adjustment Lightness adjustment + Input image: Input video: Output video: Permission Denied