Commit 7b254727 by samrobinson Committed by microkatz

Utilize AudioProcessingPipeline in Transformer.

Provides an API for applications to set AudioProcessors for use
in Transformer.

PiperOrigin-RevId: 488621242
parent 7a7d0834
...@@ -26,7 +26,6 @@ import androidx.media3.common.Format; ...@@ -26,7 +26,6 @@ import androidx.media3.common.Format;
import androidx.media3.common.FrameProcessingException; import androidx.media3.common.FrameProcessingException;
import androidx.media3.common.FrameProcessor; import androidx.media3.common.FrameProcessor;
import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackException;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.audio.AudioProcessor.AudioFormat; import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
...@@ -73,6 +72,7 @@ public final class TransformationException extends Exception { ...@@ -73,6 +72,7 @@ public final class TransformationException extends Exception {
ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED, ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED,
ERROR_CODE_HDR_ENCODING_UNSUPPORTED, ERROR_CODE_HDR_ENCODING_UNSUPPORTED,
ERROR_CODE_FRAME_PROCESSING_FAILED, ERROR_CODE_FRAME_PROCESSING_FAILED,
ERROR_CODE_AUDIO_PROCESSING_FAILED,
ERROR_CODE_MUXING_FAILED, ERROR_CODE_MUXING_FAILED,
}) })
public @interface ErrorCode {} public @interface ErrorCode {}
...@@ -163,9 +163,15 @@ public final class TransformationException extends Exception { ...@@ -163,9 +163,15 @@ public final class TransformationException extends Exception {
/** Caused by a frame processing failure. */ /** Caused by a frame processing failure. */
public static final int ERROR_CODE_FRAME_PROCESSING_FAILED = 5001; public static final int ERROR_CODE_FRAME_PROCESSING_FAILED = 5001;
// Muxing errors (6xxx). // Audio processing errors (6xxx).
/** Caused by an audio processing failure. */
public static final int ERROR_CODE_AUDIO_PROCESSING_FAILED = 6001;
// Muxing errors (7xxx).
/** Caused by a failure while muxing media samples. */ /** Caused by a failure while muxing media samples. */
public static final int ERROR_CODE_MUXING_FAILED = 6001; public static final int ERROR_CODE_MUXING_FAILED = 7001;
private static final ImmutableBiMap<String, @ErrorCode Integer> NAME_TO_ERROR_CODE = private static final ImmutableBiMap<String, @ErrorCode Integer> NAME_TO_ERROR_CODE =
new ImmutableBiMap.Builder<String, @ErrorCode Integer>() new ImmutableBiMap.Builder<String, @ErrorCode Integer>()
...@@ -188,6 +194,7 @@ public final class TransformationException extends Exception { ...@@ -188,6 +194,7 @@ public final class TransformationException extends Exception {
.put("ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED", ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED) .put("ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED", ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED)
.put("ERROR_CODE_HDR_ENCODING_UNSUPPORTED", ERROR_CODE_HDR_ENCODING_UNSUPPORTED) .put("ERROR_CODE_HDR_ENCODING_UNSUPPORTED", ERROR_CODE_HDR_ENCODING_UNSUPPORTED)
.put("ERROR_CODE_FRAME_PROCESSING_FAILED", ERROR_CODE_FRAME_PROCESSING_FAILED) .put("ERROR_CODE_FRAME_PROCESSING_FAILED", ERROR_CODE_FRAME_PROCESSING_FAILED)
.put("ERROR_CODE_AUDIO_PROCESSING_FAILED", ERROR_CODE_AUDIO_PROCESSING_FAILED)
.put("ERROR_CODE_MUXING_FAILED", ERROR_CODE_MUXING_FAILED) .put("ERROR_CODE_MUXING_FAILED", ERROR_CODE_MUXING_FAILED)
.buildOrThrow(); .buildOrThrow();
...@@ -264,18 +271,18 @@ public final class TransformationException extends Exception { ...@@ -264,18 +271,18 @@ public final class TransformationException extends Exception {
} }
/** /**
* Creates an instance for an {@link AudioProcessor} related exception. * Creates an instance for an audio processing related exception.
* *
* @param cause The cause of the failure. * @param cause The cause of the failure.
* @param componentName The name of the {@link AudioProcessor} used.
* @param audioFormat The {@link AudioFormat} used. * @param audioFormat The {@link AudioFormat} used.
* @param errorCode See {@link #errorCode}.
* @return The created instance. * @return The created instance.
*/ */
public static TransformationException createForAudioProcessor( public static TransformationException createForAudioProcessing(
Throwable cause, String componentName, AudioFormat audioFormat, int errorCode) { Throwable cause, AudioFormat audioFormat) {
return new TransformationException( return new TransformationException(
componentName + " error, audio_format = " + audioFormat, cause, errorCode); "Audio processing error, audio_format = " + audioFormat,
cause,
ERROR_CODE_AUDIO_PROCESSING_FAILED);
} }
/** /**
......
...@@ -35,6 +35,7 @@ import androidx.media3.common.FrameProcessor; ...@@ -35,6 +35,7 @@ import androidx.media3.common.FrameProcessor;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaLibraryInfo; import androidx.media3.common.MediaLibraryInfo;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.ListenerSet; import androidx.media3.common.util.ListenerSet;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
...@@ -85,6 +86,7 @@ public final class Transformer { ...@@ -85,6 +86,7 @@ public final class Transformer {
// Optional fields. // Optional fields.
private TransformationRequest transformationRequest; private TransformationRequest transformationRequest;
private ImmutableList<AudioProcessor> audioProcessors;
private ImmutableList<Effect> videoEffects; private ImmutableList<Effect> videoEffects;
private boolean removeAudio; private boolean removeAudio;
private boolean removeVideo; private boolean removeVideo;
...@@ -106,6 +108,7 @@ public final class Transformer { ...@@ -106,6 +108,7 @@ public final class Transformer {
public Builder(Context context) { public Builder(Context context) {
this.context = context.getApplicationContext(); this.context = context.getApplicationContext();
transformationRequest = new TransformationRequest.Builder().build(); transformationRequest = new TransformationRequest.Builder().build();
audioProcessors = ImmutableList.of();
videoEffects = ImmutableList.of(); videoEffects = ImmutableList.of();
decoderFactory = new DefaultDecoderFactory(this.context); decoderFactory = new DefaultDecoderFactory(this.context);
encoderFactory = new DefaultEncoderFactory.Builder(this.context).build(); encoderFactory = new DefaultEncoderFactory.Builder(this.context).build();
...@@ -121,6 +124,7 @@ public final class Transformer { ...@@ -121,6 +124,7 @@ public final class Transformer {
private Builder(Transformer transformer) { private Builder(Transformer transformer) {
this.context = transformer.context; this.context = transformer.context;
this.transformationRequest = transformer.transformationRequest; this.transformationRequest = transformer.transformationRequest;
this.audioProcessors = transformer.audioProcessors;
this.videoEffects = transformer.videoEffects; this.videoEffects = transformer.videoEffects;
this.removeAudio = transformer.removeAudio; this.removeAudio = transformer.removeAudio;
this.removeVideo = transformer.removeVideo; this.removeVideo = transformer.removeVideo;
...@@ -152,6 +156,19 @@ public final class Transformer { ...@@ -152,6 +156,19 @@ 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.
*/
@CanIgnoreReturnValue
public Builder setAudioProcessors(List<AudioProcessor> audioProcessors) {
this.audioProcessors = ImmutableList.copyOf(audioProcessors);
return this;
}
/**
* Sets the {@link Effect} instances to apply to each video frame. * Sets the {@link Effect} instances to apply to each video frame.
* *
* <p>The {@link Effect} instances are applied before any {@linkplain * <p>The {@link Effect} instances are applied before any {@linkplain
...@@ -426,6 +443,7 @@ public final class Transformer { ...@@ -426,6 +443,7 @@ public final class Transformer {
return new Transformer( return new Transformer(
context, context,
transformationRequest, transformationRequest,
audioProcessors,
videoEffects, videoEffects,
removeAudio, removeAudio,
removeVideo, removeVideo,
...@@ -537,6 +555,7 @@ public final class Transformer { ...@@ -537,6 +555,7 @@ public final class Transformer {
private final Context context; private final Context context;
private final TransformationRequest transformationRequest; private final TransformationRequest transformationRequest;
private final ImmutableList<AudioProcessor> audioProcessors;
private final ImmutableList<Effect> videoEffects; private final ImmutableList<Effect> videoEffects;
private final boolean removeAudio; private final boolean removeAudio;
private final boolean removeVideo; private final boolean removeVideo;
...@@ -558,6 +577,7 @@ public final class Transformer { ...@@ -558,6 +577,7 @@ public final class Transformer {
private Transformer( private Transformer(
Context context, Context context,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
ImmutableList<AudioProcessor> audioProcessors,
ImmutableList<Effect> videoEffects, ImmutableList<Effect> videoEffects,
boolean removeAudio, boolean removeAudio,
boolean removeVideo, boolean removeVideo,
...@@ -573,6 +593,7 @@ public final class Transformer { ...@@ -573,6 +593,7 @@ public final class Transformer {
checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed."); checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed.");
this.context = context; this.context = context;
this.transformationRequest = transformationRequest; this.transformationRequest = transformationRequest;
this.audioProcessors = audioProcessors;
this.videoEffects = videoEffects; this.videoEffects = videoEffects;
this.removeAudio = removeAudio; this.removeAudio = removeAudio;
this.removeVideo = removeVideo; this.removeVideo = removeVideo;
...@@ -589,6 +610,7 @@ public final class Transformer { ...@@ -589,6 +610,7 @@ public final class Transformer {
new TransformerInternal( new TransformerInternal(
context, context,
transformationRequest, transformationRequest,
audioProcessors,
videoEffects, videoEffects,
removeAudio, removeAudio,
removeVideo, removeVideo,
......
...@@ -34,6 +34,7 @@ import androidx.media3.common.MediaItem; ...@@ -34,6 +34,7 @@ import androidx.media3.common.MediaItem;
import androidx.media3.common.Metadata; import androidx.media3.common.Metadata;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackException;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.extractor.metadata.mp4.SlowMotionData; import androidx.media3.extractor.metadata.mp4.SlowMotionData;
...@@ -52,6 +53,7 @@ import java.util.List; ...@@ -52,6 +53,7 @@ import java.util.List;
private final Context context; private final Context context;
private final TransformationRequest transformationRequest; private final TransformationRequest transformationRequest;
private final ImmutableList<AudioProcessor> audioProcessors;
private final ImmutableList<Effect> videoEffects; private final ImmutableList<Effect> videoEffects;
private final Codec.DecoderFactory decoderFactory; private final Codec.DecoderFactory decoderFactory;
private final Codec.EncoderFactory encoderFactory; private final Codec.EncoderFactory encoderFactory;
...@@ -66,6 +68,7 @@ import java.util.List; ...@@ -66,6 +68,7 @@ import java.util.List;
public TransformerInternal( public TransformerInternal(
Context context, Context context,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
ImmutableList<AudioProcessor> audioProcessors,
ImmutableList<Effect> videoEffects, ImmutableList<Effect> videoEffects,
boolean removeAudio, boolean removeAudio,
boolean removeVideo, boolean removeVideo,
...@@ -78,6 +81,7 @@ import java.util.List; ...@@ -78,6 +81,7 @@ import java.util.List;
Clock clock) { Clock clock) {
this.context = context; this.context = context;
this.transformationRequest = transformationRequest; this.transformationRequest = transformationRequest;
this.audioProcessors = audioProcessors;
this.videoEffects = videoEffects; this.videoEffects = videoEffects;
this.decoderFactory = decoderFactory; this.decoderFactory = decoderFactory;
this.encoderFactory = encoderFactory; this.encoderFactory = encoderFactory;
...@@ -210,6 +214,7 @@ import java.util.List; ...@@ -210,6 +214,7 @@ import java.util.List;
streamStartPositionUs, streamStartPositionUs,
streamOffsetUs, streamOffsetUs,
transformationRequest, transformationRequest,
audioProcessors,
decoderFactory, decoderFactory,
encoderFactory, encoderFactory,
muxerWrapper, muxerWrapper,
...@@ -256,6 +261,9 @@ import java.util.List; ...@@ -256,6 +261,9 @@ import java.util.List;
if (transformationRequest.flattenForSlowMotion && isSlowMotion(inputFormat)) { if (transformationRequest.flattenForSlowMotion && isSlowMotion(inputFormat)) {
return true; return true;
} }
if (!audioProcessors.isEmpty()) {
return true;
}
return false; return false;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment