mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	Bumped the exoplayer version and fixed the audio & video track selection
This commit is contained in:
		
							parent
							
								
									7e750a40e0
								
							
						
					
					
						commit
						93cbd29f3d
					
				
					 8 changed files with 108 additions and 43 deletions
				
			
		|  | @ -150,7 +150,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi | |||
|                             } else { | ||||
|                                 ChromecastSubtitlesFragment.getCurrentSavedStyle().apply { | ||||
|                                     val font = TextTrackStyle() | ||||
|                                     font.fontFamily = fontFamily ?: "Google Sans" | ||||
|                                     font.setFontFamily(fontFamily ?: "Google Sans") | ||||
|                                     fontGenericFamily?.let { | ||||
|                                         font.fontGenericFamily = it | ||||
|                                     } | ||||
|  | @ -183,7 +183,9 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi | |||
|                     val contentUrl = (remoteMediaClient?.currentItem?.media?.contentUrl | ||||
|                         ?: remoteMediaClient?.currentItem?.media?.contentId) | ||||
| 
 | ||||
|                     val sortingMethods = items.map { "${it.name} ${Qualities.getStringByInt(it.quality)}" }.toTypedArray() | ||||
|                     val sortingMethods = | ||||
|                         items.map { "${it.name} ${Qualities.getStringByInt(it.quality)}" } | ||||
|                             .toTypedArray() | ||||
|                     val sotringIndex = items.indexOfFirst { it.url == contentUrl } | ||||
| 
 | ||||
|                     val arrayAdapter = | ||||
|  | @ -279,7 +281,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi | |||
|                     val currentPosition = remoteMediaClient?.approximateStreamPosition | ||||
|                     if (currentDuration != null && currentPosition != null) | ||||
|                         DataStoreHelper.setViewPos(epData.id, currentPosition, currentDuration) | ||||
|                 } catch (t : Throwable) { | ||||
|                 } catch (t: Throwable) { | ||||
|                     logError(t) | ||||
|                 } | ||||
| 
 | ||||
|  | @ -358,10 +360,8 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onSessionConnected(castSession: CastSession?) { | ||||
|         castSession?.let { | ||||
|             super.onSessionConnected(it) | ||||
|         } | ||||
|     override fun onSessionConnected(castSession: CastSession) { | ||||
|         super.onSessionConnected(castSession) | ||||
|         remoteMediaClient?.queueSetRepeatMode(REPEAT_MODE_REPEAT_OFF, JSONObject()) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource | |||
| import com.google.android.exoplayer2.source.* | ||||
| import com.google.android.exoplayer2.text.TextRenderer | ||||
| import com.google.android.exoplayer2.trackselection.DefaultTrackSelector | ||||
| import com.google.android.exoplayer2.trackselection.TrackSelectionOverride | ||||
| import com.google.android.exoplayer2.trackselection.TrackSelector | ||||
| import com.google.android.exoplayer2.ui.SubtitleView | ||||
| import com.google.android.exoplayer2.upstream.* | ||||
|  | @ -218,7 +219,43 @@ class CS3IPlayer : IPlayer { | |||
| 
 | ||||
|     var currentSubtitles: SubtitleData? = null | ||||
| 
 | ||||
|     override fun setMaxVideoSize(width: Int, height: Int) { | ||||
|     private fun List<Tracks.Group>.getTrack(id: String?): Pair<TrackGroup, Int>? { | ||||
|         if (id == null) return null | ||||
|         // This beast of an expression does: | ||||
|         // 1. Filter all audio tracks | ||||
|         // 2. Get all formats in said audio tacks | ||||
|         // 3. Gets all ids of the formats | ||||
|         // 4. Filters to find the first audio track with the same id as the audio track we are looking for | ||||
|         // 5. Returns the media group and the index of the audio track in the group | ||||
|         return this.firstNotNullOfOrNull { group -> | ||||
|             (0 until group.mediaTrackGroup.length).map { | ||||
|                 group.getTrackFormat(it) to it | ||||
|             }.firstOrNull { it.first.id == id } | ||||
|                 ?.let { group.mediaTrackGroup to it.second } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun setMaxVideoSize(width: Int, height: Int, id: String?) { | ||||
|         if (id != null) { | ||||
|             val videoTrack = | ||||
|                 exoPlayer?.currentTracks?.groups?.filter { it.type == TRACK_TYPE_VIDEO } | ||||
|                     ?.getTrack(id) | ||||
| 
 | ||||
|             if (videoTrack != null) { | ||||
|                 exoPlayer?.trackSelectionParameters = exoPlayer?.trackSelectionParameters | ||||
|                     ?.buildUpon() | ||||
|                     ?.setOverrideForType( | ||||
|                         TrackSelectionOverride( | ||||
|                             videoTrack.first, | ||||
|                             videoTrack.second | ||||
|                         ) | ||||
|                     ) | ||||
|                     ?.build() | ||||
|                     ?: return | ||||
|                 return | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         exoPlayer?.trackSelectionParameters = exoPlayer?.trackSelectionParameters | ||||
|             ?.buildUpon() | ||||
|             ?.setMaxVideoSize(width, height) | ||||
|  | @ -226,8 +263,29 @@ class CS3IPlayer : IPlayer { | |||
|             ?: return | ||||
|     } | ||||
| 
 | ||||
|     override fun setPreferredAudioTrack(trackLanguage: String?) { | ||||
|     override fun setPreferredAudioTrack(trackLanguage: String?, id: String?) { | ||||
|         preferredAudioTrackLanguage = trackLanguage | ||||
| 
 | ||||
|         if (id != null) { | ||||
|             val audioTrack = | ||||
|                 exoPlayer?.currentTracks?.groups?.filter { it.type == TRACK_TYPE_AUDIO } | ||||
|                     ?.getTrack(id) | ||||
| 
 | ||||
|             if (audioTrack != null) { | ||||
|                 exoPlayer?.trackSelectionParameters = exoPlayer?.trackSelectionParameters | ||||
|                     ?.buildUpon() | ||||
|                     ?.setOverrideForType( | ||||
|                         TrackSelectionOverride( | ||||
|                             audioTrack.first, | ||||
|                             audioTrack.second | ||||
|                         ) | ||||
|                     ) | ||||
|                     ?.build() | ||||
|                     ?: return | ||||
|                 return | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         exoPlayer?.trackSelectionParameters = exoPlayer?.trackSelectionParameters | ||||
|             ?.buildUpon() | ||||
|             ?.setPreferredAudioLanguage(trackLanguage) | ||||
|  | @ -239,11 +297,11 @@ class CS3IPlayer : IPlayer { | |||
|     /** | ||||
|      * Gets all supported formats in a list | ||||
|      * */ | ||||
|     private fun List<TracksInfo.TrackGroupInfo>.getFormats(): List<Format> { | ||||
|     private fun List<Tracks.Group>.getFormats(): List<Pair<Format, Int>> { | ||||
|         return this.map { | ||||
|             (0 until it.trackGroup.length).mapNotNull { i -> | ||||
|             (0 until it.mediaTrackGroup.length).mapNotNull { i -> | ||||
|                 if (it.isSupported) | ||||
|                     it.trackGroup.getFormat(i) // to it.isSelected | ||||
|                     it.mediaTrackGroup.getFormat(i) to i | ||||
|                 else null | ||||
|             } | ||||
|         }.flatten() | ||||
|  | @ -270,11 +328,12 @@ class CS3IPlayer : IPlayer { | |||
|     } | ||||
| 
 | ||||
|     override fun getVideoTracks(): CurrentTracks { | ||||
|         val allTracks = exoPlayer?.currentTracksInfo?.trackGroupInfos ?: emptyList() | ||||
|         val videoTracks = allTracks.filter { it.trackType == TRACK_TYPE_VIDEO }.getFormats() | ||||
|             .map { it.toVideoTrack() } | ||||
|         val audioTracks = allTracks.filter { it.trackType == TRACK_TYPE_AUDIO }.getFormats() | ||||
|             .map { it.toAudioTrack() } | ||||
|         val allTracks = exoPlayer?.currentTracks?.groups ?: emptyList() | ||||
|         val videoTracks = allTracks.filter { it.type == TRACK_TYPE_VIDEO } | ||||
|             .getFormats() | ||||
|             .map { it.first.toVideoTrack() } | ||||
|         val audioTracks = allTracks.filter { it.type == TRACK_TYPE_AUDIO }.getFormats() | ||||
|             .map { it.first.toAudioTrack() } | ||||
| 
 | ||||
|         return CurrentTracks( | ||||
|             exoPlayer?.videoFormat?.toVideoTrack(), | ||||
|  | @ -611,7 +670,12 @@ class CS3IPlayer : IPlayer { | |||
|                             } else it | ||||
|                         }.toTypedArray() | ||||
|                     } | ||||
|                     .setTrackSelector(trackSelector ?: getTrackSelector(context, maxVideoHeight)) | ||||
|                     .setTrackSelector( | ||||
|                         trackSelector ?: getTrackSelector( | ||||
|                             context, | ||||
|                             maxVideoHeight | ||||
|                         ) | ||||
|                     ) | ||||
|                     .setLoadControl( | ||||
|                         DefaultLoadControl.Builder() | ||||
|                             .setTargetBufferBytes( | ||||
|  | @ -781,10 +845,7 @@ class CS3IPlayer : IPlayer { | |||
|                 isPlaying = exo.isPlaying | ||||
|             } | ||||
|             exoPlayer?.addListener(object : Player.Listener { | ||||
|                 /** | ||||
|                  * Records the current used subtitle/track. Needed as exoplayer seems to have loose track language selection. | ||||
|                  * */ | ||||
|                 override fun onTracksInfoChanged(tracksInfo: TracksInfo) { | ||||
|                 override fun onTracksChanged(tracks: Tracks) { | ||||
|                     fun Format.isSubtitle(): Boolean { | ||||
|                         return this.sampleMimeType?.contains("video/") == false && | ||||
|                                 this.sampleMimeType?.contains("audio/") == false | ||||
|  | @ -792,17 +853,17 @@ class CS3IPlayer : IPlayer { | |||
| 
 | ||||
|                     normalSafeApiCall { | ||||
|                         exoPlayerSelectedTracks = | ||||
|                             tracksInfo.trackGroupInfos.mapNotNull { | ||||
|                                 val format = it.trackGroup.getFormat(0) | ||||
|                             tracks.groups.mapNotNull { | ||||
|                                 val format = it.mediaTrackGroup.getFormat(0) | ||||
|                                 if (format.isSubtitle()) | ||||
|                                     format.language?.let { lang -> lang to it.isSelected } | ||||
|                                 else null | ||||
|                             } | ||||
| 
 | ||||
|                         val exoPlayerReportedTracks = tracksInfo.trackGroupInfos.mapNotNull { | ||||
|                         val exoPlayerReportedTracks = tracks.groups.mapNotNull { | ||||
|                             // Filter out unsupported tracks | ||||
|                             if (it.isSupported) | ||||
|                                 it.trackGroup.getFormat(0) | ||||
|                                 it.mediaTrackGroup.getFormat(0) | ||||
|                             else | ||||
|                                 null | ||||
|                         }.mapNotNull { | ||||
|  | @ -827,7 +888,6 @@ class CS3IPlayer : IPlayer { | |||
|                         onTracksInfoChanged?.invoke() | ||||
|                         subtitlesUpdates?.invoke() | ||||
|                     } | ||||
|                     super.onTracksInfoChanged(tracksInfo) | ||||
|                 } | ||||
| 
 | ||||
|                 override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { | ||||
|  |  | |||
|  | @ -796,15 +796,16 @@ class GeneratorPlayer : FullScreenPlayer() { | |||
|                 } | ||||
| 
 | ||||
|                 tracksDialog.apply_btt?.setOnClickListener { | ||||
|                     val currentTrack = currentAudioTracks.getOrNull(audioIndexStart) | ||||
|                     player.setPreferredAudioTrack( | ||||
|                         currentAudioTracks.getOrNull(audioIndexStart)?.language | ||||
|                         currentTrack?.language, currentTrack?.id | ||||
|                     ) | ||||
| 
 | ||||
|                     val currentVideo = currentVideoTracks.getOrNull(videoIndex) | ||||
|                     val width = currentVideo?.width ?: NO_VALUE | ||||
|                     val height = currentVideo?.height ?: NO_VALUE | ||||
|                     if (width != NO_VALUE && height != NO_VALUE) { | ||||
|                         player.setMaxVideoSize(width, height) | ||||
|                         player.setMaxVideoSize(width, height, currentVideo?.id) | ||||
|                     } | ||||
| 
 | ||||
|                     tracksDialog.dismissSafe(activity) | ||||
|  |  | |||
|  | @ -161,9 +161,9 @@ interface IPlayer { | |||
| 
 | ||||
|     fun getVideoTracks(): CurrentTracks | ||||
| 
 | ||||
|     /** If no parameters are set it'll default to no set size */ | ||||
|     fun setMaxVideoSize(width: Int = Int.MAX_VALUE, height: Int = Int.MAX_VALUE) | ||||
|     /** If no parameters are set it'll default to no set size, Specifying the id allows for track overrides to force the player to pick the quality. */ | ||||
|     fun setMaxVideoSize(width: Int = Int.MAX_VALUE, height: Int = Int.MAX_VALUE, id: String? = null) | ||||
| 
 | ||||
|     /** If no trackLanguage is set it'll default to first track */ | ||||
|     fun setPreferredAudioTrack(trackLanguage: String?) | ||||
|     /** If no trackLanguage is set it'll default to first track. Specifying the id allows for track overrides as the language can be identical. */ | ||||
|     fun setPreferredAudioTrack(trackLanguage: String?, id: String? = null) | ||||
| } | ||||
|  | @ -75,7 +75,7 @@ open class NonFinalTextRenderer @JvmOverloads constructor( | |||
|         return TAG | ||||
|     } | ||||
| 
 | ||||
|     @RendererCapabilities.Capabilities | ||||
| //    @RendererCapabilities.Capabilities | ||||
|     override fun supportsFormat(format: Format): Int { | ||||
|         return if (decoderFactory.supportsFormat(format)) { | ||||
|             RendererCapabilities.create( | ||||
|  | @ -202,7 +202,8 @@ open class NonFinalTextRenderer @JvmOverloads constructor( | |||
|                     return | ||||
|                 } | ||||
|                 // Try and read the next subtitle from the source. | ||||
|                 @ReadDataResult val result = | ||||
| //                @ReadDataResult | ||||
|                 val result = | ||||
|                     readSource(formatHold, nextInputBuffer,  /* readFlags= */0) | ||||
|                 if (result == C.RESULT_BUFFER_READ) { | ||||
|                     if (nextInputBuffer.isEndOfStream) { | ||||
|  |  | |||
|  | @ -49,7 +49,7 @@ data class SaveCaptionStyle( | |||
|     @JsonProperty("foregroundColor") var foregroundColor: Int, | ||||
|     @JsonProperty("backgroundColor") var backgroundColor: Int, | ||||
|     @JsonProperty("windowColor") var windowColor: Int, | ||||
|     @CaptionStyleCompat.EdgeType | ||||
| //    @CaptionStyleCompat.EdgeType | ||||
|     @JsonProperty("edgeType") var edgeType: Int, | ||||
|     @JsonProperty("edgeColor") var edgeColor: Int, | ||||
|     @FontRes | ||||
|  |  | |||
|  | @ -20,10 +20,13 @@ class CastOptionsProvider : OptionsProvider { | |||
|             MediaIntentReceiver.ACTION_FORWARD, | ||||
|             MediaIntentReceiver.ACTION_STOP_CASTING | ||||
|         ) | ||||
| 
 | ||||
|         val name = ControllerActivity::class.qualifiedName!! | ||||
| 
 | ||||
|         val compatButtonAction = intArrayOf(1, 3) | ||||
|         val notificationOptions = | ||||
|             NotificationOptions.Builder() | ||||
|                 .setTargetActivityClassName(ControllerActivity::class.qualifiedName) | ||||
|                 .setTargetActivityClassName(name) | ||||
|                 .setActions(buttonActions, compatButtonAction) | ||||
|                 .setForward30DrawableResId(R.drawable.go_forward_30) | ||||
|                 .setRewind30DrawableResId(R.drawable.go_back_30) | ||||
|  | @ -32,7 +35,7 @@ class CastOptionsProvider : OptionsProvider { | |||
| 
 | ||||
|         val mediaOptions = CastMediaOptions.Builder() | ||||
|             .setNotificationOptions(notificationOptions) | ||||
|             .setExpandedControllerActivityClassName(ControllerActivity::class.qualifiedName) | ||||
|             .setExpandedControllerActivityClassName(name) | ||||
|             .build() | ||||
| 
 | ||||
|         return CastOptions.Builder() | ||||
|  | @ -44,7 +47,7 @@ class CastOptionsProvider : OptionsProvider { | |||
|             .build() | ||||
|     } | ||||
| 
 | ||||
|     override fun getAdditionalSessionProviders(p0: Context?): MutableList<SessionProvider> { | ||||
|     override fun getAdditionalSessionProviders(p0: Context): MutableList<SessionProvider> { | ||||
|         return Collections.emptyList() | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue