CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-androidx-media3--media3-exoplayer

ExoPlayer module that provides the core ExoPlayer implementation for local media playback on Android, supporting various media formats and streaming protocols

Pending
Overview
Eval results
Files

audio-rendering.mddocs/

Audio Rendering

Audio rendering in ExoPlayer handles decoding and outputting audio data to the Android audio system. The audio pipeline includes decoders, processors, and sinks that work together to provide high-quality audio playback with support for various codecs and audio effects.

AudioSink Interface

The AudioSink interface defines how audio data is consumed and output to audio hardware.

public interface AudioSink {
    /**
     * Exception thrown when audio sink configuration fails.
     */
    final class ConfigurationException extends Exception {
        public final Format format;
        
        public ConfigurationException(String message, Format format);
        public ConfigurationException(Throwable cause, Format format);
        public ConfigurationException(String message, Throwable cause, Format format);
    }
    
    /**
     * Exception thrown when audio sink write operations fail.
     */
    final class WriteException extends Exception {
        public final int errorCode;
        public final Format format;
        
        public WriteException(int errorCode, Format format, Throwable cause);
    }
    
    /**
     * Configures the sink for the specified audio format.
     * 
     * @param format The audio format
     * @param specifiedBufferSize The buffer size in bytes, or 0 for default
     * @param outputChannels The output channel configuration, or null for default
     * @throws ConfigurationException If configuration fails
     */
    void configure(Format format, int specifiedBufferSize, @Nullable int[] outputChannels) throws ConfigurationException;
    
    /**
     * Starts or resumes audio output.
     */
    void play();
    
    /**
     * Pauses audio output.
     */
    void pause();
    
    /**
     * Plays to the end of the stream.
     * 
     * @throws WriteException If writing fails
     */
    void playToEndOfStream() throws WriteException;
    
    /**
     * Resets the sink.
     */
    void reset();
    
    /**
     * Releases the sink.
     */
    void release();
    
    /**
     * Sets the audio volume.
     * 
     * @param volume The volume (0.0 to 1.0)
     */
    void setVolume(float volume);
    
    /**
     * Sets the audio attributes.
     * 
     * @param audioAttributes The audio attributes
     */
    void setAudioAttributes(AudioAttributes audioAttributes);
    
    /**
     * Sets auxiliary effect information.
     * 
     * @param auxEffectInfo The auxiliary effect info
     */
    void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);
    
    /**
     * Returns the current playback parameters.
     * 
     * @return The current playback parameters
     */
    PlaybackParameters getPlaybackParameters();
    
    /**
     * Sets playback parameters for speed and pitch adjustment.
     * 
     * @param playbackParameters The playback parameters
     */
    void setPlaybackParameters(PlaybackParameters playbackParameters);
    
    /**
     * Attempts to write audio data to the sink.
     * 
     * @param buffer The audio data buffer
     * @param presentationTimeUs The presentation time in microseconds
     * @param encodedAccessUnitCount The number of encoded access units
     * @return Whether the buffer was consumed
     * @throws WriteException If writing fails
     */
    boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAccessUnitCount) throws WriteException;
    
    /**
     * Returns the buffer size for the AudioTrack in microseconds.
     * 
     * @return The buffer size in microseconds
     */
    long getAudioTrackBufferSizeUs();
}

DefaultAudioSink

The default implementation of AudioSink using Android's AudioTrack.

public final class DefaultAudioSink implements AudioSink {
    /**
     * Builder for DefaultAudioSink.
     */
    public static final class Builder {
        /**
         * Creates a builder.
         */
        public Builder();
        
        /**
         * Sets the audio capabilities.
         * 
         * @param audioCapabilities The audio capabilities
         * @return This builder
         */
        public Builder setAudioCapabilities(AudioCapabilities audioCapabilities);
        
        /**
         * Sets the audio processors.
         * 
         * @param audioProcessors The audio processors
         * @return This builder
         */
        public Builder setAudioProcessors(AudioProcessor[] audioProcessors);
        
        /**
         * Sets whether to enable float output.
         * 
         * @param enableFloatOutput Whether to enable float output
         * @return This builder
         */
        public Builder setEnableFloatOutput(boolean enableFloatOutput);
        
