mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add second player for input video
PiperOrigin-RevId: 478510687 (cherry picked from commit 48a7f6a9240cd7c0ce8016915de630d903e5c393)
This commit is contained in:
parent
186f516b65
commit
c8917b50e6
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user