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:
kimvde 2023-01-18 16:53:05 +00:00 committed by christosts
parent d4db33a535
commit aa72b45cdf
2 changed files with 62 additions and 65 deletions

View File

@ -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,

View File

@ -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.