        /**
         * Sets whether to enable AudioTrack playback parameters.
         * 
         * @param enableAudioTrackPlaybackParams Whether to enable AudioTrack playback parameters
         * @return This builder
         */
        public Builder setEnableAudioTrackPlaybackParams(boolean enableAudioTrackPlaybackParams);
        
        /**
         * Sets the offload mode.
         * 
         * @param offloadMode The offload mode
         * @return This builder
         */
        public Builder setOffloadMode(@OffloadMode int offloadMode);
        
        /**
         * Builds the DefaultAudioSink.
         * 
         * @return The built DefaultAudioSink
         */
        public DefaultAudioSink build();
    }
    
    // Offload modes
    public static final int OFFLOAD_MODE_DISABLED = 0;
    public static final int OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED = 1;
    public static final int OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED = 2;
    public static final int OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED = 3;
}

MediaCodecAudioRenderer

Audio renderer that uses MediaCodec for decoding.

public class MediaCodecAudioRenderer extends MediaCodecRenderer implements MediaClock {
    /**
     * Creates a MediaCodecAudioRenderer.
     * 
     * @param context The context
     * @param mediaCodecSelector The MediaCodec selector
     * @param enableDecoderFallback Whether to enable decoder fallback
     * @param eventHandler The event handler
     * @param eventListener The event listener
     * @param audioSink The audio sink
     */
    public MediaCodecAudioRenderer(Context context, MediaCodecSelector mediaCodecSelector, 
                                 boolean enableDecoderFallback, @Nullable Handler eventHandler,
                                 @Nullable AudioRendererEventListener eventListener, AudioSink audioSink);
    
    /**
     * Sets the volume.
     * 
     * @param volume The volume (0.0 to 1.0)
     */
    public final void setVolume(float volume);
    
    /**
     * Returns the current playback parameters.
     * 
     * @return The current playback parameters
     */
    public PlaybackParameters getPlaybackParameters();
    
    /**
     * Sets playback parameters.
     * 
     * @param playbackParameters The playback parameters
     */
    public void setPlaybackParameters(PlaybackParameters playbackParameters);
    
    /**
     * Returns the position according to the media clock.
     * 
     * @return The position in microseconds
     */
    @Override
    public long getPositionUs();
    
    /**
     * Sets the audio session ID.
     * 
     * @param audioSessionId The audio session ID
     */
    public void setAudioSessionId(int audioSessionId);
    
    /**
     * Sets auxiliary effect information.
     * 
     * @param auxEffectInfo The auxiliary effect info
     */
    public void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);
}

AudioRendererEventListener

Listener for audio renderer events.

public interface AudioRendererEventListener {
    /**
     * Called when the audio renderer is enabled.
     * 
     * @param counters The decoder counters
     */
    default void onAudioEnabled(DecoderCounters counters) {}
    
    /**
     * Called when the audio session ID changes.
     * 
     * @param audioSessionId The new audio session ID
     */
    default void onAudioSessionIdChanged(int audioSessionId) {}
    
    /**
     * Called when the audio decoder is initialized.
     * 
     * @param decoderName The decoder name
     * @param initializedTimestampMs The initialization timestamp
     * @param initializationDurationMs The initialization duration
     */
    default void onAudioDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {}
    
    /**
     * Called when the audio input format changes.
     * 
     * @param format The new format
     * @param decoderReuseEvaluation The decoder reuse evaluation
     */
    default void onAudioInputFormatChanged(Format format, @Nullable DecoderReuseEvaluation decoderReuseEvaluation) {}
    
    /**
     * Called when the audio position is advancing.
     * 
     * @param playoutStartSystemTimeMs The playout start system time
     */
    default void onAudioPositionAdvancing(long playoutStartSystemTimeMs) {}
    
    /**
     * Called when audio underrun occurs.
     * 
     * @param bufferSize The buffer size
     * @param bufferSizeMs The buffer size in milliseconds
     * @param elapsedSinceLastFeedMs Time elapsed since last feed
     */
    default void onAudioUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {}
    
    /**
     * Called when the audio decoder is released.
     * 
     * @param decoderName The decoder name
     */
    default void onAudioDecoderReleased(String decoderName) {}
    
