diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index af000fe65b..59ffd6d6fd 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -272,8 +272,6 @@ public final class TransformerActivity extends AppCompatActivity { Transformer.Builder transformerBuilder = new Transformer.Builder(/* context= */ this); if (bundle != null) { TransformationRequest.Builder requestBuilder = new TransformationRequest.Builder(); - requestBuilder.setFlattenForSlowMotion( - bundle.getBoolean(ConfigurationActivity.SHOULD_FLATTEN_FOR_SLOW_MOTION)); @Nullable String audioMimeType = bundle.getString(ConfigurationActivity.AUDIO_MIME_TYPE); if (audioMimeType != null) { requestBuilder.setAudioMimeType(audioMimeType); @@ -352,6 +350,8 @@ public final class TransformerActivity extends AppCompatActivity { return editedMediaItemBuilder .setRemoveAudio(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_AUDIO)) .setRemoveVideo(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_VIDEO)) + .setFlattenForSlowMotion( + bundle.getBoolean(ConfigurationActivity.SHOULD_FLATTEN_FOR_SLOW_MOTION)) .setEffects(new Effects(audioProcessors, videoEffects)) .build(); } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java index 3274db3162..4120675092 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java @@ -35,7 +35,6 @@ import com.google.android.exoplayer2.transformer.AndroidTestUtil.ForceEncodeEnco import com.google.android.exoplayer2.transformer.DefaultEncoderFactory; import com.google.android.exoplayer2.transformer.EditedMediaItem; import com.google.android.exoplayer2.transformer.Effects; -import com.google.android.exoplayer2.transformer.TransformationRequest; import com.google.android.exoplayer2.transformer.Transformer; import com.google.android.exoplayer2.transformer.TransformerAndroidTestRunner; import com.google.android.exoplayer2.transformer.VideoEncoderSettings; @@ -203,13 +202,11 @@ public class TransformationTest { return; } - Transformer transformer = - new Transformer.Builder(context) - .setTransformationRequest( - new TransformationRequest.Builder().setFlattenForSlowMotion(true).build()) - .build(); + Transformer transformer = new Transformer.Builder(context).build(); EditedMediaItem editedMediaItem = - new EditedMediaItem.Builder(MediaItem.fromUri(Uri.parse(MP4_ASSET_SEF_URI_STRING))).build(); + new EditedMediaItem.Builder(MediaItem.fromUri(Uri.parse(MP4_ASSET_SEF_URI_STRING))) + .setFlattenForSlowMotion(true) + .build(); new TransformerAndroidTestRunner.Builder(context, transformer) .build() .run(testId, editedMediaItem); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java index d1b6893c0e..a6c1d44efa 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AssetLoader.java @@ -74,7 +74,7 @@ public interface AssetLoader { * this is done on decoded samples. * *
For more information on slow motion flattening, see {@link
- * TransformationRequest.Builder#setFlattenForSlowMotion(boolean)}.
+ * EditedMediaItem.Builder#setFlattenForSlowMotion(boolean)}.
*/
@CanIgnoreReturnValue
Factory setFlattenVideoForSlowMotion(boolean flattenVideoForSlowMotion);
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java
index 338e088d06..64f0cda487 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java
@@ -63,6 +63,7 @@ import org.checkerframework.dataflow.qual.Pure;
long streamStartPositionUs,
long streamOffsetUs,
TransformationRequest transformationRequest,
+ boolean flattenForSlowMotion,
ImmutableList The default value is {@code false}.
+ *
+ * The flattened output is obtained by removing the slow motion metadata and by actually
+ * slowing down the parts of the video and audio streams defined in this metadata.
+ *
+ * Only Samsung Extension Format (SEF) slow motion metadata type is supported. Flattening has
+ * no effect if the input does not contain this metadata type.
+ *
+ * For SEF slow motion media, the following assumptions are made on the input:
+ *
+ * If using an {@link ExoPlayerAssetLoader.Factory} with a provided {@link
+ * MediaSource.Factory}, make sure that {@link Mp4Extractor#FLAG_READ_SEF_DATA} is set on the
+ * {@link Mp4Extractor} used. Otherwise, the slow motion metadata will be ignored and the input
+ * won't be flattened.
+ *
+ * Using slow motion flattening together with {@link MediaItem.ClippingConfiguration} is not
+ * supported yet.
+ *
+ * @param flattenForSlowMotion Whether to flatten for slow motion.
+ * @return This builder.
+ */
+ @CanIgnoreReturnValue
+ public Builder setFlattenForSlowMotion(boolean flattenForSlowMotion) {
+ // TODO(b/233986762): Support clipping with SEF flattening.
+ checkArgument(
+ mediaItem.clippingConfiguration.equals(MediaItem.ClippingConfiguration.UNSET)
+ || !flattenForSlowMotion,
+ "Slow motion flattening is not supported when clipping is requested");
+ this.flattenForSlowMotion = flattenForSlowMotion;
+ return this;
+ }
+
/**
* Sets the {@link Effects} to apply to the {@link MediaItem}.
*
@@ -98,21 +143,28 @@ public class EditedMediaItem {
new Effects(
/* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of());
}
- return new EditedMediaItem(mediaItem, removeAudio, removeVideo, effects);
+ return new EditedMediaItem(
+ mediaItem, removeAudio, removeVideo, flattenForSlowMotion, effects);
}
}
/* package */ final MediaItem mediaItem;
/* package */ final boolean removeAudio;
/* package */ final boolean removeVideo;
+ /* package */ final boolean flattenForSlowMotion;
/* package */ final Effects effects;
private EditedMediaItem(
- MediaItem mediaItem, boolean removeAudio, boolean removeVideo, Effects effects) {
+ MediaItem mediaItem,
+ boolean removeAudio,
+ boolean removeVideo,
+ boolean flattenForSlowMotion,
+ Effects effects) {
checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed");
this.mediaItem = mediaItem;
this.removeAudio = removeAudio;
this.removeVideo = removeVideo;
+ this.flattenForSlowMotion = flattenForSlowMotion;
this.effects = effects;
}
}
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java
index 1a5b2ed62d..12a458bde3 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Effects.java
@@ -47,8 +47,7 @@ public final class Effects {
* They are applied in the order of the list, and buffers will only be modified by that {@link
* AudioProcessor} if it {@link AudioProcessor#isActive()} based on the current configuration.
* @param videoEffects The list of {@link Effect} instances to apply to each video frame. They are
- * applied in the order of the list, after {@linkplain
- * TransformationRequest.Builder#setFlattenForSlowMotion(boolean) slow-motion flattening}.
+ * applied in the order of the list.
* @param frameProcessorFactory The {@link FrameProcessor.Factory} for the {@link FrameProcessor}
* to use when applying the {@code videoEffects} to the video frames.
*/
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java
index db1883cba0..96c0c96edd 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java
@@ -44,7 +44,10 @@ import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
+import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
+import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
import com.google.android.exoplayer2.metadata.MetadataOutput;
+import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
@@ -60,34 +63,50 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
public static final class Factory implements AssetLoader.Factory {
private final Context context;
- private final MediaSource.Factory mediaSourceFactory;
private final Codec.DecoderFactory decoderFactory;
private final Clock clock;
+ @Nullable private final MediaSource.Factory mediaSourceFactory;
private boolean removeAudio;
private boolean removeVideo;
private boolean flattenVideoForSlowMotion;
/**
- * Creates an instance.
+ * Creates an instance using a {@link DefaultMediaSourceFactory}.
*
* @param context The {@link Context}.
- * @param mediaSourceFactory The {@link MediaSource.Factory} to use to retrieve the samples to
- * transform.
* @param decoderFactory The {@link Codec.DecoderFactory} to use to decode the samples (if
* necessary).
* @param clock The {@link Clock} to use. It should always be {@link Clock#DEFAULT}, except for
* testing.
*/
- public Factory(
- Context context,
- MediaSource.Factory mediaSourceFactory,
- Codec.DecoderFactory decoderFactory,
- Clock clock) {
+ public Factory(Context context, Codec.DecoderFactory decoderFactory, Clock clock) {
this.context = context;
- this.mediaSourceFactory = mediaSourceFactory;
this.decoderFactory = decoderFactory;
this.clock = clock;
+ this.mediaSourceFactory = null;
+ }
+
+ /**
+ * Creates an instance.
+ *
+ * @param context The {@link Context}.
+ * @param decoderFactory The {@link Codec.DecoderFactory} to use to decode the samples (if
+ * necessary).
+ * @param clock The {@link Clock} to use. It should always be {@link Clock#DEFAULT}, except for
+ * testing.
+ * @param mediaSourceFactory The {@link MediaSource.Factory} to use to retrieve the samples to
+ * transform.
+ */
+ public Factory(
+ Context context,
+ Codec.DecoderFactory decoderFactory,
+ Clock clock,
+ MediaSource.Factory mediaSourceFactory) {
+ this.context = context;
+ this.decoderFactory = decoderFactory;
+ this.clock = clock;
+ this.mediaSourceFactory = mediaSourceFactory;
}
@Override
@@ -113,6 +132,14 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
@Override
public AssetLoader createAssetLoader(MediaItem mediaItem, Looper looper, Listener listener) {
+ MediaSource.Factory mediaSourceFactory = this.mediaSourceFactory;
+ if (mediaSourceFactory == null) {
+ DefaultExtractorsFactory defaultExtractorsFactory = new DefaultExtractorsFactory();
+ if (flattenVideoForSlowMotion) {
+ defaultExtractorsFactory.setMp4ExtractorFlags(Mp4Extractor.FLAG_READ_SEF_DATA);
+ }
+ mediaSourceFactory = new DefaultMediaSourceFactory(context, defaultExtractorsFactory);
+ }
return new ExoPlayerAssetLoader(
context,
mediaItem,
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java
index 9326df295e..aecf3ac3e0 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationRequest.java
@@ -23,8 +23,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
-import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
@@ -108,7 +106,6 @@ public final class TransformationRequest {
/** A builder for {@link TransformationRequest} instances. */
public static final class Builder {
- private boolean flattenForSlowMotion;
private int outputHeight;
@Nullable private String audioMimeType;
@Nullable private String videoMimeType;
@@ -125,48 +122,12 @@ public final class TransformationRequest {
}
private Builder(TransformationRequest transformationRequest) {
- this.flattenForSlowMotion = transformationRequest.flattenForSlowMotion;
this.outputHeight = transformationRequest.outputHeight;
this.audioMimeType = transformationRequest.audioMimeType;
this.videoMimeType = transformationRequest.videoMimeType;
this.hdrMode = transformationRequest.hdrMode;
}
- /**
- * Sets whether the input should be flattened for media containing slow motion markers.
- *
- * The transformed output is obtained by removing the slow motion metadata and by actually
- * slowing down the parts of the video and audio streams defined in this metadata. The default
- * value for {@code flattenForSlowMotion} is {@code false}.
- *
- * Only Samsung Extension Format (SEF) slow motion metadata type is supported. The
- * transformation has no effect if the input does not contain this metadata type.
- *
- * For SEF slow motion media, the following assumptions are made on the input:
- *
- * If using an {@link ExoPlayerAssetLoader.Factory} with a provided {@link
- * MediaSource.Factory}, make sure that {@link Mp4Extractor#FLAG_READ_SEF_DATA} is set on the
- * {@link Mp4Extractor} used. Otherwise, the slow motion metadata will be ignored and the input
- * won't be flattened.
- *
- * Using slow motion flattening together with {@link
- * com.google.android.exoplayer2.MediaItem.ClippingConfiguration} is not supported yet.
- *
- * @param flattenForSlowMotion Whether to flatten for slow motion.
- * @return This builder.
- */
- @CanIgnoreReturnValue
- public Builder setFlattenForSlowMotion(boolean flattenForSlowMotion) {
- this.flattenForSlowMotion = flattenForSlowMotion;
- return this;
- }
-
/**
* Sets the output resolution using the output height of the displayed video.
*
@@ -288,17 +249,10 @@ public final class TransformationRequest {
/** Builds a {@link TransformationRequest} instance. */
public TransformationRequest build() {
- return new TransformationRequest(
- flattenForSlowMotion, outputHeight, audioMimeType, videoMimeType, hdrMode);
+ return new TransformationRequest(outputHeight, audioMimeType, videoMimeType, hdrMode);
}
}
- /**
- * Whether the input should be flattened for media containing slow motion markers.
- *
- * @see Builder#setFlattenForSlowMotion(boolean)
- */
- public final boolean flattenForSlowMotion;
/**
* The requested height of the output video, or {@link C#LENGTH_UNSET} if inferred from the input.
*
@@ -327,13 +281,10 @@ public final class TransformationRequest {
public final @HdrMode int hdrMode;
private TransformationRequest(
- boolean flattenForSlowMotion,
int outputHeight,
@Nullable String audioMimeType,
@Nullable String videoMimeType,
@HdrMode int hdrMode) {
-
- this.flattenForSlowMotion = flattenForSlowMotion;
this.outputHeight = outputHeight;
this.audioMimeType = audioMimeType;
this.videoMimeType = videoMimeType;
@@ -349,8 +300,7 @@ public final class TransformationRequest {
return false;
}
TransformationRequest that = (TransformationRequest) o;
- return flattenForSlowMotion == that.flattenForSlowMotion
- && outputHeight == that.outputHeight
+ return outputHeight == that.outputHeight
&& Util.areEqual(audioMimeType, that.audioMimeType)
&& Util.areEqual(videoMimeType, that.videoMimeType)
&& hdrMode == that.hdrMode;
@@ -358,8 +308,7 @@ public final class TransformationRequest {
@Override
public int hashCode() {
- int result = (flattenForSlowMotion ? 1 : 0);
- result = 31 * result + outputHeight;
+ int result = outputHeight;
result = 31 * result + (audioMimeType != null ? audioMimeType.hashCode() : 0);
result = 31 * result + (videoMimeType != null ? videoMimeType.hashCode() : 0);
result = 31 * result + hdrMode;
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java
index 91dafe7a34..913eb63223 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java
@@ -32,10 +32,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.audio.AudioProcessor;
import com.google.android.exoplayer2.audio.SonicAudioProcessor;
import com.google.android.exoplayer2.effect.GlEffectsFrameProcessor;
-import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
-import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
-import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.DebugViewProvider;
import com.google.android.exoplayer2.util.Effect;
@@ -51,6 +48,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A transformer to transform media inputs.
@@ -84,9 +82,10 @@ public final class Transformer {
private ImmutableList
+ *
+ *
+ *
- *
- *
- *