Make startTransformation methods take an EditedMediaItem
Usages of the deprecated methods in Transformer.Builder will be removed in a follow-up CL. PiperOrigin-RevId: 502889423
This commit is contained in:
parent
d4db33a535
commit
aa72b45cdf
@ -40,9 +40,7 @@ import androidx.media3.common.util.HandlerWrapper;
|
||||
import androidx.media3.common.util.ListenerSet;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.effect.GlEffect;
|
||||
import androidx.media3.effect.GlEffectsFrameProcessor;
|
||||
import androidx.media3.effect.GlMatrixTransformation;
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.extractor.DefaultExtractorsFactory;
|
||||
@ -153,34 +151,24 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AudioProcessor} instances to apply to audio buffers.
|
||||
*
|
||||
* <p>The {@link AudioProcessor} instances 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.
|
||||
* @deprecated Set the {@linkplain AudioProcessor audio processors} in an {@link
|
||||
* EditedMediaItem}, and pass it to {@link #startTransformation(EditedMediaItem, String)} or
|
||||
* {@link #startTransformation(EditedMediaItem, ParcelFileDescriptor)} instead.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
@Deprecated
|
||||
public Builder setAudioProcessors(List<AudioProcessor> audioProcessors) {
|
||||
this.audioProcessors = ImmutableList.copyOf(audioProcessors);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Effect} instances to apply to each video frame.
|
||||
*
|
||||
* <p>The {@link Effect} instances are applied before any {@linkplain
|
||||
* TransformationRequest.Builder#setResolution(int) resolution} change specified in the {@link
|
||||
* #setTransformationRequest(TransformationRequest) TransformationRequest} but after {@linkplain
|
||||
* TransformationRequest.Builder#setFlattenForSlowMotion(boolean) slow-motion flattening}.
|
||||
*
|
||||
* <p>The default {@link FrameProcessor} only supports {@link GlEffect} instances. To use other
|
||||
* effects, call {@link #setFrameProcessorFactory(FrameProcessor.Factory)} with a custom {@link
|
||||
* FrameProcessor.Factory}.
|
||||
*
|
||||
* @param effects The {@link Effect} instances to apply to each video frame.
|
||||
* @return This builder.
|
||||
* @deprecated Set the {@linkplain Effect video effects} in an {@link EditedMediaItem}, and pass
|
||||
* it to {@link #startTransformation(EditedMediaItem, String)} or {@link
|
||||
* #startTransformation(EditedMediaItem, ParcelFileDescriptor)} instead.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
@Deprecated
|
||||
public Builder setVideoEffects(List<Effect> effects) {
|
||||
this.videoEffects = ImmutableList.copyOf(effects);
|
||||
return this;
|
||||
@ -301,20 +289,12 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link FrameProcessor.Factory} for the {@link FrameProcessor} to use when applying
|
||||
* {@linkplain Effect effects} to the video frames.
|
||||
*
|
||||
* <p>This factory will be used to create the {@link FrameProcessor} used for applying the
|
||||
* {@link Effect} instances passed to {@link #setVideoEffects(List)} and any additional {@link
|
||||
* GlMatrixTransformation} instances derived from the {@link TransformationRequest} set using
|
||||
* {@link #setTransformationRequest(TransformationRequest)}.
|
||||
*
|
||||
* <p>The default is {@link GlEffectsFrameProcessor.Factory}.
|
||||
*
|
||||
* @param frameProcessorFactory The {@link FrameProcessor.Factory} to use.
|
||||
* @return This builder.
|
||||
* @deprecated Set the {@link FrameProcessor.Factory} in an {@link EditedMediaItem}, and pass it
|
||||
* to {@link #startTransformation(EditedMediaItem, String)} or {@link
|
||||
* #startTransformation(EditedMediaItem, ParcelFileDescriptor)} instead.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
@Deprecated
|
||||
public Builder setFrameProcessorFactory(FrameProcessor.Factory frameProcessorFactory) {
|
||||
this.frameProcessorFactory = frameProcessorFactory;
|
||||
return this;
|
||||
@ -412,11 +392,13 @@ public final class Transformer {
|
||||
* <li>Duration will match duration of the input media.
|
||||
* <li>Sample mime type will match {@link TransformationRequest#audioMimeType}, or {@link
|
||||
* MimeTypes#AUDIO_AAC} if {@code null}.
|
||||
* <li>Sample rate will be {@code 44100} hz. This can be modified by passing a {@link
|
||||
* SonicAudioProcessor} to {@link #setAudioProcessors(List)}, using {@link
|
||||
* SonicAudioProcessor#setOutputSampleRateHz(int)}.
|
||||
* <li>Sample rate will be {@code 44100} hz. This can be modified by creating a {@link
|
||||
* SonicAudioProcessor}, setting its {@linkplain
|
||||
* SonicAudioProcessor#setOutputSampleRateHz(int) sample rate}, and passing it to the
|
||||
* {@link EditedMediaItem} used to start the transformation.
|
||||
* <li>Channel count will be {@code 2}. This can be modified by implementing a custom {@link
|
||||
* AudioProcessor} and passing it to {@link #setAudioProcessors(List)}.
|
||||
* AudioProcessor} and passing it to the {@link EditedMediaItem} used to start the
|
||||
* transformation.
|
||||
* </ul>
|
||||
*
|
||||
* @param generateSilentAudio Whether to generate silent audio for the output file if there is
|
||||
@ -690,15 +672,16 @@ public final class Transformer {
|
||||
* ignored. For adaptive bitrate, if no custom {@link AssetLoader.Factory} is specified, the
|
||||
* highest bitrate video and audio streams are selected.
|
||||
*
|
||||
* @param mediaItem The {@link MediaItem} to transform.
|
||||
* @param editedMediaItem The {@link MediaItem} to transform, with the transformations to apply to
|
||||
* it.
|
||||
* @param path The path to the output file.
|
||||
* @throws IllegalArgumentException If the path is invalid.
|
||||
* @throws IllegalArgumentException If the {@link MediaItem} is not supported.
|
||||
* @throws IllegalStateException If this method is called from the wrong thread.
|
||||
* @throws IllegalStateException If a transformation is already in progress.
|
||||
*/
|
||||
public void startTransformation(MediaItem mediaItem, String path) {
|
||||
startTransformationInternal(mediaItem, path, /* parcelFileDescriptor= */ null);
|
||||
public void startTransformation(EditedMediaItem editedMediaItem, String path) {
|
||||
startTransformationInternal(editedMediaItem, path, /* parcelFileDescriptor= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -715,7 +698,8 @@ public final class Transformer {
|
||||
* ignored. For adaptive bitrate, if no custom {@link AssetLoader.Factory} is specified, the
|
||||
* highest bitrate video and audio streams are selected.
|
||||
*
|
||||
* @param mediaItem The {@link MediaItem} to transform.
|
||||
* @param editedMediaItem The {@link MediaItem} to transform, with the transformations to apply to
|
||||
* it.
|
||||
* @param parcelFileDescriptor A readable and writable {@link ParcelFileDescriptor} of the output.
|
||||
* The file referenced by this ParcelFileDescriptor should not be used before the
|
||||
* transformation is completed. It is the responsibility of the caller to close the
|
||||
@ -726,14 +710,39 @@ public final class Transformer {
|
||||
* @throws IllegalStateException If a transformation is already in progress.
|
||||
*/
|
||||
@RequiresApi(26)
|
||||
public void startTransformation(
|
||||
EditedMediaItem editedMediaItem, ParcelFileDescriptor parcelFileDescriptor) {
|
||||
startTransformationInternal(editedMediaItem, /* path= */ null, parcelFileDescriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #startTransformation(EditedMediaItem, String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void startTransformation(MediaItem mediaItem, String path) {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem(
|
||||
mediaItem, new Effects(audioProcessors, videoEffects, frameProcessorFactory));
|
||||
startTransformationInternal(editedMediaItem, path, /* parcelFileDescriptor= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #startTransformation(EditedMediaItem, ParcelFileDescriptor)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@RequiresApi(26)
|
||||
public void startTransformation(MediaItem mediaItem, ParcelFileDescriptor parcelFileDescriptor) {
|
||||
startTransformationInternal(mediaItem, /* path= */ null, parcelFileDescriptor);
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem(
|
||||
mediaItem, new Effects(audioProcessors, videoEffects, frameProcessorFactory));
|
||||
startTransformationInternal(editedMediaItem, /* path= */ null, parcelFileDescriptor);
|
||||
}
|
||||
|
||||
private void startTransformationInternal(
|
||||
MediaItem mediaItem,
|
||||
EditedMediaItem editedMediaItem,
|
||||
@Nullable String path,
|
||||
@Nullable ParcelFileDescriptor parcelFileDescriptor) {
|
||||
MediaItem mediaItem = editedMediaItem.mediaItem;
|
||||
if (!mediaItem.clippingConfiguration.equals(MediaItem.ClippingConfiguration.UNSET)
|
||||
&& transformationRequest.flattenForSlowMotion) {
|
||||
// TODO(b/233986762): Support clipping with SEF flattening.
|
||||
@ -752,17 +761,14 @@ public final class Transformer {
|
||||
transformerInternal =
|
||||
new TransformerInternal(
|
||||
context,
|
||||
mediaItem,
|
||||
editedMediaItem,
|
||||
path,
|
||||
parcelFileDescriptor,
|
||||
transformationRequest,
|
||||
audioProcessors,
|
||||
videoEffects,
|
||||
removeAudio,
|
||||
removeVideo,
|
||||
generateSilentAudio,
|
||||
assetLoaderFactory,
|
||||
frameProcessorFactory,
|
||||
encoderFactory,
|
||||
muxerFactory,
|
||||
transformerInternalListener,
|
||||
|
@ -35,11 +35,9 @@ import androidx.media3.common.C;
|
||||
import androidx.media3.common.DebugViewProvider;
|
||||
import androidx.media3.common.Effect;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.FrameProcessor;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Metadata;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.audio.AudioProcessor;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.ConditionVariable;
|
||||
import androidx.media3.common.util.HandlerWrapper;
|
||||
@ -47,7 +45,6 @@ import androidx.media3.common.util.Size;
|
||||
import androidx.media3.effect.Presentation;
|
||||
import androidx.media3.effect.ScaleToFitTransformation;
|
||||
import androidx.media3.extractor.metadata.mp4.SlowMotionData;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -94,9 +91,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
private final Context context;
|
||||
private final TransformationRequest transformationRequest;
|
||||
private final ImmutableList<AudioProcessor> audioProcessors;
|
||||
private final ImmutableList<Effect> videoEffects;
|
||||
private final FrameProcessor.Factory frameProcessorFactory;
|
||||
private final CapturingEncoderFactory encoderFactory;
|
||||
private final Listener listener;
|
||||
private final HandlerWrapper applicationHandler;
|
||||
@ -105,6 +99,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
private final HandlerThread internalHandlerThread;
|
||||
private final HandlerWrapper internalHandler;
|
||||
private final AssetLoader assetLoader;
|
||||
private final Effects effects;
|
||||
private final List<SamplePipeline> samplePipelines;
|
||||
private final MuxerWrapper muxerWrapper;
|
||||
private final ConditionVariable transformerConditionVariable;
|
||||
@ -119,17 +114,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
public TransformerInternal(
|
||||
Context context,
|
||||
MediaItem mediaItem,
|
||||
EditedMediaItem editedMediaItem,
|
||||
@Nullable String outputPath,
|
||||
@Nullable ParcelFileDescriptor outputParcelFileDescriptor,
|
||||
TransformationRequest transformationRequest,
|
||||
ImmutableList<AudioProcessor> audioProcessors,
|
||||
ImmutableList<Effect> videoEffects,
|
||||
boolean removeAudio,
|
||||
boolean removeVideo,
|
||||
boolean generateSilentAudio,
|
||||
AssetLoader.Factory assetLoaderFactory,
|
||||
FrameProcessor.Factory frameProcessorFactory,
|
||||
Codec.EncoderFactory encoderFactory,
|
||||
Muxer.Factory muxerFactory,
|
||||
Listener listener,
|
||||
@ -139,10 +131,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
Clock clock) {
|
||||
this.context = context;
|
||||
this.transformationRequest = transformationRequest;
|
||||
this.audioProcessors = audioProcessors;
|
||||
this.videoEffects = videoEffects;
|
||||
this.generateSilentAudio = generateSilentAudio;
|
||||
this.frameProcessorFactory = frameProcessorFactory;
|
||||
this.encoderFactory = new CapturingEncoderFactory(encoderFactory);
|
||||
this.listener = listener;
|
||||
this.applicationHandler = applicationHandler;
|
||||
@ -151,6 +140,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
internalHandlerThread = new HandlerThread("Transformer:Internal");
|
||||
internalHandlerThread.start();
|
||||
Looper internalLooper = internalHandlerThread.getLooper();
|
||||
MediaItem mediaItem = editedMediaItem.mediaItem;
|
||||
ComponentListener componentListener = new ComponentListener(mediaItem, fallbackListener);
|
||||
assetLoader =
|
||||
assetLoaderFactory
|
||||
@ -158,6 +148,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
.setRemoveVideo(removeVideo)
|
||||
.setFlattenVideoForSlowMotion(transformationRequest.flattenForSlowMotion)
|
||||
.createAssetLoader(mediaItem, internalLooper, componentListener);
|
||||
effects = editedMediaItem.effects;
|
||||
samplePipelines = new ArrayList<>();
|
||||
muxerWrapper =
|
||||
new MuxerWrapper(outputPath, outputParcelFileDescriptor, muxerFactory, componentListener);
|
||||
@ -490,7 +481,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
streamStartPositionUs,
|
||||
streamOffsetUs,
|
||||
transformationRequest,
|
||||
audioProcessors,
|
||||
effects.audioProcessors,
|
||||
generateSilentAudio ? durationUs : C.TIME_UNSET,
|
||||
encoderFactory,
|
||||
muxerWrapper,
|
||||
@ -502,8 +493,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
streamStartPositionUs,
|
||||
streamOffsetUs,
|
||||
transformationRequest,
|
||||
videoEffects,
|
||||
frameProcessorFactory,
|
||||
effects.videoEffects,
|
||||
effects.frameProcessorFactory,
|
||||
encoderFactory,
|
||||
muxerWrapper,
|
||||
/* errorConsumer= */ this::onTransformationError,
|
||||
@ -534,7 +525,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
if (transformationRequest.flattenForSlowMotion && isSlowMotion(inputFormat)) {
|
||||
return true;
|
||||
}
|
||||
if (!audioProcessors.isEmpty()) {
|
||||
if (!effects.audioProcessors.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (generateSilentAudio) {
|
||||
@ -582,8 +573,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
// TODO(b/265927935): consider generalizing this logic.
|
||||
for (int i = 0; i < videoEffects.size(); i++) {
|
||||
Effect videoEffect = videoEffects.get(i);
|
||||
for (int i = 0; i < effects.videoEffects.size(); i++) {
|
||||
Effect videoEffect = effects.videoEffects.get(i);
|
||||
if (videoEffect instanceof Presentation) {
|
||||
Presentation presentation = (Presentation) videoEffect;
|
||||
// The decoder rotates encoded frames for display by inputFormat.rotationDegrees.
|
||||
|
Loading…
x
Reference in New Issue
Block a user