    /**
     * Called when the audio renderer is disabled.
     * 
     * @param counters The decoder counters
     */
    default void onAudioDisabled(DecoderCounters counters) {}
    
    /**
     * Called when the audio sink underruns.
     * 
     * @param bufferSize The buffer size
     * @param bufferSizeMs The buffer size in milliseconds
     * @param elapsedSinceLastFeedMs Time elapsed since last feed
     */
    default void onAudioSinkUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {}
    
    /**
     * Called when audio codec error occurs.
     * 
     * @param audioCodecError The audio codec error
     */
    default void onAudioCodecError(Exception audioCodecError) {}
}

AudioProcessor Interface

Interface for audio processing components that can modify audio data.

public interface AudioProcessor {
    /**
     * Data structure for audio format.
     */
    final class AudioFormat {
        public static final AudioFormat NOT_SET = new AudioFormat(Format.NO_VALUE, Format.NO_VALUE, Format.NO_VALUE);
        
        public final int sampleRate;
        public final int channelCount;
        @C.PcmEncoding public final int encoding;
        
        public AudioFormat(int sampleRate, int channelCount, @C.PcmEncoding int encoding);
    }
    
    /**
     * Exception thrown when audio processing fails.
     */
    final class UnhandledAudioFormatException extends Exception {
        public final AudioFormat inputAudioFormat;
        public final AudioFormat outputAudioFormat;
        
        public UnhandledAudioFormatException(AudioFormat inputAudioFormat, AudioFormat outputAudioFormat);
    }
    
    /**
     * Configures the processor for the specified input format.
     * 
     * @param inputAudioFormat The input audio format
     * @return The output audio format
     * @throws UnhandledAudioFormatException If the format is not supported
     */
    AudioFormat configure(AudioFormat inputAudioFormat) throws UnhandledAudioFormatException;
    
    /**
     * Returns whether the processor is active.
     * 
     * @return Whether the processor is active
     */
    boolean isActive();
    
    /**
     * Queues input data for processing.
     * 
     * @param inputBuffer The input buffer
     */
    void queueInput(ByteBuffer inputBuffer);
    
    /**
     * Queues end of stream.
     */
    void queueEndOfStream();
    
    /**
     * Returns a buffer containing processed output data.
     * 
     * @return The output buffer, or EMPTY_BUFFER if no output is available
     */
    ByteBuffer getOutput();
    
    /**
     * Returns whether the processor has ended.
     * 
     * @return Whether the processor has ended
     */
    boolean isEnded();
    
    /**
     * Flushes the processor.
     */
    void flush();
    
    /**
     * Resets the processor.
     */
    void reset();
}

Usage Examples

Basic Audio Renderer Setup

// Create default audio sink
DefaultAudioSink audioSink = new DefaultAudioSink.Builder().build();

// Create audio renderer
MediaCodecAudioRenderer audioRenderer = new MediaCodecAudioRenderer(
    context,
    MediaCodecSelector.DEFAULT,
    /* enableDecoderFallback= */ false,
    /* eventHandler= */ null,
    /* eventListener= */ null,
    audioSink
);

// Use with custom renderers factory
RenderersFactory renderersFactory = new DefaultRenderersFactory(context) {
    @Override
    protected void buildAudioRenderers(Context context, int extensionRendererMode,
                                     MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback,
                                     AudioSink audioSink, Handler eventHandler,
                                     AudioRendererEventListener eventListener,
                                     ArrayList<Renderer> out) {
        out.add(new MediaCodecAudioRenderer(context, mediaCodecSelector, enableDecoderFallback,
                                          eventHandler, eventListener, audioSink));
    }
};

Audio Sink Configuration

// Configure audio sink with custom settings
DefaultAudioSink audioSink = new DefaultAudioSink.Builder()
    .setEnableFloatOutput(true)  // Enable high-resolution audio
    .setEnableAudioTrackPlaybackParams(true)  // Enable speed/pitch adjustment
    .setOffloadMode(DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED)  // Enable offload
    .build();

Audio Event Handling

