Repository navigation
Playing simultaneous tracks with ExoPlayer 2.17 #10050
Copy link
Copy link
Closed
Labels
Description
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) {
}
};
Reactions are currently unavailable
Activity