Add HDR & Resolution Height settings to demo-composition
Added UI and logic implementation for HDR mode and Resolution Height to be used as settings for both previewing and exporting. PiperOrigin-RevId: 684011852
This commit is contained in:
parent
c744fe9f8f
commit
d5baa4ce59
@ -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.audio.SonicAudioProcessor;
|
||||
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 androidx.recyclerview.widget.RecyclerView;
|
||||
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<String, @Composition.HdrMode Integer> HDR_MODE_DESCRIPTIONS =
|
||||
new ImmutableMap.Builder<String, @Composition.HdrMode Integer>()
|
||||
.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<String> RESOLUTION_HEIGHTS =
|
||||
ImmutableList.of(
|
||||
SAME_AS_INPUT_OPTION, "144", "240", "360", "480", "720", "1080", "1440", "2160");
|
||||
|
||||
private ArrayList<String> sequenceAssetTitles;
|
||||
private boolean[] selectedMediaItems;
|
||||
@ -103,6 +124,19 @@ public final class CompositionPreviewActivity extends AppCompatActivity {
|
||||
backgroundAudioCheckBox.setOnCheckedChangeListener(
|
||||
(compoundButton, checked) -> includeBackgroundAudioTrack = checked);
|
||||
|
||||
ArrayAdapter<String> 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<String> 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 @@ public final class CompositionPreviewActivity extends AppCompatActivity {
|
||||
String[] presetUris = getResources().getStringArray(/* id= */ R.array.preset_uris);
|
||||
int[] presetDurationsUs = getResources().getIntArray(/* id= */ R.array.preset_durations);
|
||||
List<EditedMediaItem> mediaItems = new ArrayList<>();
|
||||
ImmutableList<Effect> videoEffects =
|
||||
appliesVideoEffects
|
||||
? ImmutableList.of(
|
||||
MatrixTransformationFactory.createDizzyCropEffect(),
|
||||
RgbFilter.createGrayscaleFilter())
|
||||
: ImmutableList.of();
|
||||
ImmutableList.Builder<Effect> 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<Effect> 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 @@ public final class CompositionPreviewActivity extends AppCompatActivity {
|
||||
}
|
||||
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 @@ public final class CompositionPreviewActivity extends AppCompatActivity {
|
||||
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();
|
||||
|
@ -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" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/resolution_height_setting"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/hdr_mode_setting">
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/output_video_resolution"/>
|
||||
<Spinner
|
||||
android:id="@+id/resolution_height_spinner"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:gravity="end"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/hdr_mode_setting"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/preview_button">
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/hdr_mode" />
|
||||
<Spinner
|
||||
android:id="@+id/hdr_mode_spinner"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:gravity="end"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/composition_export_button"
|
||||
|
25
demos/composition/src/main/res/layout/spinner_item.xml
Normal file
25
demos/composition/src/main/res/layout/spinner_item.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:textIsSelectable="false" />
|
@ -26,4 +26,7 @@
|
||||
<string name="export_error" translatable="false">Export error</string>
|
||||
<string name="export_started" translatable="false">Export started</string>
|
||||
<string name="add_background_audio" translatable="false">Add background audio</string>
|
||||
<string name="output_video_resolution" translatable="false">Output video resolution</string>
|
||||
<string name="hdr_mode" translatable="false">HDR mode</string>
|
||||
<string name="ok" translatable="false">OK</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user