diff --git a/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java b/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java index 8a3c8287d02..b7b7e3905c0 100644 --- a/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java +++ b/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java @@ -15,9 +15,16 @@ */ package androidx.media3.demo.composition; +import static androidx.media3.transformer.Composition.HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR; +import static androidx.media3.transformer.Composition.HDR_MODE_KEEP_HDR; +import static androidx.media3.transformer.Composition.HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_MEDIACODEC; +import static androidx.media3.transformer.Composition.HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL; + import android.app.Activity; import android.content.DialogInterface; import android.os.Bundle; +import android.widget.ArrayAdapter; +import android.widget.Spinner; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; @@ -33,6 +40,8 @@ import androidx.media3.common.util.Clock; import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; +import androidx.media3.effect.LanczosResample; +import androidx.media3.effect.Presentation; import androidx.media3.effect.RgbFilter; import androidx.media3.transformer.Composition; import androidx.media3.transformer.CompositionPlayer; @@ -50,6 +59,7 @@ import com.google.common.base.Stopwatch; import com.google.common.base.Ticker; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -66,6 +76,17 @@ public final class CompositionPreviewActivity extends AppCompatActivity { private static final String TAG = "CompPreviewActivity"; private static final String AUDIO_URI = "https://storage.googleapis.com/exoplayer-test-media-0/play.mp3"; + private static final String SAME_AS_INPUT_OPTION = "same as input"; + private static final ImmutableMap HDR_MODE_DESCRIPTIONS = + new ImmutableMap.Builder() + .put("Keep HDR", HDR_MODE_KEEP_HDR) + .put("MediaCodec tone-map HDR to SDR", HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_MEDIACODEC) + .put("OpenGL tone-map HDR to SDR", HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL) + .put("Force Interpret HDR as SDR", HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR) + .build(); + private static final ImmutableList RESOLUTION_HEIGHTS = + ImmutableList.of( + SAME_AS_INPUT_OPTION, "144", "240", "360", "480", "720", "1080", "1440", "2160"); private ArrayList sequenceAssetTitles; private boolean[] selectedMediaItems; @@ -103,6 +124,19 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { backgroundAudioCheckBox.setOnCheckedChangeListener( (compoundButton, checked) -> includeBackgroundAudioTrack = checked); + ArrayAdapter resolutionHeightAdapter = + new ArrayAdapter<>(/* context= */ this, R.layout.spinner_item); + resolutionHeightAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + Spinner resolutionHeightSpinner = findViewById(R.id.resolution_height_spinner); + resolutionHeightSpinner.setAdapter(resolutionHeightAdapter); + resolutionHeightAdapter.addAll(RESOLUTION_HEIGHTS); + + ArrayAdapter hdrModeAdapter = new ArrayAdapter<>(this, R.layout.spinner_item); + hdrModeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + Spinner hdrModeSpinner = findViewById(R.id.hdr_mode_spinner); + hdrModeSpinner.setAdapter(hdrModeAdapter); + hdrModeAdapter.addAll(HDR_MODE_DESCRIPTIONS.keySet()); + AppCompatCheckBox applyVideoEffectsCheckBox = findViewById(R.id.apply_video_effects_checkbox); applyVideoEffectsCheckBox.setOnCheckedChangeListener( ((compoundButton, checked) -> appliesVideoEffects = checked)); @@ -150,12 +184,19 @@ private Composition prepareComposition() { String[] presetUris = getResources().getStringArray(/* id= */ R.array.preset_uris); int[] presetDurationsUs = getResources().getIntArray(/* id= */ R.array.preset_durations); List mediaItems = new ArrayList<>(); - ImmutableList videoEffects = - appliesVideoEffects - ? ImmutableList.of( - MatrixTransformationFactory.createDizzyCropEffect(), - RgbFilter.createGrayscaleFilter()) - : ImmutableList.of(); + ImmutableList.Builder videoEffectsBuilder = new ImmutableList.Builder<>(); + if (appliesVideoEffects) { + videoEffectsBuilder.add(MatrixTransformationFactory.createDizzyCropEffect()); + videoEffectsBuilder.add(RgbFilter.createGrayscaleFilter()); + } + Spinner resolutionHeightSpinner = findViewById(R.id.resolution_height_spinner); + String selectedResolutionHeight = String.valueOf(resolutionHeightSpinner.getSelectedItem()); + if (!SAME_AS_INPUT_OPTION.equals(selectedResolutionHeight)) { + int resolutionHeight = Integer.parseInt(selectedResolutionHeight); + videoEffectsBuilder.add(LanczosResample.scaleToFit(10000, resolutionHeight)); + videoEffectsBuilder.add(Presentation.createForHeight(resolutionHeight)); + } + ImmutableList videoEffects = videoEffectsBuilder.build(); // Preview requires all sequences to be the same duration, so calculate main sequence duration // and limit background sequence duration to match. long videoSequenceDurationUs = 0; @@ -187,11 +228,15 @@ private Composition prepareComposition() { } SonicAudioProcessor sampleRateChanger = new SonicAudioProcessor(); sampleRateChanger.setOutputSampleRateHz(8_000); + Spinner hdrModeSpinner = findViewById(R.id.hdr_mode_spinner); + int selectedHdrMode = + HDR_MODE_DESCRIPTIONS.get(String.valueOf(hdrModeSpinner.getSelectedItem())); return new Composition.Builder(/* sequences= */ compositionSequences) .setEffects( new Effects( /* audioProcessors= */ ImmutableList.of(sampleRateChanger), /* videoEffects= */ ImmutableList.of())) + .setHdrMode(selectedHdrMode) .build(); } @@ -238,7 +283,7 @@ private void selectPreset() { new AlertDialog.Builder(/* context= */ this) .setTitle(R.string.select_preset_title) .setMultiChoiceItems(presetDescriptions, selectedMediaItems, this::selectPresetInDialog) - .setPositiveButton(android.R.string.ok, /* listener= */ null) + .setPositiveButton(R.string.ok, /* listener= */ null) .setCancelable(false) .create() .show(); diff --git a/demos/composition/src/main/res/layout/composition_preview_activity.xml b/demos/composition/src/main/res/layout/composition_preview_activity.xml index 600065ee83a..c1910ea8d67 100644 --- a/demos/composition/src/main/res/layout/composition_preview_activity.xml +++ b/demos/composition/src/main/res/layout/composition_preview_activity.xml @@ -111,7 +111,49 @@ android:text="@string/add_background_audio" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toTopOf="@id/preview_button" /> + app:layout_constraintBottom_toTopOf="@id/resolution_height_setting" /> + + + + + + + + + + + + diff --git a/demos/composition/src/main/res/values/strings.xml b/demos/composition/src/main/res/values/strings.xml index ced548099ac..be124754cb6 100644 --- a/demos/composition/src/main/res/values/strings.xml +++ b/demos/composition/src/main/res/values/strings.xml @@ -26,4 +26,7 @@ Export error Export started Add background audio + Output video resolution + HDR mode + OK