From 1b4e1d4f1367d40f0fb24ec7cf6d8a8f16f73373 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Mon, 16 Sep 2024 12:33:06 +0200 Subject: [PATCH] merge StreamVariant and stream part 2 --- .../newplayer/utils/MediaSourceBuilder.kt | 23 +-- .../newpipe/newplayer/utils/StreamSelect.kt | 158 +++++++++--------- 2 files changed, 88 insertions(+), 93 deletions(-) diff --git a/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt b/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt index e873ff2..7d010bc 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/utils/MediaSourceBuilder.kt @@ -2,18 +2,14 @@ package net.newpipe.newplayer.utils import androidx.annotation.OptIn import androidx.media3.common.MediaItem -import androidx.media3.common.Tracks import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.HttpDataSource import androidx.media3.exoplayer.dash.DashMediaSource -import androidx.media3.exoplayer.source.DefaultMediaSourceFactory -import androidx.media3.exoplayer.source.MediaSource -import androidx.media3.exoplayer.source.MergingMediaSource import androidx.media3.exoplayer.source.ProgressiveMediaSource import kotlinx.coroutines.flow.MutableSharedFlow import net.newpipe.newplayer.MediaRepository import net.newpipe.newplayer.StreamType -import net.newpipe.newplayer.StreamVariant +import net.newpipe.newplayer.Stream import kotlin.random.Random class MediaSourceBuilder( @@ -23,31 +19,30 @@ class MediaSourceBuilder( private val httpDataSourceFactory: HttpDataSource.Factory ) { suspend fun buildMediaSource(item: String) { - val availableStreamVariants = repository.getAvailableStreamVariants(item) + val availableStreams = repository.getStreams(item) } @OptIn(UnstableApi::class) - private suspend - fun toMediaItem(item: String, streamVariant: StreamVariant): MediaItem { - val dataStream = repository.getStream(item, streamVariant) + private + fun toMediaItem(item: String, stream: Stream): MediaItem { val uniqueId = Random.nextLong() uniqueIdToIdLookup[uniqueId] = item val mediaItemBuilder = MediaItem.Builder() .setMediaId(uniqueId.toString()) - .setUri(dataStream.streamUri) + .setUri(stream.streamUri) - if (dataStream.mimeType != null) { - mediaItemBuilder.setMimeType(dataStream.mimeType) + if (stream.mimeType != null) { + mediaItemBuilder.setMimeType(stream.mimeType) } return mediaItemBuilder.build() } @OptIn(UnstableApi::class) - private fun toMediaSource(mediaItem: MediaItem, streamVariant: StreamVariant) = - if (streamVariant.streamType == StreamType.DYNAMIC) + private fun toMediaSource(mediaItem: MediaItem, stream: Stream) = + if (stream.streamType == StreamType.DYNAMIC) DashMediaSource.Factory(httpDataSourceFactory) .createMediaSource(mediaItem) else diff --git a/new-player/src/main/java/net/newpipe/newplayer/utils/StreamSelect.kt b/new-player/src/main/java/net/newpipe/newplayer/utils/StreamSelect.kt index 15d568d..a82cce0 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/utils/StreamSelect.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/utils/StreamSelect.kt @@ -4,29 +4,29 @@ package net.newpipe.newplayer.utils import net.newpipe.newplayer.NewPlayerException import net.newpipe.newplayer.PlayMode import net.newpipe.newplayer.StreamType -import net.newpipe.newplayer.StreamVariant +import net.newpipe.newplayer.Stream object StreamSelect { interface StreamSelection data class SingleSelection( - val streamVariant: StreamVariant + val stream: Stream ) : StreamSelection data class MultiSelection( - val videoStream: StreamVariant, - val audioStream: StreamVariant + val videoStream: Stream, + val audioStream: Stream ) : StreamSelection private fun getBestLanguageFit( - availableStreamVariants: List, + availableStreams: List, preferredLanguages: List ): String? { for (preferredLanguage in preferredLanguages) { - for (availableVariant in availableStreamVariants) { - if (availableVariant.language == preferredLanguage) { + for (available in availableStreams) { + if (available.language == preferredLanguage) { return preferredLanguage } } @@ -34,21 +34,21 @@ object StreamSelect { return null } - private fun filterVariantsByLanguage( - availableStreamVariants: List, + private fun filtersByLanguage( + availableStreams: List, language: String ) = - availableStreamVariants.filter { it.language == language } + availableStreams.filter { it.language == language } private fun getBestFittingVideoIdentifier( - availableStreamVariants: List, + availableStreams: List, preferredVideoIdentifier: List ): String? { for (preferredStream in preferredVideoIdentifier) { - for (availableVariant in availableStreamVariants) { - if ((availableVariant.streamType == StreamType.AUDIO_AND_VIDEO || - availableVariant.streamType == StreamType.VIDEO) - && preferredStream == availableVariant.streamVariantIdentifier + for (available in availableStreams) { + if ((available.streamType == StreamType.AUDIO_AND_VIDEO || + available.streamType == StreamType.VIDEO) + && preferredStream == available.identifier ) { return preferredStream } @@ -57,25 +57,25 @@ object StreamSelect { return null } - private fun getFirstVariantMatchingIdentifier( - availableStreamVariants: List, + private fun getFirstMatchingIdentifier( + availableStreams: List, identifier: String - ): StreamVariant? { - for (variant in availableStreamVariants) { - if (variant.streamVariantIdentifier == identifier) + ): Stream? { + for (variant in availableStreams) { + if (variant.identifier == identifier) return variant } return null } - private fun getBestFittingAudioVariant( - availableStreamVariants: List, + private fun getBestFittingAudio( + availableStreams: List, preferredAudioIdentifier: List - ): StreamVariant? { + ): Stream? { for (preferredStream in preferredAudioIdentifier) { - for (availableStream in availableStreamVariants) { + for (availableStream in availableStreams) { if (availableStream.streamType == StreamType.AUDIO - && preferredStream == availableStream.streamVariantIdentifier + && preferredStream == availableStream.identifier ) { return availableStream } @@ -84,21 +84,21 @@ object StreamSelect { return null } - private fun getVideoOnlyVariantWithMatchingIdentifier( - availableStreamVariants: List, + private fun getVideoOnlyWithMatchingIdentifier( + availableStreams: List, identifier: String - ): StreamVariant? { - for (variant in availableStreamVariants) { + ): Stream? { + for (variant in availableStreams) { if (variant.streamType == StreamType.VIDEO - && variant.streamVariantIdentifier == identifier + && variant.identifier == identifier ) return variant } return null } - private fun getDynamicStream(availableStreamVariants: List): StreamVariant? { - for (variant in availableStreamVariants) { + private fun getDynamicStream(availableStreams: List): Stream? { + for (variant in availableStreams) { if (variant.streamType == StreamType.DYNAMIC) { return variant } @@ -106,16 +106,16 @@ object StreamSelect { return null } - private fun getNonDynamicVideoVariants(availableStreamVariants: List) = - availableStreamVariants.filter { + private fun getNonDynamicVideos(availableStreams: List) = + availableStreams.filter { it.streamType == StreamType.VIDEO || it.streamType == StreamType.AUDIO_AND_VIDEO } - private fun getNonDynamicAudioVariants(availableStreamVariants: List) = - availableStreamVariants.filter { it.streamType == StreamType.AUDIO } + private fun getNonDynamicAudios(availableStreams: List) = + availableStreams.filter { it.streamType == StreamType.AUDIO } - private fun hasVideoStreamVariants(availableStreamVariants: List): Boolean { - for (variant in availableStreamVariants) { + private fun hasVideoStreams(availableStreams: List): Boolean { + for (variant in availableStreams) { if (variant.streamType == StreamType.AUDIO_AND_VIDEO || variant.streamType == StreamType.VIDEO || variant.streamType == StreamType.DYNAMIC) return true } @@ -125,7 +125,7 @@ object StreamSelect { fun selectStream( item: String, playMode: PlayMode, - availableStreamVariants: List, + availableStreams: List, preferredVideoIdentifier: List, preferredAudioIdentifier: List, preferredLanguage: List @@ -133,10 +133,10 @@ object StreamSelect { // filter for best fitting language stream variants - val bestFittingLanguage = getBestLanguageFit(availableStreamVariants, preferredLanguage) - val availableVariantsInPreferredLanguage = - if (bestFittingLanguage != null) filterVariantsByLanguage( - availableStreamVariants, + val bestFittingLanguage = getBestLanguageFit(availableStreams, preferredLanguage) + val availablesInPreferredLanguage = + if (bestFittingLanguage != null) filtersByLanguage( + availableStreams, bestFittingLanguage ) else { @@ -145,12 +145,12 @@ object StreamSelect { // is it a video stream or a pure audio stream? - if (hasVideoStreamVariants(availableStreamVariants)) { + if (hasVideoStreams(availableStreams)) { // first: try and get a dynamic stream variant - getDynamicStream(availableVariantsInPreferredLanguage) + getDynamicStream(availablesInPreferredLanguage) ?: getDynamicStream( - availableStreamVariants + availableStreams )?.let { return SingleSelection(it) } @@ -159,35 +159,35 @@ object StreamSelect { val bestVideoIdentifier = getBestFittingVideoIdentifier( - availableVariantsInPreferredLanguage, + availablesInPreferredLanguage, preferredVideoIdentifier )?.let { - val videoVariants = - getNonDynamicVideoVariants(availableVariantsInPreferredLanguage) - videoVariants[videoVariants.size / 2].streamVariantIdentifier + val videos = + getNonDynamicVideos(availablesInPreferredLanguage) + videos[videos.size / 2].identifier } ?: getBestFittingVideoIdentifier( - availableStreamVariants, + availableStreams, preferredVideoIdentifier ) ?: run { - val videoVariants = getNonDynamicVideoVariants(availableStreamVariants) - videoVariants[videoVariants.size / 2].streamVariantIdentifier + val videos = getNonDynamicVideos(availableStreams) + videos[videos.size / 2].identifier } val videoOnlyStream = - getVideoOnlyVariantWithMatchingIdentifier( - availableVariantsInPreferredLanguage, + getVideoOnlyWithMatchingIdentifier( + availablesInPreferredLanguage, bestVideoIdentifier - ) ?: getVideoOnlyVariantWithMatchingIdentifier( - availableStreamVariants, + ) ?: getVideoOnlyWithMatchingIdentifier( + availableStreams, bestVideoIdentifier ) if (videoOnlyStream != null) { - getBestFittingAudioVariant( - availableVariantsInPreferredLanguage, + getBestFittingAudio( + availablesInPreferredLanguage, preferredAudioIdentifier - ) ?: getBestFittingAudioVariant(availableStreamVariants, preferredAudioIdentifier) + ) ?: getBestFittingAudio(availableStreams, preferredAudioIdentifier) ?.let { return MultiSelection(videoOnlyStream, it) } @@ -195,12 +195,12 @@ object StreamSelect { // fourth: try to get a video and audio stream variant with the best fitting identifier - getFirstVariantMatchingIdentifier( - availableVariantsInPreferredLanguage, + getFirstMatchingIdentifier( + availablesInPreferredLanguage, bestVideoIdentifier ) - ?: getFirstVariantMatchingIdentifier( - availableStreamVariants, + ?: getFirstMatchingIdentifier( + availableStreams, bestVideoIdentifier )?.let { return SingleSelection(it) @@ -209,28 +209,28 @@ object StreamSelect { // fifth: try and get the median video and audio stream variant return SingleSelection(run { - val videoVariants = - getNonDynamicVideoVariants(availableVariantsInPreferredLanguage).ifEmpty { - getNonDynamicVideoVariants(availableStreamVariants) + val videos = + getNonDynamicVideos(availablesInPreferredLanguage).ifEmpty { + getNonDynamicVideos(availableStreams) } - if (videoVariants.isNotEmpty()) { - return@run videoVariants[videoVariants.size / 2] + if (videos.isNotEmpty()) { + return@run videos[videos.size / 2] } else { throw NewPlayerException("No fitting video stream could be found for stream item item: ${item}") } }) - } else { /* if(hasVideoStreamVariants(availableStreamVariants)) */ + } else { /* if(hasVideoStreams(availableStreams)) */ // first: try to get an audio stream variant with the best fitting identifier - getBestFittingAudioVariant( - availableVariantsInPreferredLanguage, + getBestFittingAudio( + availablesInPreferredLanguage, preferredAudioIdentifier ) - ?: getBestFittingAudioVariant( - availableStreamVariants, + ?: getBestFittingAudio( + availableStreams, preferredAudioIdentifier )?.let { return SingleSelection(it) @@ -239,16 +239,16 @@ object StreamSelect { // second: try and get the median audio stream variant return SingleSelection(run { - val audioVariants = - getNonDynamicAudioVariants(availableVariantsInPreferredLanguage).let { + val audios = + getNonDynamicAudios(availablesInPreferredLanguage).let { if (it.isNotEmpty()) { it } else { - getNonDynamicAudioVariants(availableStreamVariants) + getNonDynamicAudios(availableStreams) } } - if (audioVariants.isNotEmpty()) { - return@run audioVariants[audioVariants.size / 2] + if (audios.isNotEmpty()) { + return@run audios[audios.size / 2] } else { throw NewPlayerException("No fitting audio stream could be found for stream item item: ${item}") }