197197import java .util .List ;
198198import java .util .Objects ;
199199import java .util .Optional ;
200+ import java .util .stream .IntStream ;
200201
201202import io .reactivex .rxjava3 .android .schedulers .AndroidSchedulers ;
202203import io .reactivex .rxjava3 .core .Observable ;
@@ -4179,8 +4180,8 @@ private void useVideoSource(final boolean videoEnabled) {
41794180
41804181 // The current metadata may be null sometimes (for e.g. when using an unstable connection
41814182 // in livestreams) so we will be not able to execute the block below.
4182- // Reload the play queue manager in this case, which is the behavior when the video stream
4183- // played is not video only or when we don't know the index of the video renderer .
4183+ // Reload the play queue manager in this case, which is the behavior when we don't know the
4184+ // index of the video renderer or playQueueManagerReloadingNeeded returns true .
41844185 if (currentMetadata == null ) {
41854186 reloadPlayQueueManager ();
41864187 setRecovery ();
@@ -4190,41 +4191,22 @@ private void useVideoSource(final boolean videoEnabled) {
41904191 final int videoRenderIndex = getVideoRendererIndex ();
41914192 final StreamInfo info = currentMetadata .getMetadata ();
41924193
4193- /* For video streams: we don't want to stream in background the video stream so if the
4194- video stream played is not a video-only stream and if there is an audio stream available,
4195- play this audio stream in background by reloading the play queue manager.
4196- Otherwise the video renderer will be just disabled (because there is no
4197- other stream for it to play the audio): if the video stream is video-only, only the audio
4198- stream will be fetched and the video stream will be fetched again when the user return to a
4199- video player.
4194+ // In the case we don't know the source type, fallback to the one with video with audio or
4195+ // audio-only source.
4196+ final SourceType sourceType = videoResolver .getStreamSourceType ().orElse (
4197+ SourceType .VIDEO_WITH_AUDIO_OR_AUDIO_ONLY );
42004198
4201- For audio streams and audio live streams: nothing is done, it's not needed to reload the
4202- player with the same audio stream.
4203-
4204- For video live streams: the play queue manager is not reloaded if the stream source is a
4205- live source (see VideoPlaybackResolver#resolve()) and if that's not the case, the
4206- requirements for video streams is applied.
4207-
4208- In the case where we don't know the index of the video renderer, the play queue manager
4209- is also reloaded. */
4210-
4211- final StreamType streamType = info .getStreamType ();
4212- final SourceType sourceType = videoResolver .getStreamSourceType ()
4213- .orElse (SourceType .VIDEO_WITH_SEPARATED_AUDIO );
4199+ if (playQueueManagerReloadingNeeded (sourceType , info , videoRenderIndex )) {
4200+ reloadPlayQueueManager ();
4201+ } else {
4202+ final StreamType streamType = info .getStreamType ();
4203+ if (streamType == StreamType .AUDIO_STREAM
4204+ || streamType == StreamType .AUDIO_LIVE_STREAM ) {
4205+ // Nothing to do more than setting the recovery position
4206+ setRecovery ();
4207+ return ;
4208+ }
42144209
4215- final boolean isVideoWithSeparatedAudioOrVideoWithNoSeparatedAudioStreams =
4216- sourceType == SourceType .VIDEO_WITH_SEPARATED_AUDIO
4217- || (sourceType == SourceType .VIDEO_WITH_AUDIO_OR_AUDIO_ONLY
4218- && isNullOrEmpty (info .getAudioStreams ()));
4219- final boolean isVideoStreamTypeAndIsVideoOnlyStreamOrNoAudioStreamsAvailable =
4220- streamType == StreamType .VIDEO_STREAM
4221- && isVideoWithSeparatedAudioOrVideoWithNoSeparatedAudioStreams
4222- || (streamType == StreamType .LIVE_STREAM
4223- && (sourceType == SourceType .LIVE_STREAM
4224- || isVideoWithSeparatedAudioOrVideoWithNoSeparatedAudioStreams ));
4225-
4226- if (videoRenderIndex != RENDERER_UNAVAILABLE
4227- && isVideoStreamTypeAndIsVideoOnlyStreamOrNoAudioStreamsAvailable ) {
42284210 final TrackGroupArray videoTrackGroupArray = Objects .requireNonNull (
42294211 trackSelector .getCurrentMappedTrackInfo ()).getTrackGroups (videoRenderIndex );
42304212 if (videoEnabled ) {
@@ -4238,13 +4220,72 @@ live source (see VideoPlaybackResolver#resolve()) and if that's not the case, th
42384220 trackSelector .setParameters (trackSelector .buildUponParameters ()
42394221 .setSelectionOverride (videoRenderIndex , videoTrackGroupArray , null ));
42404222 }
4241- } else if (streamType != StreamType .AUDIO_STREAM
4242- && streamType != StreamType .AUDIO_LIVE_STREAM ) {
4243- reloadPlayQueueManager ();
42444223 }
42454224
42464225 setRecovery ();
42474226 }
4227+
4228+ /**
4229+ * Return whether the play queue manager needs to be reloaded when switching player type.
4230+ *
4231+ * <p>
4232+ * The play queue manager needs to be reloaded if the video renderer index is not known and if
4233+ * the content is not an audio content, but also if none of the following cases is met:
4234+ *
4235+ * <ul>
4236+ * <li>the content is an {@link StreamType#AUDIO_STREAM audio stream} or an
4237+ * {@link StreamType#AUDIO_LIVE_STREAM audio live stream};</li>
4238+ * <li>the content is a {@link StreamType#LIVE_STREAM live stream} and the source type is a
4239+ * {@link SourceType#LIVE_STREAM live source};</li>
4240+ * <li>the content's source is {@link SourceType#VIDEO_WITH_SEPARATED_AUDIO a video stream
4241+ * with a separated audio source} or has no audio-only streams available <b>and</b> is a
4242+ * {@link StreamType#LIVE_STREAM live stream} or a
4243+ * {@link StreamType#LIVE_STREAM live stream}.
4244+ * </li>
4245+ * </ul>
4246+ * </p>
4247+ *
4248+ * @param sourceType the {@link SourceType} of the stream
4249+ * @param streamInfo the {@link StreamInfo} of the stream
4250+ * @param videoRendererIndex the video renderer index of the video source, if that's a video
4251+ * source (or {@link #RENDERER_UNAVAILABLE})
4252+ * @return whether the play queue manager needs to be reloaded
4253+ */
4254+ private boolean playQueueManagerReloadingNeeded (final SourceType sourceType ,
4255+ @ NonNull final StreamInfo streamInfo ,
4256+ final int videoRendererIndex ) {
4257+ final StreamType streamType = streamInfo .getStreamType ();
4258+
4259+ if (videoRendererIndex == RENDERER_UNAVAILABLE && streamType != StreamType .AUDIO_STREAM
4260+ && streamType != StreamType .AUDIO_LIVE_STREAM ) {
4261+ return true ;
4262+ }
4263+
4264+ // The content is an audio stream, an audio live stream, or a live stream with a live
4265+ // source: it's not needed to reload the play queue manager because the stream source will
4266+ // be the same
4267+ if ((streamType == StreamType .AUDIO_STREAM || streamType == StreamType .AUDIO_LIVE_STREAM )
4268+ || (streamType == StreamType .LIVE_STREAM
4269+ && sourceType == SourceType .LIVE_STREAM )) {
4270+ return false ;
4271+ }
4272+
4273+ // The content's source is a video with separated audio or a video with audio -> the video
4274+ // and its fetch may be disabled
4275+ // The content's source is a video with embedded audio and the content has no separated
4276+ // audio stream available: it's probably not needed to reload the play queue manager
4277+ // because the stream source will be probably the same as the current played
4278+ if (sourceType == SourceType .VIDEO_WITH_SEPARATED_AUDIO
4279+ || (sourceType == SourceType .VIDEO_WITH_AUDIO_OR_AUDIO_ONLY
4280+ && isNullOrEmpty (streamInfo .getAudioStreams ()))) {
4281+ // It's not needed to reload the play queue manager only if the content's stream type
4282+ // is a video stream or a live stream
4283+ return streamType != StreamType .VIDEO_STREAM && streamType != StreamType .LIVE_STREAM ;
4284+ }
4285+
4286+ // Other cases: the play queue manager reload is needed
4287+ return true ;
4288+ }
42484289 //endregion
42494290
42504291
@@ -4483,16 +4524,18 @@ private int getVideoRendererIndex() {
44834524 final MappingTrackSelector .MappedTrackInfo mappedTrackInfo = trackSelector
44844525 .getCurrentMappedTrackInfo ();
44854526
4486- if (mappedTrackInfo != null ) {
4487- for (int i = 0 ; i < mappedTrackInfo .getRendererCount (); i ++) {
4488- final TrackGroupArray trackGroups = mappedTrackInfo .getTrackGroups (i );
4489- if (!trackGroups .isEmpty ()
4490- && simpleExoPlayer .getRendererType (i ) == C .TRACK_TYPE_VIDEO ) {
4491- return i ;
4492- }
4493- }
4527+ if (mappedTrackInfo == null ) {
4528+ return RENDERER_UNAVAILABLE ;
44944529 }
44954530
4496- return RENDERER_UNAVAILABLE ;
4531+ // Check every renderer
4532+ return IntStream .range (0 , mappedTrackInfo .getRendererCount ())
4533+ // Check the renderer is a video renderer and has at least one track
4534+ .filter (i -> !mappedTrackInfo .getTrackGroups (i ).isEmpty ()
4535+ && simpleExoPlayer .getRendererType (i ) == C .TRACK_TYPE_VIDEO )
4536+ // Return the first index found (there is at most one renderer per renderer type)
4537+ .findFirst ()
4538+ // No video renderer index with at least one track found: return unavailable index
4539+ .orElse (RENDERER_UNAVAILABLE );
44974540 }
44984541}
0 commit comments