Add second player for input video

PiperOrigin-RevId: 478510687
(cherry picked from commit 48a7f6a9240cd7c0ce8016915de630d903e5c393)
This commit is contained in:
Googler 2022-10-03 15:27:33 +00:00 committed by microkatz
parent 186f516b65
commit c8917b50e6
3 changed files with 156 additions and 57 deletions

View File

@ -60,6 +60,7 @@ import androidx.media3.transformer.TransformationResult;
import androidx.media3.transformer.Transformer; import androidx.media3.transformer.Transformer;
import androidx.media3.ui.AspectRatioFrameLayout; import androidx.media3.ui.AspectRatioFrameLayout;
import androidx.media3.ui.PlayerView; import androidx.media3.ui.PlayerView;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.progressindicator.LinearProgressIndicator; import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.base.Ticker; import com.google.common.base.Ticker;
@ -76,7 +77,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
public final class TransformerActivity extends AppCompatActivity { public final class TransformerActivity extends AppCompatActivity {
private static final String TAG = "TransformerActivity"; private static final String TAG = "TransformerActivity";
private @MonotonicNonNull PlayerView playerView; private @MonotonicNonNull MaterialCardView inputCardView;
private @MonotonicNonNull PlayerView inputPlayerView;
private @MonotonicNonNull PlayerView outputPlayerView;
private @MonotonicNonNull TextView debugTextView; private @MonotonicNonNull TextView debugTextView;
private @MonotonicNonNull TextView informationTextView; private @MonotonicNonNull TextView informationTextView;
private @MonotonicNonNull ViewGroup progressViewGroup; private @MonotonicNonNull ViewGroup progressViewGroup;
@ -85,7 +88,8 @@ public final class TransformerActivity extends AppCompatActivity {
private @MonotonicNonNull AspectRatioFrameLayout debugFrame; private @MonotonicNonNull AspectRatioFrameLayout debugFrame;
@Nullable private DebugTextViewHelper debugTextViewHelper; @Nullable private DebugTextViewHelper debugTextViewHelper;
@Nullable private ExoPlayer player; @Nullable private ExoPlayer inputPlayer;
@Nullable private ExoPlayer outputPlayer;
@Nullable private Transformer transformer; @Nullable private Transformer transformer;
@Nullable private File externalCacheFile; @Nullable private File externalCacheFile;
@ -94,7 +98,9 @@ public final class TransformerActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.transformer_activity); setContentView(R.layout.transformer_activity);
playerView = findViewById(R.id.player_view); inputCardView = findViewById(R.id.input_card_view);
inputPlayerView = findViewById(R.id.input_player_view);
outputPlayerView = findViewById(R.id.output_player_view);
debugTextView = findViewById(R.id.debug_text_view); debugTextView = findViewById(R.id.debug_text_view);
informationTextView = findViewById(R.id.information_text_view); informationTextView = findViewById(R.id.information_text_view);
progressViewGroup = findViewById(R.id.progress_view_group); progressViewGroup = findViewById(R.id.progress_view_group);
@ -104,6 +110,7 @@ public final class TransformerActivity extends AppCompatActivity {
transformationStopwatch = transformationStopwatch =
Stopwatch.createUnstarted( Stopwatch.createUnstarted(
new Ticker() { new Ticker() {
@Override
public long read() { public long read() {
return android.os.SystemClock.elapsedRealtimeNanos(); return android.os.SystemClock.elapsedRealtimeNanos();
} }
@ -117,13 +124,16 @@ public final class TransformerActivity extends AppCompatActivity {
checkNotNull(progressIndicator); checkNotNull(progressIndicator);
checkNotNull(informationTextView); checkNotNull(informationTextView);
checkNotNull(transformationStopwatch); checkNotNull(transformationStopwatch);
checkNotNull(playerView); checkNotNull(inputCardView);
checkNotNull(inputPlayerView);
checkNotNull(outputPlayerView);
checkNotNull(debugTextView); checkNotNull(debugTextView);
checkNotNull(progressViewGroup); checkNotNull(progressViewGroup);
checkNotNull(debugFrame); checkNotNull(debugFrame);
startTransformation(); startTransformation();
playerView.onResume(); inputPlayerView.onResume();
outputPlayerView.onResume();
} }
@Override @Override
@ -137,7 +147,8 @@ public final class TransformerActivity extends AppCompatActivity {
// stop watch to be stopped in a transformer callback. // stop watch to be stopped in a transformer callback.
checkNotNull(transformationStopwatch).reset(); checkNotNull(transformationStopwatch).reset();
checkNotNull(playerView).onPause(); checkNotNull(inputPlayerView).onPause();
checkNotNull(outputPlayerView).onPause();
releasePlayer(); releasePlayer();
checkNotNull(externalCacheFile).delete(); checkNotNull(externalCacheFile).delete();
@ -145,7 +156,9 @@ public final class TransformerActivity extends AppCompatActivity {
} }
@RequiresNonNull({ @RequiresNonNull({
"playerView", "inputCardView",
"inputPlayerView",
"outputPlayerView",
"debugTextView", "debugTextView",
"informationTextView", "informationTextView",
"progressIndicator", "progressIndicator",
@ -171,7 +184,8 @@ public final class TransformerActivity extends AppCompatActivity {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
informationTextView.setText(R.string.transformation_started); informationTextView.setText(R.string.transformation_started);
playerView.setVisibility(View.GONE); inputCardView.setVisibility(View.GONE);
outputPlayerView.setVisibility(View.GONE);
Handler mainHandler = new Handler(getMainLooper()); Handler mainHandler = new Handler(getMainLooper());
ProgressHolder progressHolder = new ProgressHolder(); ProgressHolder progressHolder = new ProgressHolder();
mainHandler.post( mainHandler.post(
@ -210,20 +224,10 @@ public final class TransformerActivity extends AppCompatActivity {
return mediaItemBuilder.build(); return mediaItemBuilder.build();
} }
// Create a cache file, resetting it if it already exists.
private File createExternalCacheFile(String fileName) throws IOException {
File file = new File(getExternalCacheDir(), fileName);
if (file.exists() && !file.delete()) {
throw new IllegalStateException("Could not delete the previous transformer output file");
}
if (!file.createNewFile()) {
throw new IllegalStateException("Could not create the transformer output file");
}
return file;
}
@RequiresNonNull({ @RequiresNonNull({
"playerView", "inputCardView",
"inputPlayerView",
"outputPlayerView",
"debugTextView", "debugTextView",
"informationTextView", "informationTextView",
"transformationStopwatch", "transformationStopwatch",
@ -284,7 +288,7 @@ public final class TransformerActivity extends AppCompatActivity {
@Override @Override
public void onTransformationCompleted( public void onTransformationCompleted(
MediaItem mediaItem, TransformationResult transformationResult) { MediaItem mediaItem, TransformationResult transformationResult) {
TransformerActivity.this.onTransformationCompleted(filePath); TransformerActivity.this.onTransformationCompleted(filePath, mediaItem);
} }
@Override @Override
@ -296,6 +300,18 @@ public final class TransformerActivity extends AppCompatActivity {
.build(); .build();
} }
// Create a cache file, resetting it if it already exists.
private File createExternalCacheFile(String fileName) throws IOException {
File file = new File(getExternalCacheDir(), fileName);
if (file.exists() && !file.delete()) {
throw new IllegalStateException("Could not delete the previous transformer output file");
}
if (!file.createNewFile()) {
throw new IllegalStateException("Could not create the transformer output file");
}
return file;
}
private ImmutableList<Effect> createVideoEffectsListFromBundle(Bundle bundle) { private ImmutableList<Effect> createVideoEffectsListFromBundle(Bundle bundle) {
@Nullable @Nullable
boolean[] selectedEffects = boolean[] selectedEffects =
@ -444,37 +460,55 @@ public final class TransformerActivity extends AppCompatActivity {
} }
@RequiresNonNull({ @RequiresNonNull({
"playerView", "inputCardView",
"inputPlayerView",
"outputPlayerView",
"debugTextView", "debugTextView",
"informationTextView", "informationTextView",
"progressViewGroup", "progressViewGroup",
"debugFrame", "debugFrame",
"transformationStopwatch", "transformationStopwatch",
}) })
private void onTransformationCompleted(String filePath) { private void onTransformationCompleted(String filePath, MediaItem inputMediaItem) {
transformationStopwatch.stop(); transformationStopwatch.stop();
informationTextView.setText( informationTextView.setText(
getString( getString(
R.string.transformation_completed, transformationStopwatch.elapsed(TimeUnit.SECONDS))); R.string.transformation_completed, transformationStopwatch.elapsed(TimeUnit.SECONDS)));
progressViewGroup.setVisibility(View.GONE); progressViewGroup.setVisibility(View.GONE);
debugFrame.removeAllViews(); debugFrame.removeAllViews();
playerView.setVisibility(View.VISIBLE); inputCardView.setVisibility(View.VISIBLE);
playMediaItem(MediaItem.fromUri("file://" + filePath)); outputPlayerView.setVisibility(View.VISIBLE);
playMediaItems(inputMediaItem, MediaItem.fromUri("file://" + filePath));
Log.d(TAG, "Output file path: file://" + filePath); Log.d(TAG, "Output file path: file://" + filePath);
} }
@RequiresNonNull({"playerView", "debugTextView"}) @RequiresNonNull({
private void playMediaItem(MediaItem mediaItem) { "inputCardView",
playerView.setPlayer(null); "inputPlayerView",
"outputPlayerView",
"debugTextView",
})
private void playMediaItems(MediaItem inputMediaItem, MediaItem outputMediaItem) {
inputPlayerView.setPlayer(null);
outputPlayerView.setPlayer(null);
releasePlayer(); releasePlayer();
ExoPlayer player = new ExoPlayer.Builder(/* context= */ this).build(); ExoPlayer inputPlayer = new ExoPlayer.Builder(/* context= */ this).build();
playerView.setPlayer(player); inputPlayerView.setPlayer(inputPlayer);
player.setMediaItem(mediaItem); inputPlayer.setMediaItem(inputMediaItem);
player.play(); inputPlayer.prepare();
player.prepare(); this.inputPlayer = inputPlayer;
this.player = player;
debugTextViewHelper = new DebugTextViewHelper(player, debugTextView); ExoPlayer outputPlayer = new ExoPlayer.Builder(/* context= */ this).build();
outputPlayerView.setPlayer(outputPlayer);
outputPlayer.setMediaItem(outputMediaItem);
outputPlayer.prepare();
this.outputPlayer = outputPlayer;
inputPlayer.play();
outputPlayer.play();
debugTextViewHelper = new DebugTextViewHelper(outputPlayer, debugTextView);
debugTextViewHelper.start(); debugTextViewHelper.start();
} }
@ -483,9 +517,13 @@ public final class TransformerActivity extends AppCompatActivity {
debugTextViewHelper.stop(); debugTextViewHelper.stop();
debugTextViewHelper = null; debugTextViewHelper = null;
} }
if (player != null) { if (inputPlayer != null) {
player.release(); inputPlayer.release();
player = null; inputPlayer = null;
}
if (outputPlayer != null) {
outputPlayer.release();
outputPlayer = null;
} }
} }

View File

@ -39,32 +39,87 @@
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/input_card_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_margin="16dp" android:layout_margin="16dp"
app:cardCornerRadius="4dp" app:cardCornerRadius="4dp"
app:cardElevation="2dp"> app:cardElevation="2dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.media3.ui.PlayerView <LinearLayout
android:id="@+id/player_view" android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:padding="8dp"
android:text="@string/input_video" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<androidx.media3.ui.PlayerView
android:id="@+id/input_player_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.media3.ui.AspectRatioFrameLayout
android:id="@+id/input_debug_aspect_ratio_frame_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
<TextView
android:id="@+id/debug_text_view" </com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/output_card_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="16dp"
app:cardCornerRadius="4dp"
app:cardElevation="2dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="@string/output_video" />
<TextView
android:id="@+id/debug_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textSize="10sp"
tools:ignore="SmallSp"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_gravity="center"
android:layout_height="wrap_content">
<androidx.media3.ui.PlayerView
android:id="@+id/output_player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
android:textSize="10sp"
tools:ignore="SmallSp"/>
<LinearLayout <LinearLayout
android:id="@+id/progress_view_group" android:id="@+id/progress_view_group"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_gravity="bottom"
android:padding="8dp" android:padding="8dp"
android:orientation="vertical"> android:orientation="vertical">
@ -96,5 +151,9 @@
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</LinearLayout> </LinearLayout>

View File

@ -49,14 +49,16 @@
</string-array> </string-array>
<string name="contrast_value" translatable="false">Contrast value</string> <string name="contrast_value" translatable="false">Contrast value</string>
<string name="rgb_adjustment_options" translatable="false">Scale RGB Channels individually</string> <string name="rgb_adjustment_options" translatable="false">Scale RGB Channels individually</string>
<string name="rgb_adjustment_scale_red" translatable="false">Scale Red</string> <string name="rgb_adjustment_scale_red" translatable="false">Scale red</string>
<string name="rgb_adjustment_scale_green" translatable="false">Scale Green</string> <string name="rgb_adjustment_scale_green" translatable="false">Scale green</string>
<string name="rgb_adjustment_scale_blue" translatable="false">Scale Blue</string> <string name="rgb_adjustment_scale_blue" translatable="false">Scale blue</string>
<string name="center_x">Center X</string> <string name="center_x">Center X</string>
<string name="center_y">Center Y</string> <string name="center_y">Center Y</string>
<string name="radius_range">Radius range</string> <string name="radius_range">Radius range</string>
<string name="hsl_adjustment_options" translatable="false">HSL Adjustment Options</string> <string name="hsl_adjustment_options" translatable="false">HSL adjustment options</string>
<string name="hue_adjustment">Hue Adjustment</string> <string name="hue_adjustment">Hue adjustment</string>
<string name="saturation_adjustment">Saturation Adjustment</string> <string name="saturation_adjustment">Saturation adjustment</string>
<string name="lightness_adjustment">Lightness Adjustment</string> <string name="lightness_adjustment">Lightness adjustment</string>
<string name="input_video">Input video:</string>
<string name="output_video">Output video:</string>
</resources> </resources>