AudioRendererEventListener audioListener = new AudioRendererEventListener() {
    @Override
    public void onAudioEnabled(DecoderCounters counters) {
        Log.d(TAG, "Audio enabled");
    }
    
    @Override
    public void onAudioSessionIdChanged(int audioSessionId) {
        Log.d(TAG, "Audio session ID changed: " + audioSessionId);
        // Apply audio effects to this session
        applyAudioEffects(audioSessionId);
    }
    
    @Override
    public void onAudioDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {
        Log.d(TAG, "Audio decoder initialized: " + decoderName);
    }
    
    @Override
    public void onAudioUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
        Log.w(TAG, "Audio underrun detected");
    }
    
    @Override
    public void onAudioCodecError(Exception audioCodecError) {
        Log.e(TAG, "Audio codec error", audioCodecError);
    }
};

// Use with renderer
MediaCodecAudioRenderer audioRenderer = new MediaCodecAudioRenderer(
    context, MediaCodecSelector.DEFAULT, false, 
    handler, audioListener, audioSink
);

Volume and Playback Control

// Set volume on audio renderer
audioRenderer.setVolume(0.5f);  // 50% volume

// Set playback parameters for speed/pitch adjustment
PlaybackParameters params = new PlaybackParameters(1.5f, 1.0f);  // 1.5x speed, normal pitch
audioRenderer.setPlaybackParameters(params);

// Get current playback parameters
PlaybackParameters currentParams = audioRenderer.getPlaybackParameters();

Audio Effects Integration

// Apply audio effects using session ID
private void applyAudioEffects(int audioSessionId) {
    // Create equalizer
    Equalizer equalizer = new Equalizer(0, audioSessionId);
    equalizer.setEnabled(true);
    
    // Create bass boost
    BassBoost bassBoost = new BassBoost(0, audioSessionId);
    bassBoost.setStrength((short) 1000);  // Maximum bass boost
    bassBoost.setEnabled(true);
    
    // Create virtualizer
    Virtualizer virtualizer = new Virtualizer(0, audioSessionId);
    virtualizer.setStrength((short) 1000);  // Maximum virtualization
    virtualizer.setEnabled(true);
}

Custom Audio Processor

public class VolumeAudioProcessor implements AudioProcessor {
    private float volume = 1.0f;
    private AudioFormat outputFormat;
    private ByteBuffer buffer = EMPTY_BUFFER;
    private boolean ended;
    
    public void setVolume(float volume) {
        this.volume = volume;
    }
    
    @Override
    public AudioFormat configure(AudioFormat inputAudioFormat) throws UnhandledAudioFormatException {
        if (inputAudioFormat.encoding != C.ENCODING_PCM_16BIT) {
            throw new UnhandledAudioFormatException(inputAudioFormat, AudioFormat.NOT_SET);
        }
        this.outputFormat = inputAudioFormat;
        return outputFormat;
    }
    
    @Override
    public boolean isActive() {
        return volume != 1.0f;
    }
    
    @Override
    public void queueInput(ByteBuffer inputBuffer) {
        if (!isActive()) {
            buffer = inputBuffer;
            return;
        }
        
        // Apply volume adjustment
        ByteBuffer processedBuffer = ByteBuffer.allocate(inputBuffer.remaining());
        while (inputBuffer.hasRemaining()) {
            short sample = inputBuffer.getShort();
            short adjustedSample = (short) (sample * volume);
            processedBuffer.putShort(adjustedSample);
        }
        processedBuffer.flip();
        buffer = processedBuffer;
    }
    
    @Override
    public void queueEndOfStream() {
        ended = true;
    }
    
    @Override
    public ByteBuffer getOutput() {
        ByteBuffer outputBuffer = buffer;
        buffer = EMPTY_BUFFER;
        return outputBuffer;
    }
    
    @Override
    public boolean isEnded() {
        return ended && buffer == EMPTY_BUFFER;
    }
    
    @Override
    public void flush() {
        buffer = EMPTY_BUFFER;
        ended = false;
    }
    
    @Override
    public void reset() {
        flush();
        outputFormat = null;
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-androidx-media3--media3-exoplayer

docs

analytics.md

audio-rendering.md

core-player.md

drm-support.md

index.md

media-sources.md

offline-support.md

track-selection.md

video-rendering.md

tile.json