Skip to content

Playing simultaneous tracks with ExoPlayer 2.17 #10050

Closed

Description

@ziad-halabi9

I am trying to play multiple songs simultaneously while being able to control the volume of each track through the audioSinks. I had the code used in this ticket. It was working fine until I updated to ExoPlayer 2.17. Playback started failing with the following stack trace:

E/ExoPlayerImplInternal: Playback error
      com.google.android.exoplayer2.ExoPlaybackException: Unexpected runtime error
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:624)
        at android.os.Handler.dispatchMessage(Handler.java:103)
        at android.os.Looper.loop(Looper.java:237)
        at android.os.HandlerThread.run(HandlerThread.java:67)
     Caused by: java.lang.IllegalStateException
        at com.google.android.exoplayer2.util.Assertions.checkState(Assertions.java:84)
        at com.google.android.exoplayer2.source.ProgressiveMediaPeriod.selectTracks(ProgressiveMediaPeriod.java:283)
        at com.google.android.exoplayer2.source.MergingMediaPeriod.selectTracks(MergingMediaPeriod.java:153)
        at com.google.android.exoplayer2.source.MaskingMediaPeriod.selectTracks(MaskingMediaPeriod.java:186)
        at com.google.android.exoplayer2.MediaPeriodHolder.applyTrackSelection(MediaPeriodHolder.java:296)
        at com.google.android.exoplayer2.MediaPeriodHolder.applyTrackSelection(MediaPeriodHolder.java:259)
        at com.google.android.exoplayer2.MediaPeriodHolder.handlePrepared(MediaPeriodHolder.java:193)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handlePeriodPrepared(ExoPlayerImplInternal.java:2247)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:517)
        at android.os.Handler.dispatchMessage(Handler.java:103) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 

The URLs here are just 4 mp3 tracks. I am trying to figure out what changes are needed to make this work with 2.17. I would appreciate any pointers or if there is a quick fix to get it working again. Thanks!

The code is:

MediaSource mediaSource1 = MediaSourceBuilder.buildMediaSource(context, Uri.parse(url1));
MediaSource mediaSource2 = MediaSourceBuilder.buildMediaSource(context, Uri.parse(url2));
MediaSource mediaSource3 = MediaSourceBuilder.buildMediaSource(context, Uri.parse(url3));
MediaSource mediaSource4 = MediaSourceBuilder.buildMediaSource(context, Uri.parse(url4));

TracksRenderersFactory tracksRenderersFactory = new TracksRenderersFactory(context);

player = new ExoPlayer.Builder(context, tracksRenderersFactory)
                    .setTrackSelector(trackSelector)
                    .setWakeMode(WAKE_MODE_NETWORK)
                    .build();
            
MergingMediaSource mergingMediaSource = new MergingMediaSource(mediaSource1, mediaSource2, mediaSource3, mediaSource4);
                
player.setMediaSource(mergingMediaSource);
player.prepare();
player.play();

...

    public class TracksRenderersFactory extends DefaultRenderersFactory {

            public TracksRenderersFactory(Context context) {
                super(context);
            }

            @Override
            protected void buildAudioRenderers(Context context, int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, AudioSink audioSink, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {
                super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, audioSink, eventHandler, eventListener, out);

                AudioProcessor[] audioProcessors = new AudioProcessor[0];
                audioSink1 = audioSink;

                audioSink2 = new DefaultAudioSink.Builder()
                        .setAudioCapabilities(AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES)
                        .setAudioProcessors(audioProcessors)
                        .build();

                audioSink3 = new DefaultAudioSink.Builder()
                        .setAudioCapabilities(AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES)
                        .setAudioProcessors(audioProcessors)
                        .build();

                audio4Sink = new DefaultAudioSink.Builder()
                        .setAudioCapabilities(AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES)
                        .setAudioProcessors(audioProcessors)
                        .build();

                out.add(new AudioRendererWithoutClock(context, mediaCodecSelector, (DefaultAudioSink) audioSink2));
                out.add(new AudioRendererWithoutClock(context, mediaCodecSelector, (DefaultAudioSink) audioSink3));
                out.add(new AudioRendererWithoutClock(context, mediaCodecSelector, (DefaultAudioSink) audioSink4));
            }
        }

        private static final class AudioRendererWithoutClock extends MediaCodecAudioRenderer {
            public AudioRendererWithoutClock(Context context, MediaCodecSelector mediaCodecSelector, DefaultAudioSink defaultAudioSink) {
                super(context, mediaCodecSelector, null, null, defaultAudioSink);
            }

            @Override
            public MediaClock getMediaClock() {
                return null;
            }
        }

        private final TrackSelector trackSelector = new TrackSelector() {
            @Override
            public TrackSelectorResult selectTracks(RendererCapabilities[] rendererCapabilities,
                                                    TrackGroupArray trackGroups, MediaSource.MediaPeriodId periodId, Timeline timeline) throws ExoPlaybackException {
                Queue<Integer> audioRenderers = new ArrayDeque<>();
                RendererConfiguration[] configs = new RendererConfiguration[rendererCapabilities.length];
                ExoTrackSelection[] selections = new ExoTrackSelection[rendererCapabilities.length];
                for (int i = 0; i < rendererCapabilities.length; i++) {
                    if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_AUDIO) {
                        audioRenderers.add(i);
                        configs[i] = RendererConfiguration.DEFAULT;
                    }
                }
                for (int i = 0; i < trackGroups.length; i++) {
                    if (MimeTypes.isAudio(trackGroups.get(i).getFormat(0).sampleMimeType)) {
                        Integer index = audioRenderers.poll();
                        if (index != null) {
                            selections[index] = new FixedTrackSelection(trackGroups.get(i), 0);
                        }
                    }
                }

                return new TrackSelectorResult(configs, selections, TracksInfo.EMPTY, new Object());
            }

            @Override
            public void onSelectionActivated(Object info) {
            }
        };

Activity

  1. self-assigned this
    on Mar 13, 2022
  2. locked and limited conversation to collaborators on May